您的位置:首页 > 编程语言

《集体智慧编程》第5章一些问题

2015-08-12 16:15 267 查看
第五章的主题是优化,实际上就是求最优解,其中举了一个组团旅游的例子。代码运行了,但感觉结果有点问题,google了一下,无果,不知道是不是自己理解的问题,毕竟初学机器学习,也不会python,很多代码看不太懂。

第一,题目的意思是当天到LGA,然后当天返程,可是很多时候,返程航班的起飞时间甚至比到达LGA航班的时间还要更早???那怎么成立啊?不过这个问题和解题关系不大。

第二个问题,s=[1,4,3,2,7,3,6,3,2,4,5,3],这个序列的意思是,第一个人就是乘坐第2次航班去LGA,然后乘坐第5次航班返程,第二个人乘坐第4次航班去,乘坐第3次航班返程,以此类推,并且在字典中是航班是按从早到晚的起飞顺序排列的。可我比对了一下printschedule(s)这个函数的运行结果和schedule.txt(即生成字典的源文件)根本不相符啊???在程序中查看字典flights和schedule.txt一样啊!!也就是字典的载入没有问题。那是怎么回事呢?因为对python不熟悉,所以没有再深究代码了。

第三,闲来无事,把书上的代码翻译成C++,但是又有点问题了。~~~~(>_<)~~~~

struct Sflightdata
{
std::string strleavetime;
std::string strarrivetime;
int nprice;
};

struct SPeople
{
std::string name;
std::string leaveplace;
};

class CPreprocessor
{
public:
std::map<std::pair<std::string, std::string>, std::vector<Sflightdata>> flight;
void Read(const std::string& strInputFileName);
void SplitString(const std::string& s, std::vector<std::string>& v, const std::string& c);
void PutIntoMap(std::vector<std::string>& v);
int StringToInt(std::string& s);
int GetMinutes(std::string& s);
int ScheduleCost(int s[],SPeople p[],std::string& d);
void PrintSchedule(int s[],SPeople p[],std::string& d);
void RandomSearching(int s[], SPeople p[], std::string &d);
int GetRandomInt(int lower, int upper);
double GetRandomFloat();
void SimulatedAnnealing(int s[], SPeople p[], std::string &d);
};


std::map<std::pair<std::string, std::string>, std::vector<Sflightdata>> flight;
以出发地和目的地作为键,存储航班的各个起飞时间,到达时间和票价。

void Read(const std::string& strInputFileName);
从txt文件中读入

void SplitString(const std::string& s, std::vector<std::string>& v, const std::string& c);
将每一行中的信息提取

void PutIntoMap(std::vector<std::string>& v);
把每一行的信息放入字典中

int GetMinutes(std::string& s);
同书上getminutes函数的意思一样,将时间转化为分钟,便于比较和计算

int ScheduleCost(int s[],SPeople p[],std::string& d);
成本函数

void PrintSchedule(int s[],SPeople p[],std::string& d);
打印题解的具体信息

void RandomSearching(int s[], SPeople p[], std::string &d);
随机搜索算法

int GetRandomInt(int lower, int upper);
double GetRandomFloat();
得到随机数的函数,第一个是得到[lower,upper]之间的整数,第二个是得到01之间的小数

void SimulatedAnnealing(int s[], SPeople p[], std::string &d);
模拟退火算法

模拟退火算法出现了一点问题,成本始终很高,比随机搜索高,╮(╯▽╰)╭,不知道哪里出了问题。。贴个代码吧。
#include "preprocessor.h"
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <map>
#include<iomanip>
#include<ctime>
#include<Windows.h>
#include<math.h>

void CPreprocessor::Read(const std::string& strInputFileName)
{
std::fstream fs(strInputFileName);
std::string line;
std::vector<std::string> splitedline;
while (getline(fs, line))
{
SplitString(line, splitedline, ",");
PutIntoMap(splitedline);
splitedline.clear();
}
}

