Fletcher_Reeves共轭梯度算法要先计算梯度,然后对梯度进行修正得到一组共轭梯度。而计算梯度和计算函数值一样耗时。powell算法使用一维搜索技术寻找一组共轭梯度,从而不需要计算梯度。
#include<iostream>
#include<vector>
using namespace std;
vector<vector<double>> V={{1,-1},{1,1}};
vector<vector<double>> A={{4.0,2.0},{2.0,10.0}};
vector<double> B={0,0};
double C=0;
vector<double> mat_vect(const vector<double>& v){
vector<double> ans;
int m=A.size(),n = A[0].size();
for(int i=0;i<m;++i){
for(int j=0;j<1;++j){
double tmp = 0.0;
for(int p=0;p<n;++p) tmp+=A[i][p]*v[p];
ans.push_back(tmp);
}
}
return ans;
}
double get_alpha(const vector<double>& v,const vector<double>& x){
auto tmp1 = mat_vect(x);
auto tmp2 = mat_vect(v);
double ans = 0.0,z = 0.0;
for(int i=0;i<tmp1.size();++i){
tmp1[i]+=B[i];
ans += v[i]*tmp1[i];
z += v[i]*tmp2[i];
}
return -(ans/z);
}
void upgrade(vector<double> &x,const vector<double>& v,const double alpha){
cout<<"Alpha: "<<alpha<<endl<<"X: ";
for(int i=0;i<x.size();++i){
x[i] += alpha*v[i];
cout<<x[i]<<" ";
}
cout<<endl;
}
void powell(vector<double>& x){
vector<double> x_old = x;
int n = x.size();
for(int i=0;i<n;++i){
double alpha = get_alpha(V[i],x);
upgrade(x,V[i],alpha);
if(i+1 < n) V[i] = V[i+1];
}
cout<<"U: ";
for(int i=0;i<n;++i){
V[n-1][i] = x[i]-x_old[i];
cout<<V[n-1][i]<<" ";
}
cout<<endl;
double alpha = get_alpha(V[n-1],x);
upgrade(x,V[n-1],alpha);
}
int main(){
vector<double> x = {20,20};
for(int i=1;i<=2;++i){
cout<<"-------------------------"<<i<<endl;
powell(x);
}
return 0;
}