我正在尝试提出一个程序,该程序可以在2-dy坐标系上找到正确的顶点位置,给定距离矩阵(或邻接列表),表示边距权重的距离。
最初我写了一个暴力搜索。然后,我决定修改一个C ++程序来解决AB = C矩阵方程,这是我之前做过的,以解决这个问题。
输入: 距离矩阵
输出: 考虑边缘权重作为2d-xy平面中两个顶点之间距离的满足给定距离矩阵的顶点坐标。
这是我的程序的示例运行:
The original adjacency matrix:
0 1 1.41 1
1 0 1 1.41
1.41 1 0 1
1 1.41 1 0
The coordinates which can satisfy the given input adjacency matrix with edge weight denoting distance are :
[24.327,0.40545]
[25.5472,0.425787]
[25.5306,1.42551]
[24.3103,1.40517]
The calculated adjacency matrix from the solution we got from CrossEntropy Method is :
0 1.10473 1.25607 0.999931
1.10473 0 0.999931 1.25607
1.25607 0.999931 0 1.10473
0.999931 1.25607 1.10473 0
现在,我可以看到它提供了一个近似的解决方案。或者我可以说它正在尝试。但它并不令人满意。当我查看每次迭代的适应性时,在最初的几个步骤之后它几乎是恒定的。这意味着健康状况没有太大改善。
的假设 1.我的程序随机生成了邻接矩阵。 2.适应度变量与代码中的含义相反。适应度越高,解决方案的质量越低
我的问题是>>如何调整这个程序,以便产生更好的结果(我试图改变学习速度和样本数量,但那里没有太大的成功)。我做错了什么以及如何使它更准确。有没有其他简单的方法来做到这一点,我的意思是从邻接矩阵获取坐标的整个问题?
这段代码是这样的:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<climits>
#include<ctime>
#include<iostream>
using namespace std;
#define UPPER_LIMIT 20 // this is the upper limit to the distances given in adjacency matrix,
const int SQSZ= UPPER_LIMIT*3; // this is half the size of our finite cartesian coordiante system , which will go from 0 to 2*SQSZ in x as well as y
double SQR(double X ) { return X*X ; }
#define LOWER_BOUND -SQSZ
#define UPPER_BOUND SQSZ
#define num_samples 100 //number of samples we want to generate in every iteration, our population count
#define num_update 5 //number of top members of population we are taking to modify our distribution
#define max_iter 200 //total number of iterations
#define problem_size 4 // number of vertices in graph
#define alpha 0.7 //learning rate
struct sample{
double arr[problem_size];
double cost;
};
typedef struct sample sample;
const int n = problem_size,m = problem_size;
double a[m][n] , b[m];
sample best;
sample samples[num_samples];
sample selected[num_update];
double means[problem_size];
double stdev[problem_size];
/* the following function takes the input adjacency , */
int take_input()
{
srand(time(NULL));
/*
for(int i =0; i< m; i++)
for(int j =0; j<n; j++)
if( i > j ) a[i][j] = a[j][i] = rand()%UPPER_LIMIT;
else a[i][j] = a[j][i] = 0;
*/
cout<<"Input the distance matrix of size "<< problem_size<<"X"<<problem_size<<endl;
for(int i =0 ; i< m ; i++)
for(int j =0; j <n ; j++){
cin >> a[i][j];
}
// for(int i =0; i< m; i++)
// scanf("%lf",&b[i]);
}
void print_matrix()
{
for(int i =0; i<m ; i++,printf("\n"))
for(int j =0 ; j<n; j++)
cout << a[i][j] << " ";
cout<<endl;
}
// what I am doing here is treating each value in a single sample as a creator of x,y corrdinate, by using fmod and division.
double dist(double a,double b)
{
// cout<<"dist("<<a<<" "<<b<<")" << endl;
double ax,ay,bx,by;
ax = fmod(a,SQSZ);
ay = a/SQSZ;
bx = fmod(b,SQSZ);
by = b/SQSZ;
return sqrt(hypot((ax-bx), (ay-by) ));
}
// just to decompose the sample value into x and y coordinate and print it
void decom(double a)
{
double x = fmod(a,SQSZ);
double y = a/SQSZ;
cout <<"["<< x<< "," << y << "]" << endl;
}
/* simple comparision function to compare cost */
bool cmp( sample a , sample b )
{
if( a.cost < b.cost )
return true;
else
return false;
}
/* find average of means of best part of population */
double mean_attr(int x )
{
double sum = 0.0;
for(int i=0; i< num_update; i++)
sum += selected[i].arr[x];
return sum / num_update;
}
/* find the average standard deviation for best part of population */
double stdev_attr(int x,double mean)
{
double sum = 0.0;
for(int i =0; i<num_update; i++)
sum += (selected[i].arr[x] - mean)*(selected[i].arr[x] - mean);
return sqrt( sum / num_update);
}
/* returns a random number between a to b */
double random_variable(double a ,double b){
return a + (( b - a )*((double)rand()/RAND_MAX) );
}
/* returns a value depending on mean and stdev according to gaussian distribution fucntion */
double random_gaussian(double mean , double stdev)
{
double u1,u2,w;
do {
u1 = 2*((double)rand()/RAND_MAX) - 1;
u2 = 2*((double)rand()/RAND_MAX) - 1;
w = u1*u1 + u2 * u2;
} while( w >= 1 );
w = sqrt(( -2.0 * log(w ))/w);
return mean + ( u2* w ) * stdev;
}
/* evaluate our samples , returns the cost of our solution */
double evaluate(int x)
{
double sum = 0.0;
// double delta_array[m];
for(int i =0; i<m ; i++)
for(int j =0; j< n; j++)
{
double y = 0.0;
y = a[i][j] - dist( samples[x].arr[i] +SQSZ, samples[x].arr[j] + SQSZ );
sum += y*y;
// cout << "hii there" << y*y << endl;
// fflush(stdout);
// system("sleep 0.1");
}
/*
for( int i =0; i< m; i++)
{
delta_array[i] = 0.0;
for(int j =0; j<n; j++)
delta_array[i] = ( delta_array[i] + ( (a[i][j]) *samples[x].arr[j] ));
delta_array[i] =delta_array[i] - b[i];
sum += delta_array[i] * delta_array[i];
}
*/
return sum;
}
int main()
{
take_input();
best.cost = -1; // intially we don't have any best , so its initial value is -1
// cout<<"Given random adjacency matrix"<<endl;
// print_matrix();
for(int i =0; i< problem_size; i++){
means[i] = random_variable(LOWER_BOUND,UPPER_BOUND);
stdev[i] = UPPER_BOUND - LOWER_BOUND;
}
for(int iter =0; iter < max_iter ; iter++ )
{
for(int i =0; i< num_samples; i++)
{
for(int j=0; j< problem_size; j++)
{
samples[i].arr[j] = random_gaussian(means[j],stdev[j]);
if( samples[i].arr[j] < LOWER_BOUND ) samples[i].arr[j] = LOWER_BOUND;
if( samples[i].arr[j] > UPPER_BOUND ) samples[i].arr[j] = UPPER_BOUND;
}
samples[i].cost = evaluate(i);
}
sort( samples,samples+num_samples,cmp);
if( best.cost == -1 || best.cost > samples[0].cost )
{
best.cost = samples[0].cost;
for(int i=0; i<problem_size; i++)
best.arr[i] = samples[0].arr[i];
}
for(int j=0; j< num_update;j++){
selected[j].cost = samples[j].cost;
for(int k =0; k< problem_size; k++)
selected[j].arr[k] = samples[j].arr[k];
}
for(int j=0; j< problem_size; j++)
{
means[j] = alpha*means[j] + ( 1.0 - alpha) * mean_attr(j);
stdev[j] = alpha*stdev[j] + ( 1.0 - alpha) * stdev_attr(j,means[j]);
}
// printf(" > iteration = %d , fitness = %lf\n",iter,best.cost );
fflush(stdout);
}
//printf("Solution : f = %lf\n",best.cost );
cout<<"The original adjacency matrix:"<< endl;
print_matrix();
cout << "The coordinates which can satisfy the given input adjacency matrix with edge weight denoting distance are :"<< endl;
for(int i =0; i< problem_size; i++)
decom(best.arr[i] + SQSZ);
cout<<endl;
cout<<"The calculated adjacency matrix from the solution we got from CrossEntropy Method is :"<<endl;
// printing our solutions adjacency matrix
for(int i =0; i<n; i++,printf("\n"))
for(int j =0 ; j<m ;j++)
cout << dist(best.arr[i] +SQSZ, best.arr[j] + SQSZ)<< " ";
cout<<endl;
return 0;
}
提前感谢你:)。
更新:
我设置了一个简单的距离矩阵,即输入中的单位平方,它给出了正确的结果。但我真的不知道如何测试我的程序,因为生成这样的图形对我来说是另一个问题。