double get_distance(double L, double *params, int num_energies) { // for a given L, start plotting the energy function until the specified number of energy roots are found { int num_eigenenergies = 0; double step_percent = 0.01; double potential = params[2]; double step = potential * step_percent; int count = 0; double lowerBound = 0; int num_of_brackets = 0; double bracket_first, bracket_second; double root; double f_E; double f_E_prev = energy_function(0, params); double highest_energy; params[1] = L; for (double energy = step; energy < potential; energy += step) { f_E = energy_function(energy, params); if (signbit(f_E) != signbit(f_E_prev)) { count++; if (count == num_energies) { lowerBound = energy - step; bracket_first = lowerBound; bracket_second = energy; num_of_brackets = num_of_brackets + 1; highest_energy = newtonhybridp(energy_function, energy_function_d, params, bracket_first, bracket_second, max_iter, TOL, VERBOSE); } // printf("num brackets: %d\r\n", num_of_brackets); } f_E_prev = f_E; if (false) { printf("energy: %3.8f ; function: %3.8f\r\n", energy, f_E); } } // printf("length: %3.8f\r\n", L); // printf("# roots: %d\r\n", count); double distance = -1; if (count == num_energies) { distance = (potential - highest_energy); } printf("%3.8f,%d,%3.8f\r\n", L, count, distance); if (count > num_energies) { return -1; } if (count < num_energies) { return -2; } return (potential - highest_energy); // bisection search with each increment step that changes sign } // if there aren't at least that many found, return null = double.min // if there are more than that many, return double.max // return the distance of the energy root from v_0 the potential }
void anneal_puncturing::unperturb() { // undo the swap pattern(set, pos1) = false; pattern(set, pos2) = true; // and work back the change in energy energy_function(-1, set, pos1); energy_function(1, set, pos2); // revert to old energy value E = Eold; }
splab::Vector<double> grad(splab::Vector<double> X){ // copy the input X std::vector<double> cppX ; for( int i=0; i<X.size(); ++i ) cppX.push_back(X[i]) ; splab::Vector<double> g(cppX.size()); double e = energy_function(cppX, ctrpoints,edges, gradmap, vecfield ) ; for( size_t i=0; i<cppX.size(); ++i ){ std::vector<double> cppX2 = cppX; double step = 3.0 ; cppX2[i] += step ; g[i] = (energy_function( cppX2,ctrpoints, edges, gradmap, vecfield ) - e ) / step ; } std::cout<< "g[] = ["; for( int i=0; i<g.size()-1; ++i ) std::cout<<g[i]<<"," ; std::cout<<g[X.size()-1]<<"] "<< std::endl; return g; }
double operator() (splab::Vector<double> X){ // copy the input X std::vector<double> X0 ; for( int i=0; i<X.size(); ++i ) X0.push_back(X[i]) ; double energy = energy_function(X0, ctrpoints,edges, gradmap, vecfield ) ; std::cout<< "f("; for( size_t i=0; i<X0.size()-1; ++i ) std::cout<<X0[i]<<"," ; std::cout<<X0.back()<<") = "<< energy <<std::endl; return energy ; }
static lbfgsfloatval_t evaluate( void *instance, const lbfgsfloatval_t *x, lbfgsfloatval_t *g, const int n, const lbfgsfloatval_t step ) { // copy the input X std::vector<double> cppX ; for( int i=0; i<n; ++i ) cppX.push_back(x[i]) ; std::cout<< "f("; for( size_t i=0; i<cppX.size()-1; ++i ) std::cout<<cppX[i]<<"," ; std::cout<<cppX.back()<<") "<< std::endl; // evaluate fx double e = energy_function(cppX, ctrpoints,edges, gradmap, vecfield ) ; // evaluate g std::vector<double> cppG(n) ; for( int i=0; i<n; ++i ){ std::vector<double> cppX2 = cppX; double step = 3.0 ; cppX2[i] += step ; cppG[i] = (energy_function( cppX2,ctrpoints, edges, gradmap, vecfield ) - e ) / step ; if( isnan(cppG[i]) || !finite( cppG[i] ) ){ std::cout<<"\n"<<energy_function( cppX2,ctrpoints, edges, gradmap, vecfield )<<"\n"<<e<<"\n"<<std::endl; system("pause"); } } // write g for( int i=0; i<n; ++i ) g[i] = cppG[i] ; std::cout<< "g[] = ["; for( size_t i=0; i<cppG.size()-1; ++i ) std::cout<<cppG[i]<<"," ; std::cout<<cppG.back()<<"] "<< std::endl; return e ; }
double anneal_puncturing::perturb() { // choose a set and two positions in that set to swap (one must be punctured, the other transmitted) set = r.ival(s - 1) + 1; do { pos1 = r.ival(tau); } while (pattern(set, pos1)); do { pos2 = r.ival(tau); } while (!pattern(set, pos2)); // do the swap pattern(set, pos1) = true; pattern(set, pos2) = false; // and work out the change in energy energy_function(1, set, pos1); energy_function(-1, set, pos2); // update energy Eold = E; E = work_energy(); double delta = E - Eold; return (delta); }
anneal_puncturing::anneal_puncturing(const char *fname, const int tau, const int s) { // store user parameters anneal_puncturing::tau = tau; anneal_puncturing::s = s; // initialise contribution matrix and load contribution matrix from file contrib.init(s, tau, tau); FILE *file = fopen(fname, "rb"); if (file == NULL) { std::cerr << "FATAL ERROR (anneal_puncturing): Cannot open contribution file (" << fname << ")." << std::endl; exit(1); } for (int i = 0; i < tau; i++) for (int j = 0; j < s; j++) for (int k = 0; k < tau; k++) { double temp; if (fscanf(file, "%lf", &temp) == 0) assertalways(fscanf(file, "%*[^\n]\n") == 0); contrib(j, i, k) = temp; } fclose(file); // initialise the puncturing pattern as odd-even (and transmitting all data bits) { pattern.init(s, tau); for (int i = 0; i < s; i++) for (int j = 0; j < tau; j++) pattern(i, j) = (i == 0 || (i - 1) % 2 == j % 2); } // initialise the working vectors res.init(tau); res = 0; // now work the energy { for (int i = 0; i < s; i++) for (int j = 0; j < tau; j++) if (!pattern(i, j)) energy_function(1, i, j); } // work out the system's initial energy E = work_energy(); }