RunData.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. #include "pch.h"
  2. #include "GraphView.h"
  3. #include "RunData.h"
  4. #include <QDebug>
  5. #include <QString>
  6. #include <regex>
  7. #include <algorithm>
  8. RunData::RunData()
  9. {
  10. }
  11. RunData::RunData(std::string filePath) : fileStream(filePath), filePath(filePath)
  12. {
  13. std::string file = filePath.substr(filePath.find_last_of("/\\") + 1);
  14. name = file.substr(0, file.rfind("."));
  15. if (!fileStream.is_open())
  16. {
  17. //Cant open file
  18. badFileFlag = true;
  19. return;
  20. }
  21. std::string buffer;
  22. getLine(buffer);
  23. qDebug() << QString::fromStdString(buffer);
  24. /*bool retflag;
  25. metalogFile(retflag);
  26. if (retflag) return;*/
  27. std::string integerRegexString = "([\\+\\-]?\\d+)";
  28. std::string doubleRegexString = "([\\+\\-]?\\d+(?:\\.\\d+(?:E[\\+\\-]\\d+)?)?)";
  29. std::string binaryRegexString = "([01]+)";
  30. std::string seperator = ",";
  31. std::regex regexLine(integerRegexString
  32. + seperator + integerRegexString
  33. + seperator + integerRegexString
  34. + seperator + doubleRegexString
  35. + seperator + binaryRegexString);
  36. while (fileStream.peek() != EOF) {
  37. std::string buffer;
  38. getLine(buffer);
  39. SolutionPointData sol;
  40. std::smatch match;
  41. if (!std::regex_search(buffer, match, regexLine)) {
  42. qDebug() << "Bad formatatted Line[" << actualLine << "].";
  43. qDebug() << "Failed to matched:";
  44. qDebug() << QString::fromStdString(buffer);
  45. return;
  46. }
  47. sol.round = std::stoi(match[1]);
  48. sol.iteration = std::stoi(match[2]);
  49. sol.particleNumber = std::stoi(match[3]);
  50. sol.objectiveFunction = std::stod(match[4]);
  51. sol.bitVec.resize(match[5].length());
  52. std::string binaryString = match[5];
  53. for (std::string::size_type i = 0; i < binaryString.size(); ++i) {
  54. sol.bitVec[i] = (binaryString[i] == '1');
  55. }
  56. solutionVec.push_back(sol);
  57. }
  58. fileStream.close();
  59. qDebug() << "Import done";
  60. //Set Runs apart
  61. int count = 0;
  62. std::vector<SolutionPointData>::iterator begin = solutionVec.begin();
  63. for (auto iter = solutionVec.begin(); iter != solutionVec.end(); iter++) {
  64. if (iter->round != begin->round) {
  65. std::string endString("[");
  66. endString += std::to_string(count++);
  67. endString += "]";
  68. singleRunList.push_back(SingleRun(name, begin, iter, name + endString));
  69. begin = iter;
  70. }
  71. }
  72. std::string endString("[");
  73. endString += std::to_string(count);
  74. endString += "]";
  75. singleRunList.push_back(SingleRun(name, begin, solutionVec.end(), name + endString));
  76. //Generate PascalTriangle
  77. std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
  78. int amountOfBits = begin->bitVec.size();
  79. int lines = amountOfBits + 1;
  80. std::vector<boost::multiprecision::cpp_int> pascalTriangleVec(((lines + 1) / 2 * (lines / 2 + 1)));
  81. for (int line = 0; line < lines; line++) {
  82. for (int number = 0; number < line + 1; number++) {
  83. if (number > line / 2) break;
  84. if (number == 0 || number == line) {
  85. pascalTriangleVec[binominalIndex(line, number)] = 1;
  86. }
  87. else {
  88. pascalTriangleVec[binominalIndex(line, number)] = pascalTriangleVec[binominalIndex(line - 1, number)] + pascalTriangleVec[binominalIndex(line - 1, number - 1)];
  89. }
  90. }
  91. }
  92. std::chrono::high_resolution_clock::time_point endPoint = std::chrono::high_resolution_clock::now();
  93. std::chrono::milliseconds time = std::chrono::duration_cast<std::chrono::milliseconds>(endPoint - start);
  94. qDebug() << "PascalTriangle: " << time.count() << "ms";
  95. //Calculate Additional Data
  96. for (SingleRun& srun : singleRunList) {
  97. srun.calculateAdditionalData(pascalTriangleVec, amountOfBits);
  98. }
  99. calculateAverageOverRuns();
  100. }
  101. void RunData::metalogFile(bool& retflag)
  102. {
  103. retflag = true;
  104. /* Start extracting */
  105. while (fileStream.peek() != EOF) {
  106. std::string buffer;
  107. getLine(buffer);
  108. SolutionPointData sol;
  109. std::regex regexIter("i:([\\+\\-]?\\d+)");
  110. std::regex regexObjectiveFunction("of:([\\+\\-]?\\d+\\.\\d+(?:E[\\+\\-]\\d+)?)");
  111. std::smatch match;
  112. if (!std::regex_search(buffer, match, regexIter)) {
  113. qDebug() << "Bad formatatted Line[" << actualLine << "].";
  114. qDebug() << "Failed to matched:";
  115. qDebug() << QString::fromStdString(buffer);
  116. return;
  117. }
  118. sol.iteration = std::stoi(match[1]);
  119. if (!std::regex_search(buffer, match, regexObjectiveFunction)) {
  120. qDebug() << "Bad formatatted Line[" << actualLine << "].";
  121. qDebug() << "Failed to matched:";
  122. qDebug() << QString::fromStdString(buffer);
  123. return;
  124. }
  125. sol.objectiveFunction = std::stod(match[1]);
  126. std::regex regexParticleNumber("pN:([\\+\\-]?\\d+)");
  127. if (!std::regex_search(buffer, match, regexParticleNumber)) {
  128. qDebug() << "Bad formatatted Line[" << actualLine << "].";
  129. qDebug() << "Failed to matched:";
  130. qDebug() << QString::fromStdString(buffer);
  131. return;
  132. }
  133. sol.particleNumber = std::stoi(match[1]);
  134. std::regex regexBitVec("b:([01]+)");
  135. if (!std::regex_search(buffer, match, regexBitVec)) {
  136. qDebug() << "Bad formatatted Line[" << actualLine << "].";
  137. qDebug() << "Failed to matched:";
  138. qDebug() << QString::fromStdString(buffer);
  139. return;
  140. }
  141. sol.bitVec.resize(match[1].length());
  142. int count = 0;
  143. std::string str = match[1];
  144. for (std::string::size_type i = 0; i < str.size(); ++i) {
  145. sol.bitVec[i] = (str[i] == '1');
  146. }
  147. solutionVec.push_back(sol);
  148. }
  149. retflag = false;
  150. }
  151. void RunData::getLine(std::string& bufferString)
  152. {
  153. std::getline(fileStream, bufferString);
  154. actualLine++;
  155. }
  156. void RunData::calculateAverageOverRuns()
  157. {
  158. qDebug() << "calculateAverageOverRuns";
  159. {
  160. std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
  161. int iter = singleRunList.begin()->bestMaxSolutionFoundPerIteration.size();
  162. double n = singleRunList.size();
  163. bestAverageMaxSolutionFoundPerIteration.resize(iter);
  164. for (int i = 0; i < iter; i++) {
  165. double average = std::accumulate(singleRunList.begin(), singleRunList.end(), 0.0, [i](double a, const SingleRun& b) -> double
  166. {return a + b.bestMaxSolutionFoundPerIteration[i].y; }) / n;
  167. bestAverageMaxSolutionFoundPerIteration[i] = GraphDataPoint((double)i, average);
  168. }
  169. std::chrono::high_resolution_clock::time_point endPoint = std::chrono::high_resolution_clock::now();
  170. std::chrono::milliseconds time = std::chrono::duration_cast<std::chrono::milliseconds>(endPoint - start);
  171. qDebug() << "Time" << time.count() << "ms";
  172. }
  173. }
  174. SingleRun::SingleRun(std::string uniqueName, const std::vector<SolutionPointData>::iterator begin, const std::vector<SolutionPointData>::iterator end, std::string name = "")
  175. :begin(begin), end(end), name(name), runDataName(uniqueName)
  176. {
  177. }
  178. void SingleRun::calculateAdditionalData(std::vector<boost::multiprecision::cpp_int>& pascalTriangleVec, int amountOfBits)
  179. {
  180. calculateBestAndAverageIter();
  181. calculateParticleSolution();
  182. calculateDotsForDistribution();
  183. calculateBitFieldData(pascalTriangleVec, amountOfBits);
  184. calculateMeanHammingDistance();
  185. }
  186. void SingleRun::calculateBestAndAverageIter()
  187. {
  188. if (begin == end) {
  189. return;
  190. }
  191. double minObjectiveFunctionInIter = begin->objectiveFunction;
  192. double maxObjectiveFunctionInIter = begin->objectiveFunction;
  193. double bestMinObjectiveFunctionFound = begin->objectiveFunction;
  194. double bestMaxObjectiveFunctionFound = begin->objectiveFunction;
  195. double actualIterObjectiveFunctionAggregate = begin->objectiveFunction;
  196. int actualIter = begin->iteration;
  197. int foundSolutionInIteration = 1;
  198. for (auto iter = begin; iter != end; iter++) {
  199. SolutionPointData& nextData = *iter;
  200. if (nextData.iteration != actualIter) {
  201. //save last
  202. bestMinSolutionFoundPerIteration.push_back(GraphDataPoint((double)actualIter, bestMinObjectiveFunctionFound));
  203. bestMaxSolutionFoundPerIteration.push_back(GraphDataPoint((double)actualIter, bestMaxObjectiveFunctionFound));
  204. averageSolutionPerItertion.push_back(GraphDataPoint((double)actualIter, actualIterObjectiveFunctionAggregate / (double)foundSolutionInIteration));
  205. minSolutionPerItertion.push_back(GraphDataPoint((double)actualIter, minObjectiveFunctionInIter));
  206. maxSolutionPerItertion.push_back(GraphDataPoint((double)actualIter, maxObjectiveFunctionInIter));
  207. //init new iteration
  208. actualIter = nextData.iteration;
  209. foundSolutionInIteration = 1;
  210. actualIterObjectiveFunctionAggregate = nextData.objectiveFunction;
  211. minObjectiveFunctionInIter = nextData.objectiveFunction;
  212. maxObjectiveFunctionInIter = nextData.objectiveFunction;
  213. }
  214. else {
  215. //increae aggregate
  216. foundSolutionInIteration++;
  217. actualIterObjectiveFunctionAggregate += nextData.objectiveFunction;
  218. }
  219. //update best min and max if better
  220. if (nextData.objectiveFunction < bestMinObjectiveFunctionFound) {
  221. bestMinObjectiveFunctionFound = nextData.objectiveFunction;
  222. }
  223. if (nextData.objectiveFunction > bestMaxObjectiveFunctionFound) {
  224. bestMaxObjectiveFunctionFound = nextData.objectiveFunction;
  225. }
  226. if (nextData.objectiveFunction < minObjectiveFunctionInIter) {
  227. minObjectiveFunctionInIter = nextData.objectiveFunction;
  228. }
  229. if (nextData.objectiveFunction > maxObjectiveFunctionInIter) {
  230. maxObjectiveFunctionInIter = nextData.objectiveFunction;
  231. }
  232. }
  233. //save last iteration
  234. bestMinSolutionFoundPerIteration.push_back(GraphDataPoint((double)actualIter, bestMinObjectiveFunctionFound));
  235. bestMaxSolutionFoundPerIteration.push_back(GraphDataPoint((double)actualIter, bestMaxObjectiveFunctionFound));
  236. averageSolutionPerItertion.push_back(GraphDataPoint((double)actualIter, actualIterObjectiveFunctionAggregate / (double)foundSolutionInIteration));
  237. minSolutionPerItertion.push_back(GraphDataPoint((double)actualIter, minObjectiveFunctionInIter));
  238. maxSolutionPerItertion.push_back(GraphDataPoint((double)actualIter, maxObjectiveFunctionInIter));
  239. }
  240. void SingleRun::calculateParticleSolution()
  241. {
  242. for (auto iter = begin; iter != end; iter++) {
  243. GraphDataPoint point(iter->iteration, iter->objectiveFunction, &*iter);
  244. auto treeIter = particleMap.find(iter->particleNumber);
  245. if (treeIter == particleMap.end()) {
  246. //create new Entry
  247. std::vector<GraphDataPoint> vec;
  248. vec.push_back(point);
  249. particleMap.insert({ iter->particleNumber, vec});
  250. }
  251. else {
  252. //append to vector in Entry
  253. treeIter->second.push_back(point);
  254. }
  255. }
  256. }
  257. void SingleRun::calculateDotsForDistribution()
  258. {
  259. for (std::vector<SolutionPointData>::iterator it = begin; it != end; ++it) {
  260. dotsForDistribution.push_back(GraphDataPoint((double)it->iteration, it->objectiveFunction, &*it));
  261. }
  262. }
  263. boost::multiprecision::cpp_int positionInPermutation2(std::vector<boost::multiprecision::cpp_int>& pascalTriangleVec, std::vector<bool>::iterator begin, std::vector<bool>::iterator end, int amountOfUnsetBits)
  264. {
  265. //recursion base
  266. if (amountOfUnsetBits == 0) return 1;
  267. int amountOfBits = end - begin;
  268. std::vector<bool>::iterator indexIter = std::find(begin, end, false);
  269. int index = indexIter - begin;
  270. int amountOfBitsAfterIndex = (amountOfBits - 1) - index;
  271. //recursion base
  272. if (amountOfUnsetBits == 1) return (amountOfBits - 1) - index;
  273. //Step 1 the amount of permutations with the rest amountOfBitsAfterIndex
  274. boost::multiprecision::cpp_int before = (amountOfUnsetBits <= amountOfBitsAfterIndex) ? pascalTriangleVec[RunData::binominalIndex(amountOfBitsAfterIndex, amountOfUnsetBits)] : 0;
  275. //Step 2 the actual position of the rest
  276. boost::multiprecision::cpp_int after = positionInPermutation2(pascalTriangleVec, ++indexIter, end, amountOfUnsetBits - 1);
  277. //Step 3 add Step 1 and Step 2
  278. return before + after;
  279. }
  280. void SingleRun::calculateBitFieldData(std::vector<boost::multiprecision::cpp_int>& pascalTriangleVec, int amountOfBits)
  281. {
  282. std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
  283. for (std::vector<SolutionPointData>::iterator it = begin; it != end; ++it) {
  284. int amountOfSetBits = std::count(it->bitVec.begin(), it->bitVec.end(), true);
  285. int amountOfUnsetBits = it->bitVec.size() - amountOfSetBits;
  286. boost::multiprecision::cpp_dec_float_100 position(positionInPermutation2(pascalTriangleVec, it->bitVec.begin(), it->bitVec.end(), amountOfUnsetBits));
  287. boost::multiprecision::cpp_dec_float_100 maxAmountOfPermutaions (pascalTriangleVec[RunData::binominalIndex(amountOfBits, amountOfSetBits)] - 1);
  288. dotsForBitField.push_back(GraphDataPoint((position / maxAmountOfPermutaions).convert_to<double>(), amountOfSetBits, &*it));
  289. }
  290. std::chrono::high_resolution_clock::time_point endPoint = std::chrono::high_resolution_clock::now();
  291. std::chrono::milliseconds time = std::chrono::duration_cast<std::chrono::milliseconds>(endPoint - start);
  292. qDebug() << "BitFieldBerechnung: " << time.count() << "ms";
  293. }
  294. void SingleRun::calculateMeanHammingDistance()
  295. {
  296. std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
  297. std::vector<SolutionPointData>::iterator iterBegin = begin;
  298. for (std::vector<SolutionPointData>::iterator iter = begin; iter != end; iter++) {
  299. if (iter->iteration != iterBegin->iteration) {
  300. double mean = RunData::meanHammingDistance(iterBegin, iter);
  301. meanHammingDistancePerIteration.push_back(GraphDataPoint(iterBegin->iteration, mean));
  302. iterBegin = iter;
  303. }
  304. }
  305. std::chrono::high_resolution_clock::time_point endPoint = std::chrono::high_resolution_clock::now();
  306. std::chrono::milliseconds time = std::chrono::duration_cast<std::chrono::milliseconds>(endPoint - start);
  307. qDebug() << "Mean: " << time.count() << "ms";
  308. }
  309. int RunData::binominalIndex(const int n, int k)
  310. {
  311. if (k > n / 2) k = n - k;
  312. return ((n + 1) / 2) * (n / 2 + 1) + k;
  313. }
  314. int RunData::hammingdistance(std::vector<bool>& bitVecA, std::vector<bool>& bitVecB)
  315. {
  316. //assert((bitVecA.size() == bitVecB.size()));
  317. int count = 0;
  318. auto iterB = bitVecB.begin();
  319. for (auto iterA = bitVecA.begin(); iterA != bitVecA.end(); iterA++) {
  320. if (*iterA != *iterB) {
  321. count++;
  322. }
  323. iterB++;
  324. }
  325. return count;
  326. }
  327. double RunData::meanHammingDistance(std::vector<SolutionPointData>::iterator begin, std::vector<SolutionPointData>::iterator end)
  328. {
  329. if (std::distance(begin, end) <= 1) {
  330. return 0.0;
  331. }
  332. std::vector<SolutionPointData>::iterator startParticle(begin);
  333. double hammingValuesAccumulated = 0.0;
  334. int count = 0;
  335. for (std::vector<SolutionPointData>::iterator iter = begin; iter != end; iter++) {
  336. for (std::vector<SolutionPointData>::iterator iterParticle = iter + 1; iterParticle != end; iterParticle++) {
  337. hammingValuesAccumulated += hammingdistance(iter->bitVec, iterParticle->bitVec);
  338. count++;
  339. }
  340. }
  341. return hammingValuesAccumulated / (double) count;
  342. }
  343. boost::multiprecision::cpp_int RunData::binominal(const int n,int k)
  344. {
  345. boost::multiprecision::cpp_int value(1);
  346. if (k > n / 2) k = n - k;
  347. for (int i = 0; i < k; i++) {
  348. value *= boost::multiprecision::cpp_int(n - i);
  349. value /= boost::multiprecision::cpp_int(i + 1);
  350. }
  351. return value;
  352. }
  353. boost::multiprecision::cpp_int RunData::positionInPermutation(std::vector<bool>::iterator begin, std::vector<bool>::iterator end, int setBits)
  354. {
  355. int amountOfBits = end - begin;
  356. //recursion base
  357. if (setBits == 0) return 1;
  358. std::vector<bool>::iterator indexIter = std::find(begin, end, true);//TODO:false könnte andersrum sortieren!
  359. int index = indexIter - begin;
  360. int bitsAfterIndex = (amountOfBits - 1) - index;
  361. //recursion base
  362. if (setBits == 1) return (amountOfBits - 1) - index;
  363. //Step 1 the amount of permutations with the rest amountOfBitsAfterIndex
  364. boost::multiprecision::cpp_int before = binominal(bitsAfterIndex, setBits);
  365. //Step 2 teh actual position of the rest
  366. boost::multiprecision::cpp_int after = positionInPermutation(++indexIter, end, setBits - 1);
  367. //setp 3 add Step 1 and Step 2
  368. return before + after;
  369. }
  370. boost::multiprecision::cpp_int RunData::positionInPermutation_reversed(std::vector<bool>::iterator begin, std::vector<bool>::iterator end, int amountOfUnsetBits)
  371. {
  372. qDebug() << "Method()";
  373. int amountOfBits = end - begin;
  374. //recursion base
  375. if (amountOfUnsetBits == 0) return 1;
  376. std::vector<bool>::iterator indexIter = std::find(begin, end, false);
  377. int index = indexIter - begin;
  378. qDebug() << "index: " << index;
  379. int bitsAfterIndex = (amountOfBits - 1) - index;
  380. //recursion base
  381. if (amountOfUnsetBits == 1) return (amountOfBits - 1) - index;
  382. //Step 1 the amount of permutations with the rest amountOfBitsAfterIndex
  383. boost::multiprecision::cpp_int before = (amountOfUnsetBits <= bitsAfterIndex)? binominal(bitsAfterIndex, amountOfUnsetBits):0;
  384. qDebug() << "before: " << "binominal("<< bitsAfterIndex << "," << amountOfUnsetBits << ")" << before.convert_to<int>();
  385. //Step 2 teh actual position of the rest
  386. boost::multiprecision::cpp_int after = positionInPermutation_reversed(++indexIter, end, amountOfUnsetBits - 1);
  387. qDebug() << "after: " << after.convert_to<int>();
  388. qDebug() << "return:" << before.convert_to<int>() << "+" << after.convert_to<int>();
  389. //setp 3 add Step 1 and Step 2
  390. return before + after;
  391. }
  392. GraphDataPoint::GraphDataPoint(double x, double y, SolutionPointData* orginalPoint) : x(x), y(y), orginalPoint(orginalPoint)
  393. {
  394. }
  395. GraphDataPoint::GraphDataPoint(double x, double y, QColor color, SolutionPointData* orginalPoint)
  396. : x(x), y(y), orginalPoint(orginalPoint), color(color)
  397. {
  398. }
  399. bool GraphDataPoint::existLink() const
  400. {
  401. return orginalPoint != nullptr;
  402. }
  403. QPointF GraphDataPoint::toQPointF() const
  404. {
  405. return QPointF(x, y);
  406. }
  407. double GraphDataPoint::squaredDistance(QPointF& graphPoint) const
  408. {
  409. return std::pow(graphPoint.x() - x, 2) + std::pow(graphPoint.y() - y, 2);
  410. }
  411. std::string SolutionPointData::bitstringToStdString()
  412. {
  413. std::string str(bitVec.size(), 0);
  414. std::transform(bitVec.begin(), bitVec.end(), str.begin(),
  415. [](bool b) -> char { return b ? '1' : '0'; });
  416. return str;
  417. }