void CPreprocessor::PutIntoMap(std::vector<std::string>& v)
{
std::pair<std::string, std::string> p;
std::string first, last;
Sflightdata tmp;
first = v[0];
last = v[1];
p = make_pair(first, last);
tmp.strleavetime = v[2];
tmp.strarrivetime = v[3];
tmp.nprice = StringToInt(v[4]);
flight[p].push_back(tmp);
}

int CPreprocessor::StringToInt(std::string& s)
{
int c;
c = atoi(s.c_str());
return c;
}

int CPreprocessor::GetMinutes(std::string& s)
{
int c;
std::vector<std::string> v;
SplitString(s, v, ":");
c = StringToInt(v[0]) * 60 + StringToInt(v[1]);
return c;
}

void CPreprocessor::SplitString(const std::string& s, std::vector<std::string>& v, const std::string& c)
{
std::string::size_type pos1, pos2;
pos2 = s.find(c);
pos1 = 0;
while (std::string::npos != pos2)
{
v.push_back(s.substr(pos1, pos2 - pos1));

pos1 = pos2 + c.size();
pos2 = s.find(c, pos1);
}
if (pos1 != s.length())
v.push_back(s.substr(pos1));
}

void CPreprocessor::PrintSchedule(int s[], SPeople p[],std::string& d)
{
std::vector<Sflightdata>::iterator it;
std::pair<std::string, std::string> searchflight;
std::string searchfirst, searchlast;
int solvelen = 12;
for (int ii = 0; ii < solvelen / 2; ii++)
{
searchfirst = p[ii].leaveplace;
searchlast = d;
searchflight = make_pair(searchfirst, searchlast);
it = flight[searchflight].begin();
std::cout <<std::setw(10)<< p[ii].name << std::setw(10)<< searchfirst;
std::cout << std::setw(10) << it[s[2 * ii]].strleavetime << "-" << it[s[2 * ii]].strarrivetime;
std::cout << std::setw(10) << it[s[2 * ii]].nprice;
searchflight = make_pair(searchlast, searchfirst);
it = flight[searchflight].begin();
std::cout <<std::setw(10) << it[s[2 * ii + 1]].strleavetime << "-" << it[s[2 * ii + 1]].strarrivetime;
std::cout << std::setw(10)<<it[s[2 * ii + 1]].nprice;
std::cout << std::endl;
}
}

//get int number range in [lower,upper],
int CPreprocessor::GetRandomInt(int lower, int upper)
{
return rand() % (upper - lower + 1) + lower;
}

//between 0 and 1
double CPreprocessor::GetRandomFloat()
{
return rand() / (RAND_MAX + 1.0);
}

void CPreprocessor::RandomSearching(int s[], SPeople p[], std::string &d)
{
int best = 99999999;
int cost = 0;
int bestschedule[10];
for (int tt = 0; tt < 100; tt++)
{
//srand((int)time(NULL));
srand(GetTickCount() + tt);
for (int ii = 0; ii < 10; ii++)
{
s[ii] = GetRandomInt(0, 9);
}

cost = ScheduleCost(s, p, d);

if (cost < best)
{
best = cost;
for (int ii = 0; ii < 10; ii++)
{
bestschedule[ii] = s[ii];
}
}
}

for (int ii = 0; ii < 10; ii++)
{
s[ii] = bestschedule[ii];
}

std::cout << best << std::endl;
}

