質問
私は現在、書面による模擬アニールコードを解決する巡回セールスマン問題に対する、走る困難を保管を使ってからデータを読み込むための、txtファイルです。各行&カラムのファイルは各都市との間の距離の異なる二つの都市として格納され15×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<char>(CityFile)), std::istreambuf_iterator<char>());
手いと言うことができる。appriciated.していたたきっこう少ない。
################ 編集-更新@SoapBox-細かなディテールのSAコード、機能、メイン().これは、クリーンで効率的な夫婦でなくなるのではないだトすることでニーズに。このバージョン(下記および設定を解く多項式(単純な問題があります)。何をすべきかに変換する巡回セールスマン問題に対するには:
記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-さんその悪いコードがunfortunatlyの時間制約の関与のための私のプロジェクトのconsiquental学習曲線の結果は何をしています。:)になるでしょう勧めで後ます。
@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();
}
私のために動作します。複雑で、おそらく非常にパフォーマンスではないことはないかもしれませんが、限り、あなたは1000×1000の配列を読んでいないとして、あなたはどんな違いが表示されません。
他のヒント
あなたは、おそらくこのようなシンプルなものを、欲しいです
std::vector<std::vector<std::string> > LoadCities(const std::string &filename)
{
using namespace std;
ifstream file;
file.open(filename, ios::in | ios::out);
if(!file.is_open()) {
// error
return vector<vector<double> >();
}
vector<vector<double> > data;
string line;
while(!std::getline(file, line, '\n').eof()) {
istringstream reader(line);
vector<double> lineData;
string::const_iterator i = line.begin();
while(!reader.eof()) {
double val;
reader << val;
if(reader.fail())
break;
lineData.push_back(val);
}
data.push_back(lineData);
}
return data;
}
は、基本的には、入力したデータをストリームを使用します。私はおそらく何か間違ったことをやっている(私は入出力ストリームを扱ったことがない; P)が、これはあなたの行列リーダーを構築する方法の一般的なアイデアを与える必要があります。
。それも、コンパイルしていますか?私は〜7つのエラーが発生します。サンプルます:
strtok(cities, "\n");
strtok()
の最初の引数はchar *
とないのstd ::文字列です。
このヘルプをしていますか?
void LoadCities()
{
std::vector<double> f((std::istream_iterator<double>
(std::ifstream("city.txt"))), /* replace filename with your own */
(std::istream_iterator<double>()));
if (!f.empty()) {
std::cout << f.size() << "\n";
/* print an arbitrary data point with 2 places of decimal */
std::cout << std::setprecision(2) << f[ 0 ] << std::endl;
}
}
行列で作業すると、多次元配列を持っている必要が意味するものではありません。特に、2Dアレイを有します。もちろん、それは読み取りと書き込みが容易になります。)
ここで私はそれを保存/ロードする方法を次のとおりです。
#include <iostream>
#include <fstream>
#include <string>
int width = 0;
int height = 0;
double **distances;
void WriteDouble( std::ofstream &stream, double toWrite )
{
char buffer[8];
memcpy( buffer, &toWrite, 8 );
stream.write( buffer, 8 );
}
void WriteInt( std::ofstream &stream, int toWrite )
{
char buffer[4];
memcpy( buffer, &toWrite, 4 );
stream.write( buffer, 4 );
}
double ReadDouble( std::ifstream &stream )
{
double d = 0;
stream.read( (char *)&d, 8 );
return d;
}
int ReadInt( std::ifstream &stream )
{
int i = 0;
stream.read( (char *)&i, 4 );
return i;
}
void Save()
{
std::ofstream stream( "cities", std::ios::out | std::ios::binary );
if( !stream.good() ) {
throw std::exception( "Error opening stream" );
}
WriteInt( stream, width );
WriteInt( stream, height );
for( int x = 0; x < width; x++ ) {
for( int y = 0; y < height; y++ ) {
WriteDouble( stream, distances[x][y] );
}
}
stream.close();
}
void Load()
{
std::ifstream stream( "cities", std::ios::in | std::ios::binary );
if( !stream.good() ) {
throw std::exception( "Error opening stream" );
}
width = ReadInt( stream );
height = ReadInt( stream );
distances = new double *[width];
for( int i = 0; i < width; i++ ) {
distances[i] = new double[height];
}
for( int x = 0; x < width; x++ ) {
for( int y = 0; y < height; y++ ) {
distances[x][y] = ReadDouble( stream );
}
}
stream.close();
}
void RunSaveTest()
{
width = 15;
height = 15;
distances = new double *[width];
for( int i = 0; i < width; i++ ) {
distances[i] = new double[height];
}
for( int x = 0; x < width; x++ ) {
for( int y = 0; y < height; y++ ) {
distances[x][y] = (double)x / (double)( y + 1 );
std::cout << distances[x][y] << std::endl;
}
}
Save();
}
void RunLoadTest()
{
Load();
for( int x = 0; x < width; x++ ) {
for( int y = 0; y < height; y++ ) {
std::cout << distances[x][y] << std::endl;
}
}
}
int main()
{
RunSaveTest();
// RunLoadTest();
return 0;
}
参考から私のこのブログ: http://www.topbug.net/blog/2013/01/10/load-a-matrix-from-an-ascii-format-file/
このコードスニペットの高い耐障害性なくともも。
#include <istream>
#include <string>
#include <sstream>
#include <vector>
// load matrix from an ascii text file.
void load_matrix(std::istream* is,
std::vector< std::vector<double> >* matrix,
const std::string& delim = " \t")
{
using namespace std;
string line;
string strnum;
// clear first
matrix->clear();
// parse line by line
while (getline(*is, line))
{
matrix->push_back(vector<double>());
for (string::const_iterator i = line.begin(); i != line.end(); ++ i)
{
// If i is not a delim, then append it to strnum
if (delim.find(*i) == string::npos)
{
strnum += *i;
if (i + 1 != line.end()) // If it's the last char, do not continue
continue;
}
// if strnum is still empty, it means the previous char is also a
// delim (several delims appear together). Ignore this char.
if (strnum.empty())
continue;
// If we reach here, we got a number. Convert it to double.
double number;
istringstream(strnum) >> number;
matrix->back().push_back(number);
strnum.clear();
}
}
}
// example
#include <fstream>
#include <iostream>
int main()
{
using namespace std;
// read the file
std::ifstream is("input.txt");
// load the matrix
std::vector< std::vector<double> > matrix;
load_matrix(&is, &matrix);
// print out the matrix
cout << "The matrix is:" << endl;
for (std::vector< std::vector<double> >::const_iterator it = matrix.begin(); it != matrix.end(); ++ it)
{
for (std::vector<double>::const_iterator itit = it->begin(); itit != it->end(); ++ itit)
cout << *itit << '\t';
cout << endl;
}
return 0;
}