C++-Programm

(nur Funktionen)


#include "tsp.hpp"

#include <time.h>

#include <assert.h>

#include <stdlib.h>

#define BOOL int

/***************************************************************************/

/* Parameter fuer Genetische Algorithmen */

static int PopulGroesse = 200; // Populationsgroesse

static int ReproRate = 18; // Reproduktionsrate (9%)

static int MutatRate = 2; // Mutationsrate (1%)

static int CORate = 120; // CrossOverRate (60%)

static int SelRate = 60; // Selektionsrate (30%) = Die ... Besten

/***************************************************************************/

/* Ein Chromosom mit zufaelligen Werten von 0.00 - 0.99 initialisieren. */

/* Parameter : Laenge des Chromosoms, das Chromosom (Ref.Par.) */

/* Funktionswert : keiner */

void InitChromosom(int ChrLaenge, CHROMOSOM & Chromo) {

for (int i=1; i<=ChrLaenge; i++) {

REAL ZufZahl;

// Zufallszahl erzeugen zwischen 0.00 und 0.99

ZufZahl=(float)rand()/(float)RAND_MAX;

// Zahl an das Chromosom anhaengen

Chromo.appr(ZufZahl);

}

}

/***************************************************************************/

/* Anfangspopulation fuer die genetischen Algorithmen initialisieren. */

/* Parameter : Laenge der Chromosome, Population (Ref.Par.) */

/* Funktionswert : keiner */

void InitPopulation(int ChrLaenge, POPULATION & Popul) {

for (int i=1; i<=PopulGroesse; i++) {

CHROMOSOM Chromo(empty);

// Ein Chromosom herstellen

InitChromosom(ChrLaenge, Chromo);

// Chromosom an die Population anhaengen

Popul.appr(Chromo);

}

}

/***************************************************************************/

/* Aus dem Chromosom den Weg berechnen = Sortierung der Gene ermitteln. */

/* Parameter : Das Chromosom, Laenge des Chromosom, Loesungsweg (Point.) */

/* Funktionswert : keiner */

void CalcPath(const CHROMOSOM & Chromo, int ChrLaenge, int* Loesung) {

BOOL* Taken; // Feld: Gen ausgewertet(J/N) ?

REAL Kleinster; // Kleinster Wert im Chromosom

unsigned int KleinstePos; // Pos. des kleinsten Wertes im Chromosom

int i; // Laufvariable

// Speicher fuer BOOLVektor alloziieren und Vektor initialisieren

Taken=new BOOL[ChrLaenge];

assert(Taken!=0);

for (i=0; i<ChrLaenge; i++) Taken[i]=FALSE;

for (i=0; i<ChrLaenge; i++) {

// Kleinster mit Wert groesser als alle Gene (max. 1.0) initialisieren

Kleinster=1.5;

// Chromosom durchlaufen und kleinstes Gen suchen

for (int j=1; j<=ChrLaenge; j++) {

if (Chromo.sel(j)<Kleinster && Taken[j-1]==FALSE) {

Kleinster=Chromo.sel(j);

KleinstePos=j;

}

}

// Reiseziel festlegen

Loesung[i]=KleinstePos;

// Bereits gewaehltes Gen blockieren

Taken[KleinstePos-1]=TRUE;

}

delete [] Taken;

}

/***************************************************************************/

/* Entfernungsmatrix mit den Entfernungswerten initialisieren. */

/* Parameter : String mit allen Werten (P), Entfernungsmatrix (RP) */

/* Funktionswert : Dimension der Matrix = Startpunkt der Reise */

int InitTable(char* Uebergabe, ZEILE & Tabelle) {

int i=0;

int Anzahl;

REAL entfernung;

float input;

// Datum Nr.1 lesen = Dimension der Entfernungsmatrix = Startpunkt

while (Uebergabe[i]!=' ') i++;

sscanf(Uebergabe,"%d",&Anzahl);

// Daten Nr.2 bis Nr.(Anzahl^2+1) lesen = Daten der Entfernungsmatrix

for (int j=1; j<=Anzahl; j++) {

SPALTE spalte(empty);

for (int k=1; k<=Anzahl; k++) {

// Zeiger zum naechsten Datum setzen

Uebergabe=Uebergabe+(i+1);

i=0;

// Nur weiterlaufen, wenn nicht letztes Element

if ( ! (j==Anzahl && k==Anzahl))

while (Uebergabe[i]!=' ') i++;

// Datum lesen und in die Matrix eintragen

sscanf(Uebergabe,"%f",&input);

entfernung=input;

spalte.appr(entfernung);

}

Tabelle.appr(spalte);

}

return Anzahl;

}

