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

来源:互联网 发布:mac战网外服 编辑:程序博客网 时间:2024/06/06 03:07

第五章的主题是优化,实际上就是求最优解,其中举了一个组团旅游的例子。代码运行了,但感觉结果有点问题,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 1double 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";}

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

若有大神指点,感激不尽。

0 0
原创粉丝点击