目录
前言
继续学习数学建模
一 解题技巧
题目分析
1 每次写题目时候,都要把题目进行可视化------很有必就是把题目转化为图谱
2 对应的约束条件是要用文字进行说明
3 优化后的模型是要满足一般性最好,就是样例放置普遍正确
4 线性规划一般都是利用LINGO软件,非线性规划最好是去用MATLAB来解决
5 先想变量然后再去写模型,这样条理才会清晰
二 非线性规划问题
某公司有6个建筑工地要开工,每个工地的位置(用平面坐标(a,b)表示,距离单位为km),及水泥日用量d(单位为t)由下表给出,目前由两个临时用料场位于P(5,1)Q(2,7),日用量各有20t,研究下面问题
工地 1 2 3 4 5 6 a 1.25 8.75 0.5 5.75 3 7.25 b 1.25 0.75 4.75 5 6.5 7.75 d 3 5 4 7 6 11 1)假设从料场到工地之间均有直线道路相连,试制定每天的供应计划,即从每个料场分别向各个工地运送多少的水泥,使得总吨公里数最小
2)为了进一步减少吨公里数,打算舍弃目前的两个料场,改建新的两个料场,日用料存储还是20t,给出新料场的位置
小题1
首先我么要分析题目吨公里数就是路程乘以重量,因为越重越烧油,然后我们就要进行计算距离和吨
所以我么就可以写出我们的公式,就是路程乘以运送到那里的吨数求取最小值
然后约束条件就是运送到各个工地的水泥的总和不可以超过料场的日用量
数学模型如下
然后我么就要编写我们的程序,这里是需要双下表求和的,所以我么要这么写
sets: aa/1..6/:a,b,d; bb/1..2/:p,q,e; cc(aa,bb):x; endsets data: e = 20,20; a = 1.25,8.75,0.5,5.75,3,7.25; b = 1.25,0.75,4.75,5,6.5,7.75; d = 3,5,4,7,6,11; p = 5,2; q = 1,7; enddata min = @sum(cc(i,j):x(i,j)*((a(i) - p(j))^2 +(b(i)-q(j))^2)^0.5); @for(bb(j):@sum(aa(i):x(i,j))<=e(j)); @for(aa(i):@sum(bb(j):x(i,j))=d(i));
我么不难看到我们设置了两个for这个for是用来进行遍历的
后面的括号转换到编程一般都是循环,求和下标转换到编程是对这个求和
双下标变量--------标识对应坐标的变量很不错
单单只有一个变量下面写i和j,条件只有i的话不是双下下标变量,双下表变量一般都是为两个限制条件
然后我们下一题就是非线性了,这个时候我们只要删除,然后把LINGO转换到全局最优解,就可以得出答案了
三 钻井布局问题
我们由十二口井水,位置分布图如下,a表示x坐标,b表示y坐标
接下来我要进行用一个网格,然后套在这个井上,然后求取这个网格最多有多少个,网格点的位置和井的位置x和y的误差可以由0.05的误差,网格的单位长度为1
首先我们来构建第一个模型
首先怎么构建这个模型呢?
我们平时想的都是去移动这个井,但是我们可以移动这个图,使得这个井的个数在图上最多不就好了,然后这里的a就是井的坐标,然后我们移动x这里的x的限制范围为0-1
为什么是0-1?
因为我们可以想如果大于了1那么这个必须不在网格上的,因为我们的网格单位长度就只有1
然后我们这里没有四舍五入的函数,只有python有,这里我们使用LINGO解题
然后我们这里的0.5就是为了向下取整使用的,这里是什么意思?
首先如果我的井水通过表格的移动到了4.54的位置,那么这个时候我用向下取整的话,那么就是为5,5是这个网格的位置,只要我们的差的绝对值小于0.05就好了
然后我们这里还是要用到0-1规划,因为我们要知道有几个,首先我们这里可以用0-1规划分别代表它在不在这个网格点上
但是这个模型还是有一定的缺陷,为什么?因为我们约束条件没有和0-1规划联系起来,什么时候取1,什么时候取0,然后我们就要更改模型
这样就建立联系了
然后我们就可以编程了
可能有的人问为什么不放在右边,因为你放在右边,取0的时候为0,然后你这左边是一个小数就矛盾了sets: aa/1..12/:s,b,f; endsets data: s = 0.50,1.41,3.00,3.37,3.40,4.72,4.72,5.43,7.57,8.38,8.98,5.50; b = 2.00,3.50,1.50,3.51,5.50,2.00,6.24,4.10,2.01,4.50,3.41,0.80; enddata Max = @sum(aa(i):f(i)); x<1; x>0; y<1; y>0; @for(aa(i):@abs(s(i)+x-@floor(s(i)+x+0.5))*f(i)<=0.05); @for(aa(i):@abs(b(i)+y-@floor(b(i)+y+0.5))*f(i)<=0.05); @for(aa(i):@bin(f(i)));
这是LINGO编写的代码,然后这个abs是取绝对值,floor是向下取整
这个是用MATLAB编写的代码
也是可以算出最值的
总结
首先我们总结了解题技巧和非线性规划要怎么处理和解决了一个真题