/***************************************************************************/

/* Laenge des ausgewaehlten Pfades anhand der Entfernungsmatrix berechnen. */

/* Parameter : Laenge des Chromosoms, Loesungsvektor (P), */

/* Entfernungsmatrix, Startpunkt der Reise */

/* Funktionswert : Laenge der Reise */

float CalcLength(int ChrLaenge, int* Loesung, const ZEILE & Tabelle,

int Start) {

float result=0; // Ergebnis der Weglaengenberechnungen

SPALTE spalte(empty); // Hilfsvariable

REAL erg; // Hilfsvariable

int i; // Laufvariable

// Vom Start zum ersten Punkt

spalte=Tabelle.sel(Start);

erg=spalte.sel(Loesung[0]);

result+=erg.cv_real();

// Vom ersten bis zum letzten Punkt

for (i=1; i<ChrLaenge; i++) {

spalte=Tabelle.sel(Loesung[i-1]);

erg=spalte.sel(Loesung[i]);

result+=erg.cv_real();

}

// Vom letzten Punkt zum Start zurueck

spalte=Tabelle.sel(Loesung[i-1]);

erg=spalte.sel(Start);

result+=erg.cv_real();

return result;

}

/***************************************************************************/

/* Das beste Chromosom bzgl. Weglaenge aus der Population suchen. */

/* Parameter : Population, Chromosomenlaenge, Entfernungsmatrix, */

/* Startpunkt, Das beste Chromosom */

/* Funktionswert : Index des besten Chromosom */

CHROMOSOM GetBest(const POPULATION & Popul, int ChrLaenge,

const ZEILE & Tabelle, int Start) {

CHROMOSOM BestChr(empty); // Bestes Chromosom

float BestWay,ZwErg; // Kuerzester Reiseweg + Zwischenergebnis

int* Loesung; // Loesungsvektor

// Speicher fuer Loesungsvektor alloziieren

Loesung=new int[ChrLaenge];

assert(Loesung!=0);

// Erstes Chromosom als Bestes festlegen

BestChr=Popul.sel(1);

CalcPath(BestChr,ChrLaenge,Loesung);

// Weg berechnen

BestWay=CalcLength(ChrLaenge,Loesung,Tabelle,Start);

// Die weiteren Chromosome der Population durchlaufen,

// ueberprufen, ob besser und bestes Chromosom evtl. ersetzen

for (int i=2; i<=Popul.len().cv_nat0(); i++) {

CalcPath(Popul.sel(i),ChrLaenge,Loesung);

ZwErg=CalcLength(ChrLaenge,Loesung,Tabelle,Start);

if (ZwErg<BestWay) {

BestWay=ZwErg;

BestChr=Popul.sel(i);

}

}

delete [] Loesung;

return BestChr;

}

/***************************************************************************/

/* Loesungvektor fuer Tcl/Tk in String konvertieren */

/* Parameter : Loesungsstring (P), Loesungsvektor (P), */

/* Chromosomenlaenge, Weglaenge */

/* Funktionswert : keiner */

void LoesungToString(char* String, int* Loesung, int ChrLaenge, float Laenge){

char* pAnfang; // Merkzeiger

// Weglaenge in den String schreiben

sprintf(String,"%f",Laenge);

strcat(String," ");

pAnfang=String;

// Die anzufahrenden Punkte in richtiger Reihenfolge in den String schreiben

for (int i=0; i<ChrLaenge; i++) {

String+=strlen(String);

sprintf(String,"%d",Loesung[i]);

strcat(String," ");

}

// Zeiger zurueck auf den Stringanfang setzen

String=pAnfang;

}

/***************************************************************************/

/* Zufaellige Auswahl eines Chromosoms fuer die Vererbungsmechanismen. */

/* Prinzip: - Zwei Chromsomen zufaellig auswaehlen */

