优化方法(C++)——0.618法、平均值法、单纯形法

来源:互联网 发布:碳足迹 水足迹 数据 编辑:程序博客网 时间:2024/06/05 18:09

1、0.618法

// 0.618.cpp : 优化方法:0.618法确定一维搜索问题的搜索区间。//#include "stdio.h"#include "iostream"#include "math.h"using namespace std;//#define Lambda 0.618double f(double x)  //输入 min f(x)  f(x)的函数体{    return (x*x-1)*(x*x-1);    //return exp(-x)+x*x;}void main(){    double a, b, Epsilon;    double Lambda, Mu;    a=2, b=5;    Epsilon=0.5;    //cout<<"输入搜索区间左值:\n";    //cin>>a;    //cout<<"输入搜索区间右值:\n";    //cin>>b;    Lambda=a+(1-0.618)*(b-a);    Mu=a+0.618*(b-a);        while((b-a)>=Epsilon)        {            if(f(Lambda)>f(Mu))//步骤3            {            a=Lambda;            b=b;            Lambda=Mu;            Mu=a+0.618*(b-a);            }            else //步骤4            {            a=a;            b=Mu;            Mu=Lambda;            Lambda=a+(1-0.618)*(b-a);            }        }        cout<<"搜索区间为:["<<a<<","<<b<<"]"<<"\n"<<"最优解为:"<<(a+b)/2<<"\n";        system("pause");    return ;}

2、平均值法

// mean.cpp : 优化方法:平均法确定一维搜索问题的搜索区间。//#include "stdio.h"#include "iostream"#include "math.h"using namespace std;double f(double x) ;double d_f(double x);void main(){    double a, b, Epsilon;    double x0;    Epsilon=0.001;    cout<<"输入搜索区间左值:\n";    cin>>a;    cout<<"输入搜索区间右值:\n";    cin>>b;    if(d_f(a)<0 && d_f(b)>0)    {        x0=(a+b)/2;        while(fabs(d_f(x0))>Epsilon)        {            x0=(a+b)/2;            if(d_f(x0)>0)            {            b=x0;            }            else            {            a=x0;            }        }        cout<<"最优解为:"<<x0<<"\n";    }    else    {        cout<<"该区间内不存在最优解 \n";      }       return ;}double f(double x)  //输入 min f(x)  f(x)的函数体{    //return x*x+2.0*x;    //return exp(-x)+x*x;    //return x*x*x*x/4-4*x*x*x/3+5*x*x/2-2*x;    return 3*x*x*x*x-16*x*x*x+30*x*x-24*x+8;}double d_f(double x){    double Delte=0.00001;    return (f(x+Delte)-f(x))/Delte;}

