bool CVMState::moveCentsToTransactionStorage(int cents) { int* changeArray = new int[3]; changeArray = makeChange(cents, totalQuarters, totalDimes, totalNickels, changeArray); if (changeArray == NULL) { delete changeArray; return false; } else { moveChangeToTransactionStorage(changeArray); delete changeArray; return true; } }
bool CVMState::moveCentsToMainStorage(int cents) { int* changeArray = new int[3]; changeArray = makeChange(cents, currentQuarters, currentDimes, currentNickels, changeArray); if (changeArray == NULL) { delete changeArray; return false; } else { moveChangeToMainStorage(changeArray); delete changeArray; return true; } }
int makeChange(int n, int denom) { int next_denom = 0; switch (denom) { case 25: next_denom = 10; break; case 10: next_denom = 5; break; case 5: next_denom = 1; break; case 1: printf("makeChange: %d, %d\n", n, denom); return 1; } int ways = 0; for (int i = 0; i * denom <= n; i++) { ways += makeChange(n - i * denom, next_denom); } return ways; }
int* CVMState::makeChangeFor(int changeCents, int* changeArray) { changeArray = makeChange(changeCents, currentQuarters, currentDimes, currentNickels, changeArray); return changeArray; }
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(); }