网上已经有很多类似方法,上一篇是Lingo,本篇是matlab,两个软件在解决最优解方面各有优势。
matlab软件中自带许多函数:
1:非线性规划:
[x,fval]=fmincon(fun,x0,A,b,Aeq,beq,lb,ub,nonlcon,);
fun: 目标函数
x0:最优解的初始值
A,B: 线性约束不等式 A * x <= b;
Aeq,Beq: 线性约束等式 Aeq * x = Beq;
lb: 自变量下届
ub: 自变量上界
nonlcon:非线性约束函数
2:线性规划:
[x,fval]= linprog(f,A,b,Aeq,beq,lb,ub,x0)
3:二次规划:
[S,y] =quadprog(H,f,A,B,Aeq,beq,lb,ub,x0)
本片着重讲解C#调用matlab解决二次规划问题
所用目标函数和约束条件还是上一篇的例子
目标函数:
min=(x1-80)^2 + (x2-10)^2 + (x3-10)^2
约束条件:
-x1 * 0.216 -x2 * 0.392 +x3 * 2.120 = y1;
-x1 * 0.0020-x2 * 0.176 + x3 * 0.336 =y2;
-x1 * (1-0.0943)* 0.282 -x2 (1-0.0833) 0.462 + x3 * (1-0.087)* 0.296 = y3;
1< x1,x2,x3<99;
-0.5
首先看看matlab如何解决:
其中H = diag([2,2,2]);比较难理解可以参考此博主的这篇文章:
https://blog.csdn.net/jbb0523/article/details/50598641
接下来展示C#项目调用matlab的方法
首先在matlab写好文件
其次在matlab命令行中输入deploytool,有如下选择
选择Library Compiler, 1:.Net Assembly 2:选择刚保存好的.m文件 3:点击Package
做完上述操作后,在bin目录下可以看到myquadprog文件目录,找到里面的dll,放到项目中引用
如下图所示,添加myquadprog.dll ,之前也做过fmincom,linprog的测试了,所以会有这两个引用。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using myLinprog;
using myfmincom;
using myquadprog;
using MathWorks.MATLAB.NET.Arrays;
namespace XianXingGuiHua
{
class Program
{
static void Main(string[] args)
{
//MWArray Hs = (MWNumericArray)new double[3, 3];
//Hs[1] = 2; 测试,将界面的值依次赋予
//Hs[2] = 0;
//Hs[3] = 0;
//Hs[4] = 0;
//Hs[5] = 2;
//Hs[6] = 0;
//Hs[7] = 0;
//Hs[8] = 0;
//Hs[9] = 2;
MWArray H = (MWNumericArray)new double[,] { { 2, 0, 0 }, { 0, 2,0 }, { 0, 0, 2 } };
MWArray ff = (MWNumericArray)new double[] { -140, -20, -40 };
MWArray AA = (MWNumericArray)new double[,] { { -0.216, -0.392, 2.120 },
{ 0.216, 0.392, -2.120 },
{ -0.02,-0.176,0.336 },
{ 0.02,0.176,-0.336 },
{ -(1-0.0943)*0.282,-(1-0.0833)*0.462,(1-0.087)*2.698 },
{(1-0.0943)*0.282,(1-0.0833)*0.462,-(1-0.087)*2.698 }
};
MWArray bb = (MWNumericArray)new double[] { 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 };
MWArray Aeqq = (MWNumericArray)new double[] { 1, 1, 1 };
MWArray Beqq = (MWNumericArray)new double[] { 100 };
MWArray lbb = (MWNumericArray)new double[] { 0, 0, 0 };
MWArray ubb = (MWNumericArray)new double[] { };
MWArray x00 = (MWNumericArray)new double[] { 1, 1, 1,1 };
MWArray[] agrsInn = new MWArray[] { (MWNumericArray)H, (MWNumericArray)ff, (MWNumericArray)AA, (MWNumericArray)bb, (MWNumericArray)Aeqq, (MWNumericArray)Beqq, (MWNumericArray)lbb, (MWNumericArray)ubb, (MWNumericArray)x00 };//输入参数
MWArray[] agrsOutt = new MWArray[2]; //输出存放的数组
myquadprog.Class1 mf = new myquadprog.Class1(); //二次规划
mf.myquadprog(2, ref agrsOutt, agrsInn);
Console.WriteLine("x最优值为 : \t");
int c1 = int.Parse(Double.Parse(agrsOutt[0][1].ToString()).ToString("#0."));
int c2 = int.Parse(Double.Parse(agrsOutt[0][2].ToString()).ToString("#0."));
int c3 = int.Parse(Double.Parse(agrsOutt[0][3].ToString()).ToString("#0."));
Console.WriteLine(agrsOutt[0][1] + "----" + agrsOutt[0][2] + "----" + agrsOutt[0][3]);
Console.WriteLine("得到的y值为 : \t" + agrsOutt[1]);
Console.ReadKey();
}
}
}
运行结果如下:
最后成功解决,但是有一个小问题,就是限定整数的问题,在线性规划上,matlab有intprog函数解决,但是像此例子,非线性规划,还是比较特殊的二次规划,就没办法解决最优解是整数的问题了,所以这时候只能用lingo解决了,大家如果对matlab精深,有更好的方法欢迎讨论,共同研究一下。