Ich schreibe gerade einen Simulated Annealing-Code, um das Problem eines reisenden Verkäufers zu lösen, und habe Schwierigkeiten mit dem Speichern und Verwenden meiner gelesenen Daten aus einer TXT-Datei. Jede Zeile & Spalte in der Datei repräsentiert jede Stadt, wobei der Abstand zwischen zwei verschiedenen Städten als Matrix 15 x 15 gespeichert:Eine Matrix-TXT-Datei lesen und als Array speichern
0.0 5.0 5.0 6.0 7.0 2.0 5.0 2.0 1.0 5.0 5.0 1.0 2.0 7.1 5.0
5.0 0.0 5.0 5.0 5.0 2.0 5.0 1.0 5.0 6.0 6.0 6.0 6.0 1.0 7.1
5.0 5.0 0.0 6.0 1.0 6.0 5.0 5.0 1.0 6.0 5.0 7.0 1.0 5.0 6.0
6.0 5.0 6.0 0.0 5.0 2.0 1.0 6.0 5.0 6.0 2.0 1.0 2.0 1.0 5.0
7.0 5.0 1.0 5.0 0.0 7.0 1.0 1.0 2.0 1.0 5.0 6.0 2.0 2.0 5.0
2.0 2.0 6.0 2.0 7.0 0.0 5.0 5.0 6.0 5.0 2.0 5.0 1.0 2.0 5.0
5.0 5.0 5.0 1.0 1.0 5.0 0.0 2.0 6.0 1.0 5.0 7.0 5.0 1.0 6.0
2.0 1.0 5.0 6.0 1.0 5.0 2.0 0.0 7.0 6.0 2.0 1.0 1.0 5.0 2.0
1.0 5.0 1.0 5.0 2.0 6.0 6.0 7.0 0.0 5.0 5.0 5.0 1.0 6.0 6.0
5.0 6.0 6.0 6.0 1.0 5.0 1.0 6.0 5.0 0.0 7.0 1.0 2.0 5.0 2.0
5.0 6.0 5.0 2.0 5.0 2.0 5.0 2.0 5.0 7.0 0.0 2.0 1.0 2.0 1.0
1.0 6.0 7.0 1.0 6.0 5.0 7.0 1.0 5.0 1.0 2.0 0.0 5.0 6.0 5.0
2.0 6.0 1.0 2.0 2.0 1.0 5.0 1.0 1.0 2.0 1.0 5.0 0.0 7.0 6.0
7.0 1.0 5.0 1.0 2.0 2.0 1.0 5.0 6.0 5.0 2.0 6.0 7.0 0.0 5.0
5.0 7.0 6.0 5.0 5.0 5.0 6.0 2.0 6.0 2.0 1.0 5.0 6.0 5.0 0.0
dies zu lesen Ich habe ein LoadCities() Funktion, wie unten gezeigt:
#include "iostream"
#include "fstream"
#include "string"
using namespace std;
double distances [15][15];
void LoadCities()
{
ifstream CityFile;
if (!CityFile.is_open()) //check is file has been opened
{
CityFile.open ("Cities.txt", ios::in | ios::out);
if (!CityFile)
{
cerr << "Failed to open " << CityFile << endl;
exit(EXIT_FAILURE); //abort program
}
}
int length;
char * buffer;
string cities;
CityFile.seekg(0, ios::end);
length = CityFile.tellg();
CityFile.seekg (0, ios::beg);
buffer = new char [length];
cities = CityFile.read (buffer,length);
string rows = strtok(cities, "\n");
distances = new double[rows.length()][rows.length()];
for (int i = 0; i < (string) rows.length(); i++)
{
string distance = strtok(rows[i], " ");
for (int j = 0; j < distance.length(); j++)
{
distances[i][j] = (double) Parse(distance[j]);
}
}
CityFile.close();
}
ich habe eine alternative istreambuf_iterator Methode, um zu dem Punkt der Manipulation des Lesematerials in Arrays versucht, aber ich scheine immer in Komplikationen führen:
ifstream CityFile("Cities.txt");
string theString((std::istreambuf_iterator<char>(CityFile)), std::istreambuf_iterator<char>());
Jede Hilfe wäre sehr geschätzt. Ich habe meinen Kopf mit wenig Erfolg dagegengestoßen!
################ EDIT/Update@ SoapBox - Einige Details der SA-Code, Funktionen und main(). Dies ist nicht sauber, effizient, sauber und nicht in diesem Stadium, sondern muss nur für den Moment arbeiten. Diese Version (unten) funktioniert und ist eingerichtet, um Polynome zu lösen (einfachste Probleme). Was muss getan werden, um wandelt es in ein Reiseproblem ist:
die LoadCities Write() Funktion, um die Entfernungsdaten zu sammeln. (Current)
ändern Initialise() die Summe der Entfernungen zu bekommen beteiligt
ändern E() an die TSP-Funktion (zB Berechnen Entfernung einer Random-Route)
Die Letzten zwei, ich weiß, ich kann tun, aber ich brauche LoadCities(), um es zu tun. Im folgenden Skript muss nichts anderes geändert werden.
#include "math.h"
#include "iostream"
#include "fstream"
#include "time.h" // Define time()
#include "stdio.h" // Define printf()
#include "randomc.h" // Define classes for random number generators
#include "mersenne.cpp" // Include code for the chosen random number generator
using namespace std; // For the use of text generation in application
double T;
double T_initial;
double S;
double S_initial;
double S_current;
double S_trial;
double E_current;
int N_step; // Number of Iterations for State Search per Temperature
int N_max; //Number of Iterations for Temperature
int Write;
const double EXP = 2.718281828;
//------------------------------------------------------------------------------
//Problem Function of Primary Variable (Debugged 17/02/09 - Works as intended)
double E(double x) //ORIGNINAL
{
double y = x*x - 6*x + 2;
return y;
}
//------------------------------------------------------------------------------
//Random Number Generation Function (Mod 19/02/09 - Generated integers only & fixed sequence)
double Random_Number_Generator(double nHigh, double nLow)
{
int seed = (int)time(0); // Random seed
CRandomMersenne RanGen(seed); // Make instance of random number generator
double fr; // Random floating point number
fr = ((RanGen.Random() * (nHigh - nLow)) + nLow); // Generatres Random Interger between nLow & nHigh
return fr;
}
//------------------------------------------------------------------------------
//Initializing Function (Temp 17/02/09)
void Initialize() //E.g. Getting total Distance between Cities
{
S_initial = Random_Number_Generator(10, -10);
cout << "S_Initial: " << S_initial << endl;
}
//------------------------------------------------------------------------------
//Cooling Schedule Function (make variables) (Completed 16/02/09)
double Schedule(double Temp, int i) // Need to find cooling schedule
{
double CoolingRate = 0.9999;
return Temp *= CoolingRate;
}
//------------------------------------------------------------------------------
//Next State Function (Mod 18/02/09)
double Next_State(double T_current, int i)
{
S_trial = Random_Number_Generator(pow(3, 0.5), pow(3, 0.5)*-1);
S_trial += S_current;
double E_t = E(S_trial);
double E_c = E(S_current);
double deltaE = E_t - E_c; //Defines gradient of movement
if (deltaE <= 0) //Downhill
{
S_current = S_trial;
E_current = E_t;
}
else //Uphill
{
double R = Random_Number_Generator(1,0); //pseudo random number generated
double Ratio = 1-(float)i/(float)N_max; //Control Parameter Convergence to 0
double ctrl_pram = pow(EXP, (-deltaE/T_current)); //Control Parameter
if (R < ctrl_pram*Ratio) //Checking
{
S_current = S_trial; //Expresses probability of uphill acceptance
E_current = E_t;
}
else
E_current = E_c;
}
return S_current;
}
//------------------------------------------------------------------------------
//Metropolis Function (Mod 18/02/09)
double Metropolis(double S_start, double T_current, int N_Steps, int N_temperatures)
{
S_current = S_start; //Initialised S_initial equated to S_current
for (int i=1; i <= N_step; i++) //Iteration of neighbour states
S_current = Next_State(T_current, N_temperatures); //Determines acceptance of new states
return S_current;
}
//------------------------------------------------------------------------------
//Write Results to Notepad (Completed 18/02/09)
void WriteResults(double i, double T, double x, double y)
{
//This function opens a results file (if not already opened)
//and stores results for one time step
static ofstream OutputFile;
const int MAXLENGTH = 80;
if (!OutputFile.is_open()) //check is file has been opened
{
//no it hasn't. Get a file name and open it.
char FileName[MAXLENGTH];
//read file name
cout << "Enter file name: ";
do
{
cin.getline(FileName, MAXLENGTH);
}
while (strlen(FileName) <= 0); //try again if length of string is 0
//open file
OutputFile.open(FileName);
// check if file was opened successfully
if (!OutputFile)
{
cerr << "Failed to open " << FileName << endl;
exit(EXIT_FAILURE); //abort program
}
OutputFile << "Iterations" << '\t' << "Temperatures" << '\t' << "X-Value" << '\t' << "Y-Value" << endl;
OutputFile << endl;
}
//OutputFile.width(10);
OutputFile << i << '\t' << T << '\t' << x << '\t' << y << endl;
if (i == N_max)
{
OutputFile << endl
<< "Settings: " << endl
<< "Initial Temperature: " << T_initial << endl
<< "Temperature Iterations: " << N_max << endl
<< "Step Iterations: " << N_step << endl
<< endl
<< "Results: " << endl
<< "Final Temperature: " << T << endl
<< "Minimum: " << S << endl;
OutputFile.close();
}
}
//------------------------------------------------------------------------------
//Main SA Function (Mod 17/02/09)
void SA(int W)
{
S = S_initial;
T = T_initial;
for (int N_temperatures = 1 ; N_temperatures <= N_max ; N_temperatures++)
{
S = Metropolis(S, T, N_step, N_temperatures);
T = Schedule(T, N_temperatures);
if (W == 1)
WriteResults(N_temperatures, T, S, E_current);
}
cout << "Result" << endl
<< "Y-value> " << S << endl
<< "Temperature> " << T << endl;
}
//------------------------------------------------------------------------------
//Execution of Traveling Salesman Problem (Progress 18/02/09)
int main()
{
cout << "Quadratic Function" << endl
<< "Solving method: Simulated Annealing" << endl;
cout << "" << endl;
cout << "Select desired Initial Temperature:" << endl
<< "> ";
cin >> T_initial;
cout << "Select desired number of Temperature Iterations:" << endl
<< "> ";
cin >> N_max;
cout << "Select desired number of step Iterations:" << endl
<< "> ";
cin >> N_step;
Initialize();
cout << "Write to file: (1/0) " << endl
<< "> ";
cin >> Write;
SA(Write);
system ("PAUSE");
return 0;
}
@ strager - ich seinen schlechten Code kennen, aber leider mit den Zeitbeschränkungen für mein Projekt beteiligt und die consiquental Lernkurve, die Ergebnisse sind, was notwendig ist! :) Es wird in späteren Phasen aufgeräumt werden.
@ dirkentely - Das war der anfängliche Grund dafür, dies zu tun, und deshalb, warum mein erster Versuch ist es so zu gehen.
Ein wenig mehr Details darüber, was das Problem tatsächlich ist, können hilfreich sein. Du hast guten Code und viele Details geliefert, aber größtenteils weggelassen, was du eigentlich lösen willst. – SoapBox
Es ist kein guter Code ... er sollte nicht einmal kompilieren! Es gibt einige Probleme. Distanzen ist ein Doppel [15] [15], wird aber wie ein Zeiger zugewiesen. Die Datei wird geprüft, ob sie geöffnet wird, bevor etwas unternommen wurde. Er liest die gesamte Datei in einen Puffer ... usw. usw. – strager
@strager: Das Lesen der gesamten Datei in einem Puffer ist eine Optimierungstechnik. Viele Leute, die ich kenne, benutzen es beim Schreiben von Code für Programmierwettbewerbe;) – dirkgently