3、单纯形法

 //simplex.cpp : 单纯形法。//ex1、ex2#include "stdio.h"#include "iostream"#include <vector>using namespace std;#define m 3  //初始表大小:m行n列 (m<n)#define n 5//*************************************************************************************double A[m][n], b[m], C[n], c[n], A2[m][n];//c[n] 标准型的目标函数系数int BaseVariable[m];    //基变量int NotBaseVariable[n-m];   //非基变量int ArtificalVariable[m];   //人工变量double f=0;int C_min_mark;int b_min_mark;double r[n];//二阶段法的向量rvoid input2();void input2(double **a,int len1,int len2);void input();void input(double **a,int len1,int len2);void output();void output(double **a,int len1,int len2);double determine();double determine(int len1,int len2);double determine2();double determine2(int len1,int len2);void exchange();void newexchange(double **a,int len1,int len2);void one_stage();void two_stage();void two_stage2();void main(){    one_stage();//一阶段    //two_stage();//两阶段    system("pause");    return ;}void two_stage2(){    input2();    //double a[m][n];    //input2((double **)a,m,n);    output();    //output((double**)a,m,n);    while(determine2())        {            exchange();            //newexchange((double**)a,m,n);            output();        }    if(f==0)        {            //double a2[m][n-m];            //for(int i=0;i<m;i++)            //  for(int j=0;j<n-m;j++)            //      (*((int *)a2+i*m+j))=(*((int *)a+i*m+j));            //int k=0,K[n-m-m];            //for(int i=0;i<n-m;i++)            //{            //              //  for(int j=0;j<m;j++)            //  {            //      if(NotBaseVariable[j]!=BaseVariable[i])            //          K[k];            //  }            //}            //while(determine(m,n-m))            //  {            //  newexchange((double**)a2,m,n-m);            //  output((double**)a,m-m,n-m);            //  }            cout<<"最优解f为:\n"<<-f<<endl;        }    else        cout<<"原问题无可行解,故无最优解. \n"<<endl;    }void two_stage(){    double a[m][n];    input2((double **)a,m,n);    output((double**)a,m,n);    while(determine2(m,n))        {            newexchange((double**)a,m,n);            output((double**)a,m,n);        }    if(f==0)        {            double a2[m][n-m];            for(int i=0;i<m;i++)                for(int j=0;j<n-m;j++)                    (*((int *)a2+i*n+j))=(*((int *)a+i*n+j));            while(determine(m,n-m))                {                newexchange((double**)a2,m,n-m);                output((double**)a,m-m,n-m);                }            cout<<"最优解f为:\n"<<-f<<endl;        }    else        cout<<"原问题无可行解,故无最优解. \n"<<endl;    }void one_stage()//一阶段单纯形法{    double a[m][n];    //input();    input((double**)a,m,n);    //output();    output((double**)a,m,n);    while(!determine())        {            //exchange();            newexchange((double**)a,m,n);            output((double**)a,m,n);        }    cout<<"最优解f为:\n"<<-f<<endl;}void input2(double **a,int len1,int len2)   //输入A[m][n], b[m], C[m],并确定基变量BaseVariable[m]{    //double a[len1][len2];    cout<<"输入系数矩阵A:\n";    for(int i=0;i<len1;i++)    {        for(int j=0;j<len2;j++)        {            cout<<"A["<<i<<"]"<<"["<<j<<"]=";            {                cin>>(*((int *)a+i*len2+j));                //A[i][j]=(*((int *)a+i*len1+j));            }        }        cout<<"\n";    }    cout<<"输入右端项b:\n";    for(int i=0;i<len1;i++)    {        cout<<"b["<<i<<"]=";        cin>>b[i];    }    int j=0,k=0;    for(int i=0;i<len2;i++)    {        if(i<len2-len1)        {            C[i]=0;            NotBaseVariable[j]=i;            j++;        }        else        {            C[i]=1;            BaseVariable[k]=i;            ArtificalVariable[k]=i;//记录人工变量            k++;        }    }    for(int j=0;j<len2;j++)    {        for(int i=0;i<len1;i++)            C[j]=C[j]-(*((int *)a+i*len2+j));//即  C0[n]->r[n]  过程    }    for(int i=0;i<len1;i++)    {        f=f-b[i];    }    cout<<"输入标准型的目标函数系数 C:\n";    for(int i=0;i<len2-len1;i++)    {        cout<<"c["<<i<<"]=";        cin>>c[i];    }}void input()  //输入A[m][n], b[m], C[m],并确定基变量BaseVariable[m]{    cout<<"输入系数矩阵A:\n";    for(int i=0;i<m;i++)    {        for(int j=0;j<n;j++)        {            cout<<"A["<<i<<"]"<<"["<<j<<"]=";            cin>>A[i][j];        }        cout<<"\n";    }    cout<<"输入右端项b:\n";    for(int i=0;i<m;i++)    {        cout<<"b["<<i<<"]=";        cin>>b[i];    }    cout<<"输入约束条件系数C:\n";    int j=0,k=0;    for(int i=0;i<n;i++)    {        cout<<"C["<<i<<"]=";        cin>>C[i];        if(C[i]==0)        {            BaseVariable[j]=i;          //确定基变量 x2 x3 x4            j++;        }        else            {            NotBaseVariable[k]=i;       //确定非基变量 x0 x1            k++;        }    }}void output(){    cout<<"矩阵A为:\n";    for(int i=0;i<m;i++)        {            for(int j=0;j<n;j++)            cout<<A[i][j]<<"    ";            cout<<"\n";        }    cout<<"右端项b:\n";    for(int i=0;i<m;i++)        {            cout<<b[i]<<"   ";        }    cout<<"\n";    cout<<"约束条件系数C:\n";    for(int i=0;i<n;i++)        {            cout<<C[i]<<"   ";        }    cout<<"\n";    cout<<"f="<<f<<"\n";}double determine2(){    int BaseVariableIncludeArtificalVariable=0;    for(int i=0;i<m;i++)    {        for(int j=0;j<m;j++)        {            if(BaseVariable[i]==ArtificalVariable[j])                BaseVariableIncludeArtificalVariable++;        }    }    if(BaseVariableIncludeArtificalVariable)//基变量中若含有人工变量则继续交换        return 1;    else        return 0;}double determine()//判定C{    int C_BaseVariable_M0=0, C_BaseVariable_L0=0, C_BaseVariable_E0=0;    int C_NotBaseVariable_M0=0, C_NotBaseVariable_L0=0, C_NotBaseVariable_E0=0;//大于、小于、等于M L E    //double C_min=0;    for(int i=0;i<m;i++)    {        if(C[BaseVariable[i]]==0)            C_BaseVariable_E0++;        else        {            if(C[BaseVariable[i]]<0)                C_BaseVariable_L0++;            else                C_BaseVariable_M0++;        }    }    for(int i=0;i<(n-m);i++)    {        if(C[NotBaseVariable[i]]>0)            C_NotBaseVariable_M0++;        else        {            if(C[NotBaseVariable[i]]<0)            {                C_NotBaseVariable_L0++;            }               else                C_NotBaseVariable_E0++;        }               }    if(C_BaseVariable_E0==m && C_NotBaseVariable_L0==0)//基变量的检验数都等于0,非基变量的检验数都大于0        return 1;    if(C_BaseVariable_E0==m && C_NotBaseVariable_L0!=0)//基变量的检验数都等于0,非基变量的检验数都大于0        return 0;}void exchange(){    double C_min=C[0];    int C_min_mark=0;    for(int i=0;i<sizeof(C)/sizeof(double);i++)    {        if(C[i]<C_min)        {            C_min=C[i];            C_min_mark=i;        }    }    double b_min;    for(int i=0;i<m;i++)    {        if(A[i][C_min_mark]!=0 && b[i]/A[i][C_min_mark]>0)        {            b_min=b[i]/A[i][C_min_mark]; //记录min(b[m])的下标            b_min_mark=i;            for(int j=i;j<m;j++)            {                if(A[j][C_min_mark]!=0 && b[j]/A[j][C_min_mark]>0 && b[j]/A[j][C_min_mark]<b_min)//0与负数不参加比值                {                    b_min=b[j]/A[j][C_min_mark];//记录min(b[m])的下标                    b_min_mark=j;                }            }            break;        }    }    //确定主元A[b_min_mark][C_min_mark]    double A0[m][n], C0[n];    for(int i=0;i<m;i++)    {        for(int j=0;j<n;j++)        {            A0[i][j]=A[i][j];        }    }    for(int j=0;j<n;j++)    {        C0[j]=C[j];    }    for(int i=0;i<m;i++)    {        if(i!=b_min_mark && A[i][C_min_mark]!=0)//主元所在行不变;        {            for(int j=0;j<n;j++)            {                A0[i][j]=A[i][j]-1.0*A[b_min_mark][j]*A[i][C_min_mark]/A[b_min_mark][C_min_mark];//利用主元将对应列消去;            }                b[i]=b[i]-b[b_min_mark]*A[i][C_min_mark]/A[b_min_mark][C_min_mark];        }       }    for(int i=0;i<m;i++)    {        for(int j=0;j<n;j++)        {            A[i][j]=A0[i][j];        }    }    f=f-1.0*b[b_min_mark]*C[C_min_mark]/A[b_min_mark][C_min_mark];    for(int j=0;j<n;j++)    {        C0[j]=C[j]-A[b_min_mark][j]*C[C_min_mark]/A[b_min_mark][C_min_mark];        }    for(int j=0;j<n;j++)    {        C[j]=C0[j];    }    NotBaseVariable[C_min_mark]=BaseVariable[b_min_mark];    BaseVariable[b_min_mark]=C_min_mark; // x C_min_mark进基,x b_min_mark出基}void exchange2(){    double C_min=C[0];    int C_min_mark=0;    for(int i=0;i<sizeof(C)/sizeof(double);i++)    {        if(C[i]<C_min)        {            C_min=C[i];            C_min_mark=i;        }    }    double b_min;    for(int i=0;i<m;i++)    {        if(A2[i][C_min_mark]!=0 && b[i]/A2[i][C_min_mark]>0)        {            b_min=b[i]/A2[i][C_min_mark]; //记录min(b[m])的下标            b_min_mark=i;            for(int j=i;j<m;j++)            {                if(A2[j][C_min_mark]!=0 && b[j]/A2[j][C_min_mark]>0 && b[j]/A2[j][C_min_mark]<b_min)//0与负数不参加比值                {                    b_min=b[j]/A2[j][C_min_mark];//记录min(b[m])的下标                    b_min_mark=j;                }            }            break;        }    }    //确定主元A[b_min_mark][C_min_mark]    double A0[m][n], C0[n];    for(int i=0;i<m;i++)    {        for(int j=0;j<n;j++)        {            A0[i][j]=A2[i][j];        }    }    for(int j=0;j<n;j++)    {        C0[j]=C[j];    }    for(int i=0;i<m;i++)    {        if(i!=b_min_mark && A2[i][C_min_mark]!=0)//主元所在行不变;        {            for(int j=0;j<n;j++)            {                A0[i][j]=A2[i][j]-1.0*A2[b_min_mark][j]*A2[i][C_min_mark]/A2[b_min_mark][C_min_mark];//利用主元将对应列消去;            }                b[i]=b[i]-b[b_min_mark]*A2[i][C_min_mark]/A2[b_min_mark][C_min_mark];        }       }    for(int i=0;i<m;i++)    {        for(int j=0;j<n;j++)        {            A2[i][j]=A0[i][j];        }    }    f=f-1.0*b[b_min_mark]*C[C_min_mark]/A2[b_min_mark][C_min_mark];    for(int j=0;j<n;j++)    {        C0[j]=C[j]-A2[b_min_mark][j]*C[C_min_mark]/A2[b_min_mark][C_min_mark];      }    for(int j=0;j<n;j++)    {        C[j]=C0[j];    }    NotBaseVariable[C_min_mark]=BaseVariable[b_min_mark];    BaseVariable[b_min_mark]=C_min_mark; // x C_min_mark进基,x b_min_mark出基}void newexchange(double **a,int len1,int len2)//    len1=m, len2=n      ((int *)a+i*len1+j))=A2[i][j]{    double C_min=C[0];    int C_min_mark=0;    for(int i=0;i<sizeof(C)/sizeof(double);i++)    {        if(C[i]<C_min)        {            C_min=C[i];            C_min_mark=i;        }    }    double b_min;    for(int i=0;i<len1;i++)    {        if((*((int *)a+i*len2+C_min_mark))!=0 && b[i]/(*((int *)a+i*len2+C_min_mark))>0)    //A2[i][C_min_mark]=(*((int *)a+i*len1+C_min_mark))        {            b_min=b[i]/(*((int *)a+i*len2+C_min_mark)); //记录min(b[m])的下标            b_min_mark=i;            for(int j=i;j<len1;j++)            {                if((*((int *)a+j*len2+C_min_mark))!=0 && b[j]/(*((int *)a+j*len2+C_min_mark))>0 && b[j]/(*((int *)a+j*len2+C_min_mark))<b_min)//0与负数不参加比值                {                    b_min=b[j]/(*((int *)a+j*len2+C_min_mark));//记录min(b[m])的下标                    b_min_mark=j;                }            }            break;        }    }    //确定主元A[b_min_mark][C_min_mark]    double A0[m][n], C0[n];    for(int i=0;i<len1;i++)    {        for(int j=0;j<len2;j++)        {            A0[i][j]=(*((int *)a+i*len2+j));        }    }    for(int j=0;j<len2;j++)    {        C0[j]=C[j];    }    for(int i=0;i<len1;i++)    {        if(i!=b_min_mark && (*((int *)a+i*len1+C_min_mark))!=0)//主元所在行不变;        {            for(int j=0;j<len2;j++)            {                A0[i][j]=(*((int *)a+i*len2+j))-1.0*(*((int *)a+b_min_mark*len2+j))*(*((int *)a+i*len2+C_min_mark))/(*((int *)a+b_min_mark*len2+C_min_mark));//利用主元将对应列消去;            }            b[i]=b[i]-b[b_min_mark]*(*((int *)a+i*len2+C_min_mark))/(*((int *)a+b_min_mark*len2+C_min_mark));        }       }    for(int i=0;i<len1;i++)    {        for(int j=0;j<len2;j++)        {            (*((int *)a+i*len2+j))=A0[i][j];        }    }    f=f-1.0*b[b_min_mark]*C[C_min_mark]/(*((int *)a+b_min_mark*len2+C_min_mark));    for(int j=0;j<len2;j++)    {        C0[j]=C[j]-(*((int *)a+b_min_mark*len2+j))*C[C_min_mark]/(*((int *)a+b_min_mark*len2+C_min_mark));      }    for(int j=0;j<len2;j++)    {        C[j]=C0[j];    }    NotBaseVariable[C_min_mark]=BaseVariable[b_min_mark];    BaseVariable[b_min_mark]=C_min_mark; // x C_min_mark进基,x b_min_mark出基}void input(double **a,int len1,int len2)  //输入A[m][n], b[m], C[m],并确定基变量BaseVariable[m]{    cout<<"输入系数矩阵A:\n";    for(int i=0;i<len1;i++)    {        for(int j=0;j<len2;j++)        {            cout<<"A["<<i<<"]"<<"["<<j<<"]=";            cin>>(*((int *)a+i*len2+j));        }        cout<<"\n";    }    cout<<"输入右端项b:\n";    for(int i=0;i<len1;i++)    {        cout<<"b["<<i<<"]=";        cin>>b[i];    }    cout<<"输入约束条件系数C:\n";    int j=0,k=0;    for(int i=0;i<len2;i++)    {        cout<<"C["<<i<<"]=";        cin>>C[i];        if(C[i]==0)        {            BaseVariable[j]=i;          //确定基变量 x2 x3 x4            j++;        }        else            {            NotBaseVariable[k]=i;       //确定非基变量 x0 x1            k++;        }    }}void output(double **a,int len1,int len2) {    cout<<"矩阵A为:\n";    for(int i=0;i<len1;i++)        {            for(int j=0;j<len2;j++)            cout<<(*((int *)a+i*len2+j))<<" ";            cout<<"\n";        }    cout<<"右端项b:\n";    for(int i=0;i<len1;i++)        {            cout<<b[i]<<"   ";        }    cout<<"\n";    cout<<"约束条件系数C:\n";    for(int i=0;i<len2;i++)        {            cout<<C[i]<<"   ";        }    cout<<"\n";    cout<<"f="<<f<<"\n";}void input2()  //输入A[m][n], b[m], C[m],并确定基变量BaseVariable[m]{    cout<<"输入系数矩阵A:\n";    for(int i=0;i<m;i++)    {        for(int j=0;j<n;j++)        {            cout<<"A["<<i<<"]"<<"["<<j<<"]=";            cin>>A[i][j];        }        cout<<"\n";    }    cout<<"输入右端项b:\n";    for(int i=0;i<m;i++)    {        cout<<"b["<<i<<"]=";        cin>>b[i];    }    int j=0,k=0;    for(int i=0;i<n;i++)    {        if(i<n-m)        {            C[i]=0;            NotBaseVariable[j]=i;            j++;        }        else        {            C[i]=1;            BaseVariable[k]=i;            ArtificalVariable[k]=i;//记录人工变量            k++;        }    }    for(int j=0;j<n;j++)    {        for(int i=0;i<m;i++)            C[j]=C[j]-A[i][j];//即  C0[n]->r[n]  过程    }    for(int i=0;i<m;i++)    {        f=f-b[i];    }    cout<<"输入标准型的目标函数系数 C:\n";    for(int i=0;i<n-m;i++)    {        cout<<"c["<<i<<"]=";        cin>>c[i];    }}double determine2(int len1,int len2){    int BaseVariableIncludeArtificalVariable=0;    for(int i=0;i<len1;i++)    {        for(int j=0;j<len1;j++)        {            if(BaseVariable[i]==ArtificalVariable[j])                BaseVariableIncludeArtificalVariable++;        }    }    if(BaseVariableIncludeArtificalVariable)//基变量中若含有人工变量则继续交换        return 1;    else        return 0;}double determine(int len1,int len2)//判定C{    int C_BaseVariable_M0=0, C_BaseVariable_L0=0, C_BaseVariable_E0=0;    int C_NotBaseVariable_M0=0, C_NotBaseVariable_L0=0, C_NotBaseVariable_E0=0;//大于、小于、等于M L E    //double C_min=0;    for(int i=0;i<len1;i++)    {        if(C[BaseVariable[i]]==0)            C_BaseVariable_E0++;        else        {            if(C[BaseVariable[i]]<0)                C_BaseVariable_L0++;            else                C_BaseVariable_M0++;        }    }    for(int i=0;i<(len2-len1);i++)    {        if(C[NotBaseVariable[i]]>0)            C_NotBaseVariable_M0++;        else        {            if(C[NotBaseVariable[i]]<0)            {                C_NotBaseVariable_L0++;            }               else                C_NotBaseVariable_E0++;        }               }    if(C_BaseVariable_E0==len1 && C_NotBaseVariable_L0==0)//基变量的检验数都等于0,非基变量的检验数都大于0        return 1;    if(C_BaseVariable_E0==len1 && C_NotBaseVariable_L0!=0)//基变量的检验数都等于0,非基变量的检验数都大于0        return 0;}