/* - Chromosom mit besserer Fitness wird zurueckgeliefert */

/* Parameter : Population, Chromosomenlaenge, Entf.Matrix, Startpunkt */

/* Funktionswert : Das Chromosom */

CHROMOSOM SelectChromo(const POPULATION & Popul, int ChrLaenge,

const ZEILE & Tabelle, int Start) {

unsigned int Zuffi_1,Zuffi_2;

POPULATION HilfsPop(empty);

do {

Zuffi_1=(rand()%PopulGroesse)+1;

Zuffi_2=(rand()%PopulGroesse)+1;

}

while (Zuffi_1==Zuffi_2);

HilfsPop.appr(Popul.sel(Zuffi_1));

HilfsPop.appr(Popul.sel(Zuffi_2));

return GetBest(HilfsPop,ChrLaenge,Tabelle,Start);

}

/***************************************************************************/

/* Ein Verebungsschritt durchfuehren ==> Neue Population erzeugen. */

/* Parameter : Population, Chromosomenlaenge, Entfernungsmatrix, Startpt. */

/* Funktionswert : Die neue Population */

POPULATION Vererbung(POPULATION Popul, int ChrLaenge,

const ZEILE & Tabelle, int Start) {

POPULATION PopulNeu(empty); // Neue Population

// Chromosomen fuer Auswahl

CHROMOSOM Chromo(empty), Chromo_1(empty), Chromo_2(empty);

unsigned int iZuffi; // Zufallszahlen

REAL rZuffi; // -"-

int i; // Laufvariable

FITNESS Fit(empty); // Fitnessfeld

REAL FitWert; // Fitnesswert

int *Loesung; // Loesungsvektor

unsigned int Index; // Hilfsindex

// Fitness fuer alle Chromosomen berechnen und speichern

Loesung=new int[ChrLaenge];

assert(Loesung!=0);

for (i=1; i<=PopulGroesse; i++) {

CalcPath(Popul.sel(i),ChrLaenge,Loesung);

FitWert=CalcLength(ChrLaenge,Loesung,Tabelle,Start);

Fit.appr(FitWert);

}

delete [] Loesung;

// Reproduktion

for (i=1; i<=ReproRate; i++) {

// Chromosom einfach anhaengen

PopulNeu.appr(SelectChromo(Popul,ChrLaenge,Tabelle,Start));

}

// Mutation

for (i=1; i<=MutatRate; i++) {

// Chromosom auswaehlen

Chromo=SelectChromo(Popul,ChrLaenge,Tabelle,Start);

// Gen fuer die Mutation per Zufall bestimmen

iZuffi=(rand()%ChrLaenge)+1;

// Neuen Wert fuer Gen per Zufall bestimmen

rZuffi=(float)rand()/(float)RAND_MAX;

Chromo.ovwrt1(iZuffi,rZuffi);

PopulNeu.appr(Chromo);

}

// Crossover

for (i=1; i<=CORate; i++) {

// Chromosom 1 bestimmen

Chromo_1=SelectChromo(Popul,ChrLaenge,Tabelle,Start);

// Chromosom 2 bestimmen

Chromo_2=SelectChromo(Popul,ChrLaenge,Tabelle,Start);

// (Keine Ueberpruefung, ob zweimal das gleiche Chromosom gewaehlt wird,

// da unwahrscheinlich und erheblicher Overhead.)

// Start-Gen fuer Crossover per Zufall bestimmen

// Bed.: 3 <= Gen <= ChrLaenge-1, da sonst Reproduktion bzw. Mutation

iZuffi=(rand()%ChrLaenge)+1;

Chromo=Chromo_1.sub_tup(1,iZuffi)

+Chromo_2.sub_tup(iZuffi+1,ChrLaenge);

PopulNeu.appr(Chromo);

}

// Selektion

for (i=1; i<=SelRate; i++) {

Index=1;

FitWert=Fit.sel(1);

for (int j=2; j<=Fit.len().cv_nat0(); j++) {

if (Fit.sel(j)<FitWert) {

Index=j;

FitWert=Fit.sel(j);

}

}

PopulNeu.appr(Popul.sel(Index));

Popul.rmv1(Index);

Fit.rmv1(Index);

}

return PopulNeu;

}