canshushezhi.cpp

来自「此代码可实现最优控制理论中的单纯型寻优算法」· C++ 代码 · 共 455 行

CPP
455
字号
// CanshuShezhi.cpp : implementation file
//

#include "stdafx.h"
#include "optimization.h"
#include "CanshuShezhi.h"
#include "math.h"
#include "optimizationDoc.h"
#include "optimizationView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CCanshuShezhi dialog


CCanshuShezhi::CCanshuShezhi(CWnd* pParent /*=NULL*/)
	: CDialog(CCanshuShezhi::IDD, pParent)
{
	//{{AFX_DATA_INIT(CCanshuShezhi)
	m_I = 0.0f;
	m_K = 0.0f;
	m_P = 0.0f;
	m_R = 0.0f;
	m_T = 0.0f;
	m_ObjFun = _T("");
	m_n = 0;
	//}}AFX_DATA_INIT
}


void CCanshuShezhi::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CCanshuShezhi)
	DDX_Text(pDX, IDC_I, m_I);
	DDX_Text(pDX, IDC_K, m_K);
	DDX_Text(pDX, IDC_P, m_P);
	DDX_Text(pDX, IDC_R, m_R);
	DDX_Text(pDX, IDC_T, m_T);
	DDX_CBString(pDX, IDC_COMBO_ObjFun, m_ObjFun);
	DDX_Text(pDX, IDC_n, m_n);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CCanshuShezhi, CDialog)
	//{{AFX_MSG_MAP(CCanshuShezhi)
	ON_EN_CHANGE(IDC_R, OnChangeR)
	ON_EN_CHANGE(IDC_T, OnChangeT)
	ON_EN_CHANGE(IDC_n, OnChangen)
	ON_EN_CHANGE(IDC_K, OnChangeK)
	ON_EN_CHANGE(IDC_P, OnChangeP)
	ON_EN_CHANGE(IDC_I, OnChangeI)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCanshuShezhi message handlers

void CCanshuShezhi::OnChangeR() 
{
	// TODO: If this is a RICHEDIT control, the control will not
	// send this notification unless you override the CDialog::OnInitDialog()
	// function and call CRichEditCtrl().SetEventMask()
	// with the ENM_CHANGE flag ORed into the mask.
	
	// TODO: Add your control notification handler code here
	UpdateData(true);
	
}

void CCanshuShezhi::OnChangeT() 
{
	// TODO: If this is a RICHEDIT control, the control will not
	// send this notification unless you override the CDialog::OnInitDialog()
	// function and call CRichEditCtrl().SetEventMask()
	// with the ENM_CHANGE flag ORed into the mask.
	
	// TODO: Add your control notification handler code here
	UpdateData(true);
}

void CCanshuShezhi::OnChangen() 
{
	// TODO: If this is a RICHEDIT control, the control will not
	// send this notification unless you override the CDialog::OnInitDialog()
	// function and call CRichEditCtrl().SetEventMask()
	// with the ENM_CHANGE flag ORed into the mask.
	
	// TODO: Add your control notification handler code here
	UpdateData(true);
}
void CCanshuShezhi::OnOK() 
{
	// TODO: Add extra validation here
	
	//(1)单纯形初始化
	int i=0,j=0,k=0;//循环变量
	double Xh=0,Xg=0,Xl=0;//最坏值,次坏值,最好值
	double mid=0;//中间变量
	//各个点的p,i,X值
	double ph=0,pl=0,pg=0,ih=0,ig=0,il=0,pc=0,ic=0,pr=0,ir=0,pe=0,ie=0,ps=0,is=0,Xc=0,Xr=0,Xe=0,Xs=0;
	double E=0.01;//精度要求
	double ansp=0,ansi=0;//最终p,i值
	double Q=0;//最终目标函数值
	double pm,im,Xm,pmm,imm,Xmm;//中间量
	double lamda=0.4,miu=1.5;//压缩因子,扩张因子
	double pini,iini,Xini,hp=0.1,hi=5,iup=250,pup=20,idow=1,pdow=0.01;

	pini=m_P;
	iini=m_I;
	Xini=simulink(m_R,pini,iini,m_K,m_n,m_T);
	pm=m_P+hp;
	im=iini;
	Xm=simulink(m_R,pm,im,m_K,m_n,m_T);
	pmm=m_P;
	imm=iini+hi;
	Xmm=simulink(m_R,pmm,imm,m_K,m_n,m_T);

	Xl=Xini;pl=pini;il=iini;
	if(Xl>Xm)//最好值
	{
		Xl=Xm;pl=pm;il=im;
	}
	if(Xl>Xmm)
	{
		Xl=Xmm;pl=pmm;il=imm;	
	}

	Xh=Xini;ph=pini;ih=iini;
	if(Xh<Xm)//最坏值
	{
		Xh=Xm;ph=pm;ih=im;	
	}
	if(Xh<Xmm)
	{
		Xh=Xmm;ph=pmm;ih=imm;
	}
	
	Xg=Xini;pg=pini;ig=iini;
	if(Xg==Xh||Xg==Xl)//次坏值
	{
		Xg=Xm;pg=pm;ig=im;
	}
	if(Xg==Xh||Xg==Xl)
	{
		Xg=Xmm;pg=pmm;ig=imm;
	}	
	

	for(k=0;k<=10000;k++)
	{
		if (fabs(Xh-Xl)/Xl<=E) //符合精度要求则退出
		{
			ansp=(ph+pl)/2;
			ansi=(ih+il)/2;			
			break;
		}

		if(k>=100)
		{
			MessageBox("搜索失败","目标函数值",MB_OK);
			ansp=(ph+pl)/2;
			ansi=(ih+il)/2;			
			break;
			//return;
		}

		if(pl>pup) pl=pup;
		if(pg>pup) pg=pup;
		if(ph>pup) ph=pup;
		if(pl<pdow) pl=pdow;
		if(pg<pdow) pg=pdow;
		if(ph<pdow) ph=pdow;

		if(il>iup) il=iup;
		if(ig>iup) ig=iup;
		if(ih>iup) ih=iup;
		if(il<idow) il=idow;
		if(ig<idow) ig=idow;
		if(ih<idow) ih=idow;
	

		pr=pl+pg-ph;//反射点
		ir=il+ig-ih;
		if(pr>pup) pr=pup;
		if(pr<pdow) pr=pdow;
		if(ir>iup) ir=iup;
		if(ir<idow) ir=idow;
		Xr=simulink(m_R,pr,ir,m_K,m_n,m_T);

		if(Xr>Xh)//反射点和最坏点互换
		{
			pm=pr;im=ir;Xm=Xr;
			pr=ph;ir=ih;Xr=Xh;
			ph=pm;ih=im;Xh=Xm;
		}
		if(Xr>Xg)//压缩单纯形
		{
			ps=(pl+pg)/2+lamda*((pl+pg)/2-ph);
			is=(il+ig)/2+lamda*((il+ig)/2-ih);
			if(ps>pup) ps=pup;
			if(ps<pdow) ps=pdow;
			if(is>iup) is=iup;
			if(is<idow) is=idow;
			Xs=simulink(m_R,ps,is,m_K,m_n,m_T);

			if(Xg>=Xs)//单纯形收缩
			{
				pini=ps; iini=is; Xini=Xs;
				pm=pl;	im=il;	Xm=Xl;
				pmm=pg;	imm=ig;	Xmm=Xg;
				
				Xl=Xini;pl=pini;il=iini;
				if(Xl>Xm)	{Xl=Xm;pl=pm;il=im;}
				if(Xl>Xmm)	{Xl=Xmm;pl=pmm;il=imm;}					
				
				Xh=Xini;ph=pini;ih=iini;
				if(Xh<Xm)	{Xh=Xm;ph=pm;ih=im;	}
				if(Xh<Xmm)	{Xh=Xmm;ph=pmm;ih=imm;}
				
				Xg=Xini;pg=pini;ig=iini;
				if(Xg==Xh||Xg==Xl)	{Xg=Xm;pg=pm;ig=im;}
				if(Xg==Xh||Xg==Xl)	{Xg=Xmm;pg=pmm;ig=imm;}
				
				continue;
			}
			if(Xg<Xs)//单纯形收缩
			{
				ph=(pl+ph)/2;
				pg=(pl+pg)/2;
				ih=(il+ih)/2;
				ig=(il+ig)/2;

				Xh=simulink(m_R,ph,ih,m_K,m_n,m_T);
				Xg=simulink(m_R,pg,ig,m_K,m_n,m_T);
				
				pini=ph; iini=ih; Xini=Xh;
				pm=pl;	im=il;	Xm=Xl;
				pmm=pg;	imm=ig;	Xmm=Xg;
				
				Xl=Xini;pl=pini;il=iini;
				if(Xl>Xm)	{Xl=Xm;pl=pm;il=im;}
				if(Xl>Xmm)	{Xl=Xmm;pl=pmm;il=imm;}					
				
				Xh=Xini;ph=pini;ih=iini;
				if(Xh<Xm)	{Xh=Xm;ph=pm;ih=im;	}
				if(Xh<Xmm)	{Xh=Xmm;ph=pmm;ih=imm;}
				
				Xg=Xini;pg=pini;ig=iini;
				if(Xg==Xh||Xg==Xl)	{Xg=Xm;pg=pm;ig=im;}
				if(Xg==Xh||Xg==Xl)	{Xg=Xmm;pg=pmm;ig=imm;}
				
				continue;				
			}
		}
		

		if((1-miu)*Xh+miu*Xr>=Xl)//Xr,Xl,Xg重新组成单纯形
		{
			pini=pr; iini=ir; Xini=Xr;
			pm=pl;	im=il;	Xm=Xl;
			pmm=pg;	imm=ig;	Xmm=Xg;
			
			
			Xl=Xini;pl=pini;il=iini;
			if(Xl>Xm)	{Xl=Xm;pl=pm;il=im;}
			if(Xl>Xmm)	{Xl=Xmm;pl=pmm;il=imm;}	
			
			Xh=Xini;ph=pini;ih=iini;
			if(Xh<Xm)	{Xh=Xm;ph=pm;ih=im;	}
			if(Xh<Xmm)	{Xh=Xmm;ph=pmm;ih=imm;}
			
			Xg=Xini;pg=pini;ig=iini;
			if(Xg==Xh||Xg==Xl)	{Xg=Xm;pg=pm;ig=im;}
			if(Xg==Xh||Xg==Xl)	{Xg=Xmm;pg=pmm;ig=imm;}
			
			continue;
		}

		if(Xr<Xg)//扩张单纯形
		{
			pe=(1-miu)*(pl+pg)/2-miu*ph;
			ie=(1-miu)*(il+ig)/2-miu*ih;
			if(pe>pup) pe=pup;
			if(pe<pdow) pe=pdow;
			if(ie>iup) ie=iup;
			if(ie<idow) ie=idow;
			Xe=simulink(m_R,pe,ie,m_K,m_n,m_T);
			
			if(Xe<Xr)
			{
				pr=pe;
				ir=ie;
				Xr=Xe;
			}

			pini=pr; iini=ir; Xini=Xr;
			pm=pl;	im=il;	Xm=Xl;
			pmm=pg;	imm=ig;	Xmm=Xg;
			
			
			Xl=Xini;pl=pini;il=iini;
			if(Xl>Xm)	{Xl=Xm;pl=pm;il=im;}
			if(Xl>Xmm)	{Xl=Xmm;pl=pmm;il=imm;	}
			
			Xh=Xini;ph=pini;ih=iini;
			if(Xh<Xm)	{Xh=Xm;ph=pm;ih=im;	}
			if(Xh<Xmm)	{Xh=Xmm;ph=pmm;ih=imm;}
			
			Xg=Xini;pg=pini;ig=iini;
			if(Xg==Xh||Xg==Xl)	{Xg=Xm;pg=pm;ig=im;}
			if(Xg==Xh||Xg==Xl)	{Xg=Xmm;pg=pmm;ig=imm;}
			
			//continue;			
		}
}
    Q=simulink(m_R,ansp,ansi,m_K,m_n,m_T);
	m_P=ansp;
	m_I=ansi;
	UpdateData(false);
	CString sq;
	sq.Format("%f",Q);
	MessageBox(sq,"目标函数值",MB_OK);

	flag=1;
	COptimizationDoc *pDoc=
	(COptimizationDoc *)(((CFrameWnd *)AfxGetApp()->m_pMainWnd)->GetActiveDocument());
	POSITION m_pos = pDoc->GetFirstViewPosition();
	COptimizationView* pView = (COptimizationView*)(pDoc->GetNextView(m_pos));
	pView->Invalidate();

	CDialog::OnOK();
}