int CPreprocessor::ScheduleCost(int s[],SPeople p[],std::string& d)
{
int totalprice = 0;
int totalwait = 0;
int latestarrival = 0;
int earliestleave = 24 * 60;
//int solvelen = sizeof(s) / sizeof(int);
int solvelen = 12;

std::vector<Sflightdata>::iterator it;
std::pair<std::string, std::string> searchflight;
std::string searchfirst, searchlast;

for (int ii = 0; ii < solvelen / 2; ii++)
{
//*outbound*//
searchfirst = p[ii].leaveplace;
searchlast = d;
searchflight = make_pair(searchfirst, searchlast);
it = flight[searchflight].begin();
totalprice += it[s[2*ii]].nprice;
//std::cout << it[s[2*ii]].strleavetime<<"   "<<it[s[2*ii]].strarrivetime<<"   "<<it[s[2 * ii]].nprice << std::endl;

/*record lastest arrive time*/
if (latestarrival < GetMinutes(it[s[2 * ii]].strarrivetime))
{
latestarrival = GetMinutes(it[s[2 * ii]].strarrivetime);
}
//*return*//
searchflight = make_pair(searchlast, searchfirst);
it = flight[searchflight].begin();
totalprice += it[s[2 * ii + 1]].nprice;
//std::cout << it[s[2 * ii + 1]].strleavetime <<"   "<<it[s[2 * ii+1]].strarrivetime <<"   "<< it[s[2 * ii+1]].nprice << std::endl;

/*record earliest leave time*/
if (earliestleave>GetMinutes(it[s[2 * ii + 1]].strleavetime))
{
earliestleave = GetMinutes(it[s[2 * ii + 1]].strleavetime);
}

//std::cout << totalprice << std::endl;
}

/*calculate wait time*/
for (int ii = 0; ii < solvelen / 2; ii++)
{
searchfirst = p[ii].leaveplace;
searchlast = d;
searchflight = make_pair(searchfirst, searchlast);
it = flight[searchflight].begin();
/*wait the latest people*/
totalwait += latestarrival - GetMinutes(it[s[2 * ii]].strarrivetime);

/*wait the return flight*/
searchflight = make_pair(searchlast, searchfirst);
it = flight[searchflight].begin();
totalwait += GetMinutes(it[s[2 * ii + 1]].strleavetime)-earliestleave;
}

if (latestarrival > earliestleave)
{
totalprice += 50;
}

return totalprice + totalwait;
}

void CPreprocessor::SimulatedAnnealing(int s[], SPeople p[], std::string &d)
{
double T = 10000;
double cool = 0.95;
int step = 1;
int index, direction;
int oldschedule[10];
int oldcost, newcost;

while (T > 0.1)
{
oldcost = ScheduleCost(s, p, d);
for (int ii = 0; ii < 10; ii++)
{
oldschedule[ii] = s[ii];
}

srand(GetTickCount());
index = GetRandomInt(0, 9);
srand(GetTickCount());
direction = GetRandomInt(-step, step);
s[index] += direction;
if (s[index]>9)
{
s[index] = 9;
}
else if (s[index] < 0)
{
s[index] = 0;
}

newcost = ScheduleCost(s, p, d);

double temp = -((newcost - oldcost) / T);
if (newcost < oldcost || GetRandomFloat() < exp(temp))
{
for (int ii = 0; ii < 10; ii++)
{
s[ii] = s[ii];
}
}

else
{
for (int ii = 0; ii < 10; ii++)
{
s[ii] = oldschedule[ii];
}
}

T = T*cool;
}
}


SPeople people[6];
string destination = "LGA";
int nsolve[12] = {1,4,3,2,7,3,6,3,2,4,5,3};
int ntest[12] = {6,5,5,5,5,6,6,4,9,1,8,3};

void InitProcessor()
{
people[0].name = "Seymour";
people[0].leaveplace = "BOS";
people[1].name = "Franny";
people[1].leaveplace = "DAL";
people[2].name = "Zooey";
people[2].leaveplace = "CAK";
people[3].name = "Walt";
people[3].leaveplace = "MIA";
people[4].name = "Buddy";
people[4].leaveplace = "ORD";
people[5].name = "Les";
people[5].leaveplace = "OMA";
}


因为模拟退火算法有问题,所以其他几个算法就没写了。

若有大神指点,感激不尽。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: