Healing the Annealing Method


kutta
10-07-2008, 06:31 AM
I shall be thankful to the Author, if the following annealing algorithm is properly dosed with appropriate medicines viz., make it compilable with out errors.
Thanking You
:)
#include <iostream>
#include "nr3.h"
#include "ran.h"
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <fstream.h>
#include<ctype.h>
#define Ranq1
#define myran

int main()
{

struct Anneal{
Anneal();

// Function declaration
void order(VecDoub_I x,VecDoub_I y,VecInt_IO iorder);
Doub revcst(VecDoub_I &x, VecDoub_I &y, VecInt_I &iorder, VecInt_IO &n);
void reverse(VecInt_IO &iorder, VecInt_I &n);
Doub trncst(VecDoub_I &x, VecDoub_I &y, VecInt_I &iorder, VecInt_IO &n);
void trnspt(VecInt_IO &iorder, VecInt_I &n);
bool metrop( double de , double t);
}
int k;
int iorder,n;
double x,y;
cout << "Enter the x " << x;
cin >> x;
cout << "Enter the y "<< y;
cin >> y;
cout << "Enter the n: "<< n;
cin >> n;
cout << "Enter the iorder: "<< iorder;
cin >> iorder;

void order(VecDoub_I x,VecDoub_I y,VecInt_IO iorder);


return 0;
}



void order(VecDoub_I &x,VecDoub_I &y,VecInt_IO &iorder)
{
const Doub TFACTR=0.9;
//step.
Bool ans;
Int i,i1,i2,nn;
VecInt n(6);
//0.5 is the initial temperature.
Doub de,path=0.0,t=0.5;
Int ncity=x.size();
//Maximum number of paths tried at any temperature.
Int nover=100*ncity;
Int nlimit=10*ncit;
// Maximum number of successful path changes bcontinuing.

for (i=0;i<ncity-1;i++) { //Calculate initial path length.
i1=iorder[i];
i2=iorder[i+1];
path += alen(x[i1],x[i2],y[i1],y[i2]);
}
i1=iorder[ncity-1];
i2=iorder[0];
path += alen(x[i1],x[i2],y[i1],y[i2]);
cout << fixed << setprecision(6);
for (Int j=0;j<100;j++) { //Try up to 100 temperature steps.
Int nsucc=0;
for (Int k=0;k<nover;k++) {
do {
// Choose beginning of segment
n[0]=Int(ncity*myran.doub());
//..and end of segment.
//..
n[1]=Int((ncity-1)*myran.doub());
if (n[1] >= n[0]) ++n[1];
//nn is the number of cities
nn=(n[0]-n[1]+ncity-1) % ncity;
// not on the segment.
} while (nn<2);
// Decide whether to do a segment reversal or transport:
// Do a transport.
if (myran.doub() < 0.5) {
n[2]=n[1]+Int(abs(nn-1)*myran.doub())+1;


// Transport tlocation not on the path.
n[2] %= ncity;
// Calculate cost.
de=trncst(x,y,iorder,n);
//Consult the oracle.
ans=metrop(de,t);
if (ans) {
++nsucc;
path += de;
// Carry out transport.
trnspt(iorder,n);
}
// Do a path reversal.
} else {
// Calculate cost.
de=revcst(x,y,iorder,n);
//Consult the oracle.
ans=metrop(de,t);
if (ans) {
++nsucc;
path += de;
//Carry out the reversal.
reverse(iorder,n);
}
}
//Finish early if we have enough suc-
if (nsucc >= nlimit) break;
//cessful changes.
}
cout << endl << "T = " << setw(12) << t;
cout << " Path Length = " << setw(12) << path << endl;
cout << "Successful Moves: " << nsucc << endl;
t *= TFACTR;
// If no success, we are done.
if (nsucc == 0)
return;
}

};

Doub revcst(VecDoub_I &x, VecDoub_I &y, VecInt_I &iorder, VecInt_IO &n)
{
VecDoub xx(4),yy(4);
Int ncity=x.size();
// Find the city before n[0] ..
n[2]=(n[0]+ncity-1) % ncity;
// .. and the city after n[1].
n[3]=(n[1]+1) % ncity;
for (Int j=0;j<4;j++) {
// Find coordinates for the four cities in-
Int ii=iorder[n[j]];
// volved.
xx[j]=x[ii];
yy[j]=y[ii];
}
// Calculate cost of disconnecting
Doub de = -alen(xx[0],xx[2],yy[0],yy[2]);
// the segment at both ends
de -= alen(xx[1],xx[3],yy[1],yy[3]);
// and reconnecting in the op-
de += alen(xx[0],xx[3],yy[0],yy[3]);
// posite order.
de += alen(xx[1],xx[2],yy[1],yy[2]);
return de;
}

void reverse(VecInt_IO &iorder, VecInt_I &n)
{
Int ncity=iorder.size();
Int nn=(1+((n[1]-n[0]+ncity) % ncity))/2; //This many cities must be swapped
//to e?ect the reversal.
for (Int j=0;j<nn;j++) {
//Start at the ends of the segment and
Int k=(n[0]+j) % ncity;
// swap pairs of cities, moving to-
Int l=(n[1]-j+ncity) % ncity;
// ward the center.
Int itmp=iorder[k];
iorder[k]=iorder[l];
iorder[l]=itmp;
}
}

Doub trncst(VecDoub_I &x, VecDoub_I &y, VecInt_I &iorder, VecInt_IO &n)

{
VecDoub xx(6),yy(6);
Int ncity=x.size();
// .. Find the city following n[2]..
n[3]=(n[2]+1) % ncity;
// ..and the one preceding n[0]..
n[4]=(n[0]+ncity-1) % ncity;
// ..and the one following n[1].
n[5]=(n[1]+1) % ncity;
for (Int j=0;j<6;j++) {
// Determine coordinates for the six cities
Int ii=iorder[n[j]];
// involved.
xx[j]=x[ii];
yy[j]=y[ii];
}
Doub de = -alen(xx[1],xx[5],yy[1],yy[5]);
// Calculate the cost of disconnecting
// the path segment from n[0] to
de -= alen(xx[0],xx[4],yy[0],yy[4]);
// n[1], opening a space between
de -= alen(xx[2],xx[3],yy[2],yy[3]);
// n[2] and n[3], connecting the
de += alen(xx[0],xx[2],yy[0],yy[2]);
//segment in the space, and con-
de += alen(xx[1],xx[3],yy[1],yy[3]);
// necting n[4] to n[5].
de += alen(xx[4],xx[5],yy[4],yy[5]);
return de;
}

void trnspt(VecInt_IO &iorder, VecInt_I &n)

{
Int ncity=iorder.size();
VecInt jorder(ncity);
// Find number of cities from n[0] to n[1]
Int m1=(n[1]-n[0]+ncity) % ncity;
//...and the number from n[3] to n[4]
Int m2=(n[4]-n[3]+ncity) % ncity;
//...and the number from n[5] to n[2].
Int m3=(n[2]-n[5]+ncity) % ncity;
Int nn=0;
for (Int j=0;j<=m1;j++) {
//Copy the chosen segment.
Int jj=(j+n[0]) % ncity;
jorder[nn++]=iorder[jj];
}
// Then copy the segment from n[3] to
for (Int j=0;j<=m2;j++) {
Int jj=(j+n[3]) % ncity; // n[4].
jorder[nn++]=iorder[jj];
}
// Finally, the segment from n[5] to n[2].
for (Int j=0;j<=m3;j++) {
Int jj=(j+n[5]) % ncity;
jorder[nn++]=iorder[jj];
}
// Copy jorder back into iorder.
for (Int j=0;j<ncity;j++)
iorder[j]=jorder[j];
}
bool metrop( Doub de , Doub t)
{
return de < 0.0 || ( myran.doub() < exp(-de/t));
}

[/CODE]

davekw7x
10-22-2008, 10:22 AM
...make it compilable

Here is a way to use the Numerical Recipes, Version 3, Anneal object on something like a "traveling salesman's" problem:

1. Create vectors of doubles, x and y, for the coordinates of the cities. There will be one x and one y entry for each city visited. Populate the vectors with coordinates of the cities.

2. Create a vector of ints, iorder, for the sequence in which the cities will be visited. This will be changed by the order() function so that its values will be the indices of x,y for the path. Unless you have some particular reason to give a specific initial path, just initialize this vector with 0, 1, 2, ...

3. Create an object of type Anneal.

4. Call that object's order() function with arguments x, y and iorder.

Here's an example that generates random coordinates for ten cities and uses the order() function of an Anneal object:


// Driver for routine anneal

#include "../code/nr3.h"
#include "../code/ran.h"
#include "../code/anneal.h"

//
// Print path and distances
//
void printall(VecDoub x, VecDoub y, VecInt iorder, Int n);

int main()
{
Ran myRan(12345678); // For debugging, use the same seed every time
//Ran myRan(time(0)); // For exploration, use different seeds

Int ncity = 10;
VecInt iorder(ncity);
VecDoub x(ncity), y(ncity);

for (Int i = 0; i < ncity; i++) {
x[i] = myRan.doub();
y[i] = myRan.doub();
iorder[i] = i;
}

cout << endl << "Initial ";
printall(x, y, iorder, ncity);

Anneal a;

a.order(x, y, iorder);

cout << endl << "Final ";
printall(x, y, iorder, ncity);

return 0;
}
void printall(VecDoub x, VecDoub y, VecInt iorder, Int n)
{
Int i, ii, iii, iiip;
Doub sum = 0;
Doub dist;
cout << "Path:" << endl;
cout << setw(5) << "City" << setw(8) << "x" << setw(11) << "y" << endl;
cout << fixed << setprecision(4);
for (i = 0; i < n; i++) {
ii = iorder[i];
cout << setw(4) << ii << setw(11) << x[ii];
cout << setw(11) << y[ii] << endl;
}
// Print out distances for each step
cout << endl;
cout << setw(5) << "Leg"
<< setw(11) << "Distance" << setw(9) << "Total" << endl;
for (i = 0; i < n - 1; i++) {
iii = iorder[i];
iiip = iorder[i + 1];
dist = sqrt(SQR(x[iiip] - x[iii]) + SQR(y[iiip] - y[iii]));
sum += dist;
cout << setw(3) << iii << "-" << iiip
<< setw(10) << dist << setw(11) << sum << endl;

}
cout << endl << endl;
}


Output from my system (GNU g++ version 4.1.2 on Linux):

Initial Path:
City x y
0 0.6224 0.1154
1 0.7751 0.4490
2 0.4455 0.7149
3 0.5977 0.5332
4 0.0376 0.0917
5 0.8665 0.2329
6 0.8015 0.7665
7 0.8480 0.7325
8 0.8542 0.8148
9 0.8675 0.8307

Leg Distance Total
0-1 0.3669 0.3669
1-2 0.4234 0.7903
2-3 0.2370 1.0273
3-4 0.7132 1.7406
4-5 0.8408 2.5814
5-6 0.5376 3.1190
6-7 0.0576 3.1766
7-8 0.0825 3.2592
8-9 0.0207 3.2799

T = 0.500000 Path Length = 4.090823
Successful Moves: 100

T = 0.450000 Path Length = 4.411241
Successful Moves: 100

Something like 60 similar messages from order()

T = 0.000809 Path Length = 2.867562
Successful Moves: 2

T = 0.000728 Path Length = 2.867562
Successful Moves: 2

T = 0.000655 Path Length = 2.867562
Successful Moves: 0

Final Path:
City x y
7 0.8480 0.7325
1 0.7751 0.4490
5 0.8665 0.2329
0 0.6224 0.1154
4 0.0376 0.0917
2 0.4455 0.7149
3 0.5977 0.5332
6 0.8015 0.7665
8 0.8542 0.8148
9 0.8675 0.8307

Leg Distance Total
7-1 0.2928 0.2928
1-5 0.2347 0.5274
5-0 0.2709 0.7983
0-4 0.5853 1.3836
4-2 0.7449 2.1285
2-3 0.2370 2.3655
3-6 0.3097 2.6753
6-8 0.0715 2.7468
8-9 0.0207 2.7675



Regards,

Dave

kutta
11-02-2008, 07:48 AM
Here is a way to use the Numerical Recipes, Version 3, Anneal object on something like a "traveling salesman's" problem:

1. Create vectors of doubles, x and y, for the coordinates of the cities. There will be one x and one y entry for each city visited. Populate the vectors with coordinates of the cities.

2. Create a vector of ints, iorder, for the sequence in which the cities will be visited. This will be changed by the order() function so that its values will be the indices of x,y for the path. Unless you have some particular reason to give a specific initial path, just initialize this vector with 0, 1, 2, ...

3. Create an object of type Anneal.

4. Call that object's order() function with arguments x, y and iorder.

Here's an example that generates random coordinates for ten cities and uses the order() function of an Anneal object:


// Driver for routine anneal

#include "../code/nr3.h"
#include "../code/ran.h"
#include "../code/anneal.h"