4、确定搜索区间和初始点

// mean.cpp : 优化方法:平均法确定一维搜索问题的搜索区间。//#include "stdio.h"#include "iostream"#include "math.h"using namespace std;double f(double x) ;void main(){    double t0, t1, t2, h;    double a, b;    h=0.2;    cout<<"输入一个初始点的估计值:\n";    cin>>t0;    t2=t0+h;    if(f(t2)<=f(t0))//步骤3    {    t1=t0+h;//步骤4    //f(t1);    }    else//步骤3    {    h=-h;    t1=t0+h;//步骤4    //f(t1);    }    while(f(t1)<=f(t0))//步骤5    {    h=2*h;    t2=t0;    t0=t1;    t1=t0+h;//步骤4    //f(t1);    }    a=min(t1,t2);    b=max(t1,t2);    cout<<"搜索区间为:["<<a<<","<<b<<"]"<<"\n"<<"初始点为:"<<(a+b)/2<<"\n";      system("pause");    return ;}double f(double x)  //输入 min f(x)  f(x)的函数体{    //return x*x+2.0*x;    //return exp(-x)+x*x;    //return x*x*x*x/4-4*x*x*x/3+5*x*x/2-2*x;    //return x*x*x*x*x+2*x*x*x*x-4*x*x*x+x*x+x+2;    return (x+1)*(x+1);}

这里写图片描述

原创粉丝点击