罚函数法和拉格朗日乘子法的区别
一、作用不同:
创新互联坚持“要么做到,要么别承诺”的工作理念,服务领域包括:网站设计制作、成都做网站、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的武威网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!
惩罚函数法在M越来越大的情况下,函数F趋近于病态,乘子法克服这个缺点根据拉格朗日分解加了一个uih(x)M变为了c/2。
主要思想是引入一个新的参数λ(即拉格朗日乘子),将约束条件函数与原函数联系到一起,使能配成与变量数量相等的等式方程。
二、定义不同:
基本的拉格朗日乘子法(又称为拉格朗日乘数法),就是求函数f(x1,x2,)在g(x1,x2,)=0的约束条件下的极值的方法。
罚函数法是从非可行解出发逐渐移动到可行区域的方法。罚函数法在理论上是可行的,在实际计算中的缺点是罚因子M的取值难于把握,太小起不到惩罚作用;太大则由于误差的影响会导致错误。
三、使用方法不同:
在进化计算中,研究者选择外部罚函数法的原因主要是该方法不需要提供初始可行解。需要提供初始可行解则是内部罚函数法的主要缺点。由于进化算法应用到实际问题中可能存在搜索可行解就是NP难问题,因此这个缺点是非常致命的。
基本的拉格朗日乘子法就bai是求函数f(x1,x2,...)在约束条件g(x1,x2,...)=0下的极值的方法。其主要思想是将约束条件函数与原函数联立,从而求出使原函数取得极值的各个变量的解。
扩展资料:
如果这个实际问题的最大或最小值存在,一般说来驻点只有一个,于是最值可求。
条件极值问题也可以化为无条件极值求解,但有些条件关系比较复杂,代换和运算很繁,而相对来说“拉格朗日乘数法”不需代换,运算简单一点,这就是优势。
条件φ(x,y,z)一定是个等式,不妨设为φ(x,y,z)=m
则再建一个函数g(x,y,z)=φ(x,y,z)-m
g(x,y,z)=0以g(x,y,z)代替φ(x,y,z)
在许多极值问题中,函数的自变量往往要受到一些条件的限制,比如,要设计一个容积为 V的长方体形开口水箱,确定长、宽和高,使水箱的表面积最小.。设水箱的长、宽、高分别为 x,y,z, 则水箱容积V=xyz。
参考资料来源:百度百科-拉格朗日乘数法
求解一道贪心算法
因为这个问题涉及到高维求解(大于3维),所以不推荐你用贪心算法或遗传算法之类的算法。这里给出一种升级的蒙特卡罗算法——自适应序贯数论算法,这是一种以GLP集合为基础的随机遍历算法,可以很轻易的解决一系列的高维求解问题,目前根据网上能找到的资料最多可以做到18维。
下面就根据你给出的例子讲解一下:
对于6000的料来说
1185最多做到5根(要求4根,所以一根木料对于1185的产品来说最多有0到45种可能);1079最多做到5根;985最多做到6根;756最多做到7根。
所以第一次加工一根木料最多有5*6*7*8=1680种加工可能(当然其中包括那些产品总长度大于料长的可能,但是我们可以通过罚函数来避免这些情况),那么利用GLP算法我们可以一次性产生这1680种可能,然后逐个比较那种可能最省木料;
设第一加工出的产品量分别为1 1 3 1
那么1185加工量剩3,1079剩5,985剩7,756剩7,所以第二次加工的可能性有(3+1)*(5+1)*(6+1)*(7+1)=1120种
关于自适应序贯数论算法,根据这道题你可以这样理解,4种尺寸构成了一个4维的空间,四种尺寸的每一种组合相当于空间中的一个点(1185的1根,1079的1根,985的3根,756的1根,这就组成了这个4维空间中的(1,1,3,1)点) ,自适应序贯数论算法就是先根据GLP算法在这个4维空间中随机的,均匀的分布一定的点(也就是尺寸的组合),然后根据目标函数确定其中哪一个点是最优点,我们认为最优点的附近出现最优解的可能性最大,那么我们就以最优点为中心,以一定的尺度为半径将原空间缩小,然后我们在心空间中再一次利用GLP算法均匀,随机的充满这个空间,然后重复以上过程,直到这个空间小到我们事先规定的大小,这样我们就找到了最优解。
也许你会担心算法一上来就收敛到了局部最优解,然后一直在这里打转,不用担心,GLP最大的优点就是均匀的充斥整个空间,尽量将每一种可能都遍历到。
这种算法的缺点在于充斥空间用的点需要生成向量来生成,每一种充斥方式都需要不同的向量,你可以在《数论方法在统计中的应用》这本书中查到已有的每种充斥方式对应的那些生成向量。
下面是我跟据对你给出的例子的理解算出的结果。
1185:1根
1079:1根
985:3根
756:1根
剩余木料0
1185:1根
1079:1根
985:3根
756:1根
剩余木料0
1185:1根
1079:1根
985:3根
756:1根
剩余木料0
1185:1根
1079:0根
985:1根
756:5根
剩余木料15
1185:0根
1079:3根
985:0根
756:0根
剩余木料2748
用去木料:5根
请按任意键继续. . .
程序代码如下:(变量都是用汉语拼音标的)
#include stdlib.h
#include stdio.h
#include math.h
#include iostream.h
#include iomanip.h
#include time.h
#include fstream.h
#include windows.h
#include "glp.h"
#define jiedeweishu 4
#define glpgeshu 10007
#define glpgeshu1 5003//100063
#define glpgeshu2 6007//33139//71053//172155//100063
#define yuanmuchang 6000
#define qiegesushi 5
#define chicun1 1185
#define chicun2 1079
#define chicun3 985
#define chicun4 756
#define chicun1shuliang 4
#define chicun2shuliang 6
#define chicun3shuliang 10
#define chicun4shuliang 8
float xuqiuchicun[jiedeweishu]={chicun1,chicun2,chicun3,chicun4};
float chicunxuqiuliang[jiedeweishu]={chicun1shuliang,chicun2shuliang,chicun3shuliang,chicun4shuliang};
float zuobianjie0[jiedeweishu];//{-19,1,-11,1.5,0,200};//{0.39111,-18.5,1,-11,1,0,2};//左边界
float youbianjie0[jiedeweishu];//{-17,1.5,-7,2,0.05,900};//{0.393,-17,2,-9,2,0.1,6};//右边界
float zuobianjie[jiedeweishu];
float youbianjie[jiedeweishu];
float zuobianjie1[jiedeweishu];//过度用
float youbianjie1[jiedeweishu];
float zuobianjie2[jiedeweishu];//局部边界
float youbianjie2[jiedeweishu];
float zuobianjie3[jiedeweishu];//大边界
float youbianjie3[jiedeweishu];
float sheng_cheng_xiang_liang[jiedeweishu]={1,1206,3421,2842};//生成向量
float sheng_cheng_xiang_liang1[jiedeweishu]={1,792,1889,191};//{1,39040,62047,89839,6347,30892,64404};//生成向量
float sheng_cheng_xiang_liang2[jiedeweishu]={1,1351,5080,3086};//{1,18236,1831,19143,5522,22910};//{1,18010,3155,50203,6065,13328};//{1,167459,153499,130657,99554,61040,18165};
struct chushi
{
float geti[jiedeweishu];
float shiyingdu;
};
chushi *zuiyougeti;//精英保存策略
chushi *zuiyougetijicunqi;
int sishewuru(float);
float chazhi;//左右边界的差
int biaozhi;//判断寻优是否成功1表示成功0表示不成功
int maxgen;//最大计算代数
int gen;//目前代数
void initialize();//算法初始化
void jingyingbaoliu();//精英保存的实现
void mubiaohanshu1(chushi bianliang);//适应度的计算使用残差法
int cmpshiyingdujiang(const void *p1,const void *p2)
{
float i=((chushi *)p1)-shiyingdu;
float j=((chushi *)p2)-shiyingdu;
return ij ? 1:(i==j ? 0:-1);//现在是按降序牌排列,将1和-1互换后就是按升序排列
}
int cmp1(const void *p1,const void *p2)
{
float i= *(float*)p1;
float j= *(float*)p2;
return ij ? 1:(i==j ? 0:-1);//现在是按降序牌排列,将1和-1互换后就是按升序排列
}
void main()
{
float bianjiebianhuashuzu[jiedeweishu];
float yiwanchengshuliang[jiedeweishu];
zuiyougeti=new chushi;//最优个体的生成
zuiyougetijicunqi=new chushi;
int i;
for(i=0;ijiedeweishu;i++)
{
zuiyougeti-geti[i]=0;
yiwanchengshuliang[i]=0;
}
int muliaoshuliang=0;
while(1)
{
if(yiwanchengshuliang[0]==chicun1shuliangyiwanchengshuliang[1]==chicun2shuliangyiwanchengshuliang[2]==chicun3shuliangyiwanchengshuliang[3]==chicun4shuliang)
break;//都加工完了就退出程序
biaozhi=1;
for(i=0;ijiedeweishu;i++)
{
bianjiebianhuashuzu[i]=chicunxuqiuliang[i]-yiwanchengshuliang[i];
}
for(i=0;ijiedeweishu;i++)
{
zuobianjie0[i]=0;
if(bianjiebianhuashuzu[i](int)(yuanmuchang/xuqiuchicun[i]))
{
youbianjie0[i]=(int)(yuanmuchang/xuqiuchicun[i]);
}
else
{
youbianjie0[i]=bianjiebianhuashuzu[i];
}
}
for(i=0;ijiedeweishu;i++)
{
zuobianjie[i]=zuobianjie0[i];
youbianjie[i]=youbianjie0[i];
}
for(i=0;ijiedeweishu;i++)//在这套程序中边界分为两个部分,其中一组是根据最优解的收敛范围进行局部寻优,如果在局部找不到最优解则以现有最优解为中心进行全局搜索
{
zuobianjie2[i]=zuobianjie[i];
youbianjie2[i]=youbianjie[i];
zuobianjie3[i]=zuobianjie[i];
youbianjie3[i]=youbianjie[i];
}
zuiyougeti-shiyingdu=-3000;
//cout zuiyougeti-shiyingduendl;
initialize();
//for(i=0;ijiedeweishu;i++)/////
//{////
// coutzuiyougeti-geti[i]",";////
//}/////////
//coutendl;/////
// cout"初始最优解:"" "-zuiyougeti-shiyingduendl;/////////////
for(gen=1;genmaxgen;gen++)
{
jingyingbaoliu();
if(chazhi1e-1)
break;
}
//cout"最终在收敛的范围内左右边界的最大差值: "chazhiendl;
//for(i=0;ijiedeweishu;i++)
//{
// coutsetiosflags(ios::fixed)setprecision(6)zuiyougeti-geti[i]",";
// }
//coutendl;
//cout"共用代数"genendl;
cout"1185:"zuiyougeti-geti[0]"根"endl;
cout"1079:"zuiyougeti-geti[1]"根"endl;
cout"985:"zuiyougeti-geti[2]"根"endl;
cout"756:"zuiyougeti-geti[3]"根"endl;
cout"剩余木料"(-zuiyougeti-shiyingdu)endl;////////////////
coutendl;
for(i=0;ijiedeweishu;i++)
{
yiwanchengshuliang[i]=yiwanchengshuliang[i]+zuiyougeti-geti[i];
}
muliaoshuliang++;
}
cout"用去木料:"muliaoshuliang"根"endl;
delete [] zuiyougetijicunqi;
delete [] zuiyougeti;
system("pause");
}
void initialize()
{
maxgen=20;//最大代数
gen=0;//起始代
chazhi=100;
chushi *chushizhongqunji;
chushizhongqunji=new chushi[glpgeshu];
int i,j;
for(i=0;ijiedeweishu;i++)
{
zuobianjie1[i]=zuobianjie[i];
youbianjie1[i]=youbianjie[i];
}
float **glp_shu_zu;//第一次求解,为了使解更精确这一次求解需要的点最多
glp_shu_zu=new (float *[glpgeshu]);
for(i=0;iglpgeshu;i++)
{
glp_shu_zu[i]=new float[jiedeweishu];//生成的glp向量用glp_shu_zu储存
}
glp glp_qiu_jie_first(glpgeshu,jiedeweishu);//定义生成多少组glp向量和向量的维数
glp_qiu_jie_first.glp_qiu_jie(glp_shu_zu,sheng_cheng_xiang_liang);//将生成的glp向量用glp_shu_zu储存,同时将生成向量带入glp类
for(i=0;iglpgeshu;i++)//产生初始种群
{
for(j=0;jjiedeweishu;j++)
{
chushizhongqunji[i].geti[j]=sishewuru((zuobianjie[j]+(youbianjie[j]-(zuobianjie[j]))*glp_shu_zu[i][j]));
if(j==3glp_shu_zu[i][j]0)
{
cout"274"endl;/////////////
coutzuobianjie[j]" "glp_shu_zu[i][j]" "youbianjie[j]endl;////////////////////
system("pause");///////////////////
}
}
}
for(i=0;iglpgeshu;i++)//计算初始种群的适应度
{
mubiaohanshu1(chushizhongqunji[i]);
}
qsort(chushizhongqunji,glpgeshu,sizeof(chushi),cmpshiyingdujiang);//根据适应度将初始种群集按降序进行排列
chushi *youxiugetiku;//建立一个储存优秀个体的库
youxiugetiku=new chushi[glpgeshu];//建立一个储存优秀个体的库
int jishuqi=0;
i=0;
while(chushizhongqunji[i].shiyingduzuiyougeti-shiyingdu)//凡是比上一代的最优个体还要好的个体都放入优秀个体库
{
for(int j=0;jjiedeweishu;j++)
{
youxiugetiku[i].geti[j]=chushizhongqunji[i].geti[j];
//coutyouxiugetiku[i].geti[j]endl;
}
//system("pause");
i++;
}
// coutiendl;//////////////
//system("pause");//////////////////////////////////////
jishuqi=i;//将得到的优秀个体的数量放入jishuqi保存
float *bianjiezancunqi;//下面就要以优秀个体库中个体的范围在成立一个局部搜索区域,所以先建立一个边界暂存器
bianjiezancunqi=new float[jishuqi];
for(i=0;ijiedeweishu;i++)
{
for(int j=0;jjishuqi;j++)
{
bianjiezancunqi[j]=youxiugetiku[j].geti[i];//将优秀个体库每一维的数据都放入bianjiezancunqi
}
qsort(bianjiezancunqi,jishuqi,sizeof(float),cmp1);//对这些数据按降序排列,取两个边界又得到一个局部范围
//将得到的范围进行保存
zuobianjie[i]=bianjiezancunqi[jishuqi-1];
youbianjie[i]=bianjiezancunqi[0];
//coutzuobianjie[i]endl;//////////////////////////
// coutyoubianjie[i]endl;///////////////////////////
//coutendl;///////////////////
//
if(zuobianjie[i]zuobianjie2[i])//如果新得到的局部左边界在上一代局部左边界左边,则左边界取上一代的
{
zuobianjie[i]=zuobianjie2[i];
}
if(youbianjie[i]youbianjie2[i])//如果新得到的局部右边界在上一代局部右边界右边,则右边界取上一代的
{
youbianjie[i]=youbianjie2[i];
}
}
if(chushizhongqunji[0].shiyingduzuiyougeti-shiyingdu)//本代种群的最优个体比历史最有个个体好,则用本代的代替之,并将标志位赋值为1表示寻优成功
{
for(i=0;ijiedeweishu;i++)
{
zuiyougeti-geti[i]=chushizhongqunji[0].geti[i];
}
zuiyougeti-shiyingdu=chushizhongqunji[0].shiyingdu;
biaozhi=1;
}
delete [] bianjiezancunqi;
delete [] youxiugetiku;
for(i=0;iglpgeshu;i++)
{
delete [] glp_shu_zu[i];
}
delete [] glp_shu_zu;
delete [] chushizhongqunji;
}
void jingyingbaoliu() //精英保留的实现
{
float glpshuliang,xiangliang[jiedeweishu];
if(biaozhi==1)//如果寻优成功则利用局部搜索的数据
{
glpshuliang=glpgeshu1;
for(int i=0;ijiedeweishu;i++)
{
xiangliang[i]=sheng_cheng_xiang_liang1[i];
}
}
else//否则利用全局搜索的数据
{
glpshuliang=glpgeshu2;
for(int i=0;ijiedeweishu;i++)
{
xiangliang[i]=sheng_cheng_xiang_liang2[i];
}
}
chushi *chushizhongqunji;//建立一个用来储存种群的容器
chushizhongqunji=new chushi[glpshuliang];
int i,j;
float **glp_shu_zu;//生成一个glp数组
glp_shu_zu=new (float *[glpshuliang]);
for(i=0;iglpshuliang;i++)
{
glp_shu_zu[i]=new float[jiedeweishu];//生成的glp向量用glp_shu_zu储存
}
glp glp_qiu_jie_first(glpshuliang,jiedeweishu);//定义生成多少组glp向量和向量的维数
glp_qiu_jie_first.glp_qiu_jie(glp_shu_zu,xiangliang);//将生成的glp向量用glp_shu_zu储存,同时将生成向量带入glp类
//cout"377"endl;
if(biaozhi!=1)//如果寻优不成功则进入全局搜索
{
//cout"380"endl;////////////
float bianjiecha[jiedeweishu];
for(i=0;ijiedeweishu;i++)
{
bianjiecha[i]=youbianjie3[i]-zuobianjie3[i];//计算上一代全局每一维范围的宽度
}
static float rou=0.9;//定义收缩比
//float rou=pow(0.5,gen);
for(i=0;ijiedeweishu;i++)//确定新的范围
{
zuobianjie1[i]=zuiyougeti-geti[i]-rou*bianjiecha[i];//左边界为以最优个体为中心-范围宽度乘以收缩比
if(zuobianjie1[i]zuobianjie2[i])//如果新的左边界比目前局部左边界大,那么以目前的为全局寻优的左边界
{
zuobianjie[i]=zuobianjie1[i];
zuobianjie3[i]=zuobianjie1[i];
}
else//否则以局部左边界为全局左边界
{
zuobianjie[i]=zuobianjie2[i];
zuobianjie3[i]=zuobianjie2[i];
}
youbianjie1[i]=zuiyougeti-geti[i]+rou*bianjiecha[i];//右边界为以最优个体为中心+范围宽度乘以收缩比
if(youbianjie1[i]youbianjie2[i])
{
youbianjie[i]=youbianjie1[i];
youbianjie3[i]=youbianjie1[i];
}
else
{
youbianjie[i]=youbianjie2[i];
youbianjie3[i]=youbianjie2[i];
}
}
qsort(bianjiecha,jiedeweishu,sizeof(float),cmp1);
if(chazhi==bianjiecha[0])//如果最大边界差不变的话就将收缩因子变小
{
rou=pow(rou,2);
}
chazhi=bianjiecha[0];
}
//cout"421"endl;/////////////////////
for(i=0;iglpshuliang;i++)//根据新产生的最优个体确定glp群
{
for(j=0;jjiedeweishu;j++)
{
chushizhongqunji[i].geti[j]=sishewuru((zuobianjie[j]+(youbianjie[j]-(zuobianjie[j]))*glp_shu_zu[i][j]));
}
}
for(i=0;iglpshuliang;i++)
{
mubiaohanshu1(chushizhongqunji[i]);
}
qsort(chushizhongqunji,glpshuliang,sizeof(chushi),cmpshiyingdujiang);
zuiyougetijicunqi-shiyingdu=zuiyougeti-shiyingdu;
if(chushizhongqunji[0].shiyingduzuiyougeti-shiyingdu)
{
for(i=0;ijiedeweishu;i++)
{
zuiyougeti-geti[i]=chushizhongqunji[0].geti[i];
}
zuiyougeti-shiyingdu=chushizhongqunji[0].shiyingdu;
biaozhi=1;
}
else
{
// cout"446"endl;/////////////
biaozhi=0;
}
if(biaozhi==1)//如果寻优成功了就需要确立一个新的局部最优解范围
{
chushi *youxiugetiku;
youxiugetiku=new chushi[glpshuliang];
int jishuqi=0;
i=0;
while(chushizhongqunji[i].shiyingduzuiyougetijicunqi-shiyingdu)
{
for(int j=0;jjiedeweishu;j++)
{
youxiugetiku[i].geti[j]=chushizhongqunji[i].geti[j];
}
i++;
}
jishuqi=i;
float *bianjiezancunqi;
bianjiezancunqi=new float[jishuqi];
for(i=0;ijiedeweishu;i++)
{
for(int j=0;jjishuqi;j++)
{
bianjiezancunqi[j]=youxiugetiku[j].geti[i];
}
qsort(bianjiezancunqi,jishuqi,sizeof(float),cmp1);
zuobianjie[i]=bianjiezancunqi[jishuqi-1];
youbianjie[i]=bianjiezancunqi[0];
// coutzuobianjie[i]endl;//////////////
// coutyoubianjie[i]endl;/////////////
// coutendl;///////////////
if(zuobianjie[i]zuobianjie2[i])
{
zuobianjie[i]=zuobianjie2[i];
}
if(youbianjie[i]youbianjie2[i])
{
youbianjie[i]=youbianjie2[i];
}
}
delete [] bianjiezancunqi;
delete [] youxiugetiku;
}
for(i=0;iglpshuliang;i++)
{
delete [] glp_shu_zu[i];
}
delete [] glp_shu_zu;
delete [] chushizhongqunji;
}
void mubiaohanshu1(chushi bianliang)//计算shiyingdu
{
int i=0;
int sunshi,chanpin;
sunshi=qiegesushi*(bianliang.geti[0]+bianliang.geti[1]+bianliang.geti[2]+bianliang.geti[3]-1);
chanpin=chicun1*bianliang.geti[0]+chicun2*bianliang.geti[1]+chicun3*bianliang.geti[2]+chicun4*bianliang.geti[3];
bianliang.shiyingdu=yuanmuchang-sunshi-chanpin;
if(bianliang.shiyingdu!=0)//如果不能正好将木料分成所需尺寸则要多切一刀
{
sunshi=qiegesushi*(bianliang.geti[0]+bianliang.geti[1]+bianliang.geti[2]+bianliang.geti[3]);
}
if(bianliang.shiyingdu0)//罚函数
{
bianliang.shiyingdu=bianliang.shiyingdu+1e5;
}
bianliang.shiyingdu=-bianliang.shiyingdu;
}
int sishewuru(float x)
{
float y;
int z;
y=x-(int)x;
if(y0.5)
{
z=(int)(x);
}
else
{
z=(int)x;
z=z+1;
}
return z;
}
glp.h源文件贴不下了,把你邮箱给我我发给你
邮箱:hu_hu605@163.com
powell算法求解惩罚函数内点法 用c语言实现 谁会 急!!!!
#include#definestacksize100//假定预分配的栈空间最多为100个元素typedefcharelementtype;//假定栈元素的数据类型为字符,在此处可以自行设置typedefstruct{elementtypedata[stacksize];inttop;}seqstack;//置空栈voidinitstack(seqstack*s){s-top=-1;//解释一下,s-top指向的是当前栈顶元素的位置//当要向栈中添加一个新元素时,要先将s-top增加1,//此时s-top指向的就是新元素要添加的位置了。//所以当栈为空时,填加第一元素时,top加1后//s-top的值就变为0,也就是第一个元素的位置了。}//判栈空intstackempty(seqstack*s){if(s-top==-1)return1;//若相等就返回1,否则为0elsereturn0;}//入栈voidpush(seqstack*s,elementtypex){if(s-top==stacksize-1)//进栈前判断栈是否已经满了printf("stackoverflow\n");else{s-top=s-top+1;s-data[s-top]=x;}}//出栈elementtypepop(seqstack*s){if(stackempty(s))//出栈前先判断当前栈中是否有内容printf("stackisempty\n");else{returns-data[s-top--];//出栈后s-top的值会自减1}}//取栈顶元素(只是想知道栈顶的值,并没有出栈)elementtypegettop(seqstack*s){if(stackempty(s)){printf("stackalreadyempty.\n");}elsereturns-data[s-top];}intmain(){elementtypex;seqstack*s;//定义一个栈,用指针的方式定义的initstack(s);//想初始化定义好的栈//当栈为空时调用出栈操作pop(s);//向栈中添加一个元素apush(s,'a');//观察此时的栈顶元素x=gettop(s);printf("%c\n",x);//再添加一个元素bpush(s,'b');//观察此时的栈顶元素x=gettop(s);printf("%c\n",x);//弹出栈顶的元素x=pop(s);printf("%c\n",x);//观察弹出后栈顶元素的变化情况x=gettop(s);printf("%c\n",x);return0;}
标题名称:罚函数c语言 罚函数求解
文章分享:http://scgulin.cn/article/dooggdh.html