//
// Print path and distances
//
void printall(VecDoub x, VecDoub y, VecInt iorder, Int n);

int main()
{
Ran myRan(12345678); // For debugging, use the same seed every time
//Ran myRan(time(0)); // For exploration, use different seeds

Int ncity = 10;
VecInt iorder(ncity);
VecDoub x(ncity), y(ncity);

for (Int i = 0; i < ncity; i++) {
x[i] = myRan.doub();
y[i] = myRan.doub();
iorder[i] = i;
}

cout << endl << "Initial ";
printall(x, y, iorder, ncity);

Anneal a;

a.order(x, y, iorder);

cout << endl << "Final ";
printall(x, y, iorder, ncity);

return 0;
}
void printall(VecDoub x, VecDoub y, VecInt iorder, Int n)
{
Int i, ii, iii, iiip;
Doub sum = 0;
Doub dist;
cout << "Path:" << endl;
cout << setw(5) << "City" << setw(8) << "x" << setw(11) << "y" << endl;
cout << fixed << setprecision(4);
for (i = 0; i < n; i++) {
ii = iorder[i];
cout << setw(4) << ii << setw(11) << x[ii];
cout << setw(11) << y[ii] << endl;
}
// Print out distances for each step
cout << endl;
cout << setw(5) << "Leg"
<< setw(11) << "Distance" << setw(9) << "Total" << endl;
for (i = 0; i < n - 1; i++) {
iii = iorder[i];
iiip = iorder[i + 1];
dist = sqrt(SQR(x[iiip] - x[iii]) + SQR(y[iiip] - y[iii]));
sum += dist;
cout << setw(3) << iii << "-" << iiip
<< setw(10) << dist << setw(11) << sum << endl;

}
cout << endl << endl;
}


Output from my system (GNU g++ version 4.1.2 on Linux):

Initial Path:
City x y
0 0.6224 0.1154
1 0.7751 0.4490
2 0.4455 0.7149
3 0.5977 0.5332
4 0.0376 0.0917
5 0.8665 0.2329
6 0.8015 0.7665
7 0.8480 0.7325
8 0.8542 0.8148
9 0.8675 0.8307

Leg Distance Total
0-1 0.3669 0.3669
1-2 0.4234 0.7903
2-3 0.2370 1.0273
3-4 0.7132 1.7406
4-5 0.8408 2.5814
5-6 0.5376 3.1190
6-7 0.0576 3.1766
7-8 0.0825 3.2592
8-9 0.0207 3.2799

T = 0.500000 Path Length = 4.090823
Successful Moves: 100

T = 0.450000 Path Length = 4.411241
Successful Moves: 100

Something like 60 similar messages from order()

T = 0.000809 Path Length = 2.867562
Successful Moves: 2

T = 0.000728 Path Length = 2.867562
Successful Moves: 2

T = 0.000655 Path Length = 2.867562
Successful Moves: 0

Final Path:
City x y
7 0.8480 0.7325
1 0.7751 0.4490
5 0.8665 0.2329
0 0.6224 0.1154
4 0.0376 0.0917
2 0.4455 0.7149
3 0.5977 0.5332
6 0.8015 0.7665
8 0.8542 0.8148
9 0.8675 0.8307

Leg Distance Total
7-1 0.2928 0.2928
1-5 0.2347 0.5274
5-0 0.2709 0.7983
0-4 0.5853 1.3836
4-2 0.7449 2.1285
2-3 0.2370 2.3655
3-6 0.3097 2.6753
6-8 0.0715 2.7468
8-9 0.0207 2.7675



Regards,

Dave

Hello Comrade
Indeed your suggested procedure was succesfully compiled and executed.In this connection, I would extend my request to the author of NR to allocate a section or a unit in this forum of NR,to inculcate the various applications-areas (real life problems of NR) and their details from the users of NR
(Registered )which will definitely help all to accordingly have a comprehensive knowledge of NR and its merits of usages.
As a token of good will i now forward a recent letter that i have tried to put up to letters to the editor of a news paper .

Though a beginner in this regard, please give your feedback if i am right in the path.
Also as MechanicalEngineer by way of qualification,i have no less usages of this newly intoduced algorithmic concept in the realworld problems at NR, since annealing is replacing the tradional algorithms that were existing for TravellingSalesMan Please also accept my thanks for your solved method of this exhilarating method of Thermodynamics

Thanks
As
Kutta

;)