BOOL CCanshuShezhi::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	// TODO: Add extra initialization here
	m_I =20;
	m_K = 0.53;
	m_n = 3;
	m_ObjFun = -1;
	m_P = 2;
	m_R = 1;
	m_T = 12.5;
	m_ObjFun = "绝对误差的矩的积分";
	UpdateData(false);	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}



double CCanshuShezhi::simulink(double R,double P,double I,double K,int n,double T)
{
	//数据传递给文档类,用于保存,画图,in,out
	//文档类指针
COptimizationDoc *pDoc=
	(COptimizationDoc *)(((CFrameWnd *)AfxGetApp()->m_pMainWnd)->GetActiveDocument());
	//对象离散化,欧拉法仿真,计算目标函数,对象结构:(K)/[(aS+1)]n
	int i=0,j=0;
	double dt=1.0;//步长
	int st=1000;//仿真时间
	int lp;//仿真步数
	lp=int(st/dt);
	double Q=0;
	double x1=0,x2=0;
	double c,d;	
	c=exp(-dt/T);
	d=1-c;
	if (n>1)
	{		
		double *x=new double [n-1];
		for(i=0;i<n-1;i++)
		{
			x[i]=0.0;
		}
		for (i=0;i<lp;i++)//仿真
		{
			x1 = x1+dt*(R-x[n-2])/(P*I);
			x2=c*x2+K*d*(x1+R/P-x[n-2]/P);
			
			x[0]=x[0]*c+d*x2;
			for(j=1;j<n-1;j++)
			{
				x[j]=x[j]*c+d*x[j-1];
			}
			
			Q=Q+dt*dt*fabs(R-x[n-2])*i;
			pDoc->input[i]=R;
			pDoc->output[i]=x[n-2];
		}
		delete [n-1] x;
	}
	if (n==1)
	{		
		for (i=0;i<lp;i++)//仿真
		{
			x1 = x1+dt*(R-x2)/(P*I);
			x2=c*x2+K*d*(x1+R/P-x2/P);
			
			Q=Q+dt*dt*fabs(R-x2)*i;
			pDoc->input[i]=R;
			pDoc->output[i]=x2;
		
		
		}	
	}
	return Q;
}



void CCanshuShezhi::OnChangeK() 
{
	// TODO: If this is a RICHEDIT control, the control will not
	// send this notification unless you override the CDialog::OnInitDialog()
	// function and call CRichEditCtrl().SetEventMask()
	// with the ENM_CHANGE flag ORed into the mask.
	
	// TODO: Add your control notification handler code here
	UpdateData(true);
}

void CCanshuShezhi::OnChangeP() 
{
	// TODO: If this is a RICHEDIT control, the control will not
	// send this notification unless you override the CDialog::OnInitDialog()
	// function and call CRichEditCtrl().SetEventMask()
	// with the ENM_CHANGE flag ORed into the mask.
	
	// TODO: Add your control notification handler code here
	UpdateData(true);
}

void CCanshuShezhi::OnChangeI() 
{
	// TODO: If this is a RICHEDIT control, the control will not
	// send this notification unless you override the CDialog::OnInitDialog()
	// function and call CRichEditCtrl().SetEventMask()
	// with the ENM_CHANGE flag ORed into the mask.
	
	// TODO: Add your control notification handler code here
	UpdateData(true);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?