void arsaRawParallel(arsaRawArgs& args) { long n = args.n; Rbyte* rawDist = args.rawDist; std::vector<double>& levels = args.levels; double cool = args.cool; double temperatureMin = args.temperatureMin; if(temperatureMin <= 0) { throw std::runtime_error("Input temperatureMin must be positive"); } long nReps = args.nReps; std::vector<int>& permutation = args.permutation; std::function<void(unsigned long, unsigned long)> progressFunction = args.progressFunction; bool randomStart = args.randomStart; int maxMove = args.maxMove; if(maxMove < 0) { throw std::runtime_error("Input maxMove must be non-negative"); } double effortMultiplier = args.effortMultiplier; if(effortMultiplier <= 0) { throw std::runtime_error("Input effortMultiplier must be positive"); } permutation.resize(n); if(n == 1) { permutation[0] = 0; return; } else if(n < 1) { throw std::runtime_error("Input n must be positive"); } //We skip the initialisation of D, R1 and R2 from arsa.f, and the computation of asum. //Next the original arsa.f code creates nReps random permutations, and holds them all at once. This doesn't seem necessary, we create them one at a time and discard them double zbestAllReps = -std::numeric_limits<double>::infinity(); //A copy of the best permutation found std::vector<int> bestPermutationThisRep(n); //We use this to build the random permutations std::vector<int> consecutive(n); for(R_xlen_t i = 0; i < n; i++) consecutive[i] = (int)i; std::vector<int> deltaComponents(levels.size()); //We're doing lots of simulation, so we use the old-fashioned approach to dealing with Rs random number generation GetRNGstate(); std::vector<change> stackOfChanges; std::vector<bool> dirty(n, false); for(int repCounter = 0; repCounter < nReps; repCounter++) { //create the random permutation, if we decided to use a random initial permutation if(randomStart) { for(R_xlen_t i = 0; i < n; i++) { double rand = unif_rand(); R_xlen_t index = (R_xlen_t)(rand*(n-i)); if(index == n-i) index--; bestPermutationThisRep[i] = consecutive[index]; std::swap(consecutive[index], *(consecutive.rbegin()+i)); } } else { for(R_xlen_t i = 0; i < n; i++) { bestPermutationThisRep[i] = consecutive[i]; } } //calculate value of z double z = 0; for(R_xlen_t i = 0; i < n-1; i++) { R_xlen_t k = bestPermutationThisRep[i]; for(R_xlen_t j = i+1; j < n; j++) { R_xlen_t l = bestPermutationThisRep[j]; z += (j-i) * levels[rawDist[l*n + k]]; } } double zbestThisRep = z; double temperatureMax = 0; //Now try 5000 random swaps for(R_xlen_t swapCounter = 0; swapCounter < (R_xlen_t)(5000*effortMultiplier); swapCounter++) { R_xlen_t swap1, swap2; getPairForSwap(n, swap1, swap2); double delta = computeDelta(bestPermutationThisRep, swap1, swap2, rawDist, levels, deltaComponents); if(delta < 0) { if(fabs(delta) > temperatureMax) temperatureMax = fabs(delta); } } double temperature = temperatureMax; std::vector<int> currentPermutation = bestPermutationThisRep; int nloop = (int)((log(temperatureMin) - log(temperatureMax)) / log(cool)); long totalSteps = (long)(nloop * 100 * n * effortMultiplier); long done = 0; //Rcpp::Rcout << "Steps needed: " << nloop << std::endl; for(R_xlen_t idk = 0; idk < nloop; idk++) { //Rcpp::Rcout << "Temp = " << temperature << std::endl; for(R_xlen_t k = 0; k < (R_xlen_t)(100*n*effortMultiplier); k++) { R_xlen_t swap1, swap2; //swap if(unif_rand() <= 0.5) { getPairForSwap(n, swap1, swap2); change newChange; newChange.isMove = false; newChange.swap1 = swap1; newChange.swap2 = swap2; if(dirty[swap1] || dirty[swap2]) { #pragma omp parallel for for(std::vector<change>::iterator i = stackOfChanges.begin(); i != stackOfChanges.end(); i++) { deltaForChange(*i, currentPermutation, rawDist, levels); } for(std::vector<change>::iterator i = stackOfChanges.begin(); i != stackOfChanges.end(); i++) { makeChange(*i, currentPermutation, rawDist, levels, z, zbestThisRep, bestPermutationThisRep, temperature); } done += stackOfChanges.size(); progressFunction(done, totalSteps); stackOfChanges.clear(); std::fill(dirty.begin(), dirty.end(), false); } else dirty[swap1] = dirty[swap2] = true; stackOfChanges.push_back(newChange); } //insertion else { getPairForMove(n, swap1, swap2, maxMove); bool canDefer = true; for(R_xlen_t i = std::min(swap1, swap2); i != std::max(swap1, swap2)+1; i++) canDefer &= !dirty[i]; change newChange; newChange.isMove = true; newChange.swap1 = swap1; newChange.swap2 = swap2; if(canDefer) { std::fill(dirty.begin() + std::min(swap1, swap2), dirty.begin() + std::max(swap1, swap2)+1, true); } else { #pragma omp parallel for for(std::vector<change>::iterator i = stackOfChanges.begin(); i != stackOfChanges.end(); i++) { deltaForChange(*i, currentPermutation, rawDist, levels); } for(std::vector<change>::iterator i = stackOfChanges.begin(); i != stackOfChanges.end(); i++) { makeChange(*i, currentPermutation, rawDist, levels, z, zbestThisRep, bestPermutationThisRep, temperature); } done += stackOfChanges.size(); progressFunction(done, totalSteps); stackOfChanges.clear(); std::fill(dirty.begin(), dirty.end(), false); } stackOfChanges.push_back(newChange); } } #pragma omp parallel for for(std::vector<change>::iterator i = stackOfChanges.begin(); i != stackOfChanges.end(); i++) { deltaForChange(*i, currentPermutation, rawDist, levels); } for(std::vector<change>::iterator i = stackOfChanges.begin(); i != stackOfChanges.end(); i++) { makeChange(*i, currentPermutation, rawDist, levels, z, zbestThisRep, bestPermutationThisRep, temperature); } done += stackOfChanges.size(); progressFunction(done, totalSteps); stackOfChanges.clear(); std::fill(dirty.begin(), dirty.end(), false); temperature *= cool; } if(zbestThisRep > zbestAllReps) { zbestAllReps = zbestThisRep; permutation.swap(bestPermutationThisRep); } } PutRNGstate(); }
ZPatcher::PatchFileList_t* ZPatcher::GetDifferences(std::string& oldVersion, std::string& newVersion, ProgressCallback progressFunction) { PatchFileList_t* patchFileList = new PatchFileList_t(); std::vector<std::string> oldVersionFileList; GetFilesInDirectory(oldVersionFileList, oldVersion); std::vector<std::string> newVersionFileList; GetFilesInDirectory(newVersionFileList, newVersion); // Sort them now to avoid worries later. (Easier to find added/deleted files) std::sort(oldVersionFileList.begin(), oldVersionFileList.end()); std::sort(newVersionFileList.begin(), newVersionFileList.end()); unsigned int oldFileIndex = 0; unsigned int newFileIndex = 0; fprintf(stdout, "Detecting file differences between folders...\n"); while (oldFileIndex < oldVersionFileList.size() && newFileIndex < newVersionFileList.size()) { float progress = (oldFileIndex + newFileIndex) * 100.0f / (oldVersionFileList.size() + newVersionFileList.size()); progressFunction(progress, oldFileIndex + newFileIndex, oldVersionFileList.size() + newVersionFileList.size()); const std::string& oldFileName = oldVersionFileList[oldFileIndex]; const std::string& newFileName = newVersionFileList[newFileIndex]; if (oldFileName == newFileName) { // Check if we are dealing with directories. size_t fileNameLength = oldFileName.length(); if (fileNameLength > 0 && oldFileName[fileNameLength - 1] != '/') { // Check if the files have the same contents bool identical; bool success = AreFilesIdentical(oldVersion + "/" + oldFileName, newVersion + "/" + newFileName, identical); assert(success == true); // TODO: Handle this. if (success != true) { fprintf(stderr, "\n\nError comparing files! Patch file might be inconsistent! Check the logs for details.\n\n"); } if (success && !identical) { patchFileList->ModifiedFileList.push_back(oldFileName); } } oldFileIndex++; newFileIndex++; } else if (oldFileName < newFileName) { // The new version doesn't contain this file. patchFileList->RemovedFileList.push_back(oldFileName); oldFileIndex++; } else { // The old version doesn't contain this file. patchFileList->AddedFileList.push_back(newFileName); newFileIndex++; } } // Okay, one of the lists is smaller than the other. Add or Remove all missing files, depending on the file list. while (oldFileIndex < oldVersionFileList.size()) { float progress = (oldFileIndex + newFileIndex) * 100.0f / (oldVersionFileList.size() + newVersionFileList.size()); progressFunction(progress, oldFileIndex + newFileIndex, oldVersionFileList.size() + newVersionFileList.size()); patchFileList->RemovedFileList.push_back(oldVersionFileList[oldFileIndex]); oldFileIndex++; } while (newFileIndex < newVersionFileList.size()) { float progress = (newFileIndex + newFileIndex) * 100.0f / (newVersionFileList.size() + newVersionFileList.size()); progressFunction(progress, oldFileIndex + newFileIndex, oldVersionFileList.size() + newVersionFileList.size()); patchFileList->AddedFileList.push_back(newVersionFileList[newFileIndex]); newFileIndex++; } progressFunction(100.0f, oldFileIndex + newFileIndex, oldVersionFileList.size() + newVersionFileList.size()); fprintf(stdout, "\n\n"); return patchFileList; }
void arsaRaw(arsaRawArgs& args) { long n = args.n; Rbyte* rawDist = args.rawDist; std::vector<double>& levels = args.levels; double cool = args.cool; double temperatureMin = args.temperatureMin; if(temperatureMin <= 0) { throw std::runtime_error("Input temperatureMin must be positive"); } long nReps = args.nReps; std::vector<int>& permutation = args.permutation; std::function<void(unsigned long, unsigned long)> progressFunction = args.progressFunction; bool randomStart = args.randomStart; int maxMove = args.maxMove; if(maxMove < 0) { throw std::runtime_error("Input maxMove must be non-negative"); } double effortMultiplier = args.effortMultiplier; if(effortMultiplier <= 0) { throw std::runtime_error("Input effortMultiplier must be positive"); } permutation.resize(n); if(n == 1) { permutation[0] = 0; return; } else if(n < 1) { throw std::runtime_error("Input n must be positive"); } //We skip the initialisation of D, R1 and R2 from arsa.f, and the computation of asum. //Next the original arsa.f code creates nReps random permutations, and holds them all at once. This doesn't seem necessary, we create them one at a time and discard them double zbestAllReps = -std::numeric_limits<double>::infinity(); //A copy of the best permutation found std::vector<int> bestPermutationThisRep(n); //We use this to build the random permutations std::vector<int> consecutive(n); for(R_xlen_t i = 0; i < n; i++) consecutive[i] = (int)i; std::vector<int> deltaComponents(levels.size()); //We're doing lots of simulation, so we use the old-fashioned approach to dealing with Rs random number generation GetRNGstate(); for(int repCounter = 0; repCounter < nReps; repCounter++) { //create the random permutation, if we decided to use a random initial permutation if(randomStart) { for(R_xlen_t i = 0; i < n; i++) { double rand = unif_rand(); R_xlen_t index = (R_xlen_t)(rand*(n-i)); if(index == n-i) index--; bestPermutationThisRep[i] = consecutive[index]; std::swap(consecutive[index], *(consecutive.rbegin()+i)); } } else { for(R_xlen_t i = 0; i < n; i++) { bestPermutationThisRep[i] = consecutive[i]; } } //calculate value of z double z = 0; for(R_xlen_t i = 0; i < n-1; i++) { R_xlen_t k = bestPermutationThisRep[i]; for(R_xlen_t j = i+1; j < n; j++) { R_xlen_t l = bestPermutationThisRep[j]; z += (j-i) * levels[rawDist[l*n + k]]; } } double zbestThisRep = z; double temperatureMax = 0; //Now try 5000 random swaps for(R_xlen_t swapCounter = 0; swapCounter < (R_xlen_t)(5000*effortMultiplier); swapCounter++) { R_xlen_t swap1, swap2; getPairForSwap(n, swap1, swap2); double delta = computeDelta(bestPermutationThisRep, swap1, swap2, rawDist, levels, deltaComponents); if(delta < 0) { if(fabs(delta) > temperatureMax) temperatureMax = fabs(delta); } } double temperature = temperatureMax; std::vector<int> currentPermutation = bestPermutationThisRep; int nloop = (int)((log(temperatureMin) - log(temperatureMax)) / log(cool)); long totalSteps = (long)(nloop * 100 * n * effortMultiplier); long done = 0; long threadZeroCounter = 0; //Rcpp::Rcout << "Steps needed: " << nloop << std::endl; for(R_xlen_t idk = 0; idk < nloop; idk++) { //Rcpp::Rcout << "Temp = " << temperature << std::endl; for(R_xlen_t k = 0; k < (R_xlen_t)(100*n*effortMultiplier); k++) { R_xlen_t swap1, swap2; //swap if(unif_rand() <= 0.5) { getPairForSwap(n, swap1, swap2); double delta = computeDelta(currentPermutation, swap1, swap2, rawDist, levels, deltaComponents); if(delta > -1e-8) { z += delta; std::swap(currentPermutation[swap1], currentPermutation[swap2]); if(z > zbestThisRep) { zbestThisRep = z; bestPermutationThisRep = currentPermutation; } } else { if(unif_rand() <= exp(delta / temperature)) { z += delta; std::swap(currentPermutation[swap1], currentPermutation[swap2]); } } } //insertion else { getPairForMove(n, swap1, swap2, maxMove); double delta = computeMoveDelta(deltaComponents, swap1, swap2, currentPermutation, rawDist, n, levels); int permutedSwap1 = currentPermutation[swap1]; if(delta > -1e-8 || unif_rand() <= exp(delta / temperature)) { z += delta; if(swap2 > swap1) { for(R_xlen_t i = swap1; i < swap2; i++) { currentPermutation[i] = currentPermutation[i+1]; } currentPermutation[swap2] = (int)permutedSwap1; } else { for(R_xlen_t i = swap1; i > swap2; i--) { currentPermutation[i] = currentPermutation[i-1]; } currentPermutation[swap2] = (int)permutedSwap1; } } if(delta > -1e-8 && z > zbestThisRep) { bestPermutationThisRep = currentPermutation; zbestThisRep = z; } } done++; threadZeroCounter++; if(threadZeroCounter % 100 == 0) { progressFunction(done, totalSteps); } } temperature *= cool; } if(zbestThisRep > zbestAllReps) { zbestAllReps = zbestThisRep; permutation.swap(bestPermutationThisRep); } } PutRNGstate(); }