我目前正在编写模拟退火代码来解决旅行商问题,并且在存储和使用来自txt文件的读取数据时遇到了困难.文件中的每一行和每列代表每个城市,两个不同城市之间的距离存储为15 x 15矩阵:
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
为了阅读本文,我有一个LoadCities()函数,如下所示:
#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(); }
我已经尝试了一种替代的istreambuf_iterator方法,以便将读取材料操作到数组中,但是我似乎总是遇到并发症:
ifstream CityFile("Cities.txt"); string theString((std::istreambuf_iterator(CityFile)), std::istreambuf_iterator ());
任何帮助都会很有帮助.一直在抨击我,但收效甚微!
################编辑/更新@ SoapBox - SA代码,函数和main()的一些细节.这不是干净,高效,整洁,并不是现阶段的工作,只需要暂时工作.此版本(下面)工作并设置为解决多项式(最简单的问题).将其转换为旅行商问题需要做的是:
编写LoadCities()函数以收集距离数据.(当前)
更改Initialise()以获取所涉及的距离总和
将E()更改为TSP函数(例如,计算随机路径的距离)
后两个我知道我可以做,但是我需要LoadCities()来做.以下脚本中无需更改任何其他内容.
#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 - 我知道它的代码很糟糕,但不幸的是,我的项目所涉及的时间限制和组合学习曲线,结果都是需要的!:)它将在后期阶段进行整理.
@dirkgently - 这是这样做的最初原因,因此我的第一次尝试就是这样做.
这个怎么样?(KISS解决方案)
void LoadCities() { int x, y; ifstream in("Cities.txt"); if (!in) { cout << "Cannot open file.\n"; return; } for (y = 0; y < 15; y++) { for (x = 0; x < 15; x++) { in >> distances[x][y]; } } in.close(); }
适合我.可能不是那么复杂,也许不是很高效,但只要你不读1000x1000阵列,你就不会看到任何差别.