天天看點

數學模組化--Lingo語言使用總結以及經典例題

準備數學模組化比賽中,使用的是Lingo軟體,将學習中遇到的問題做下總結:

資料總結連結:https://blog.csdn.net/yzu_120702117/article/details/38415153

1、關于數學函數使用過程的問題
model:
sets:
object/1 .. 3/: f;
endsets
data:
a, b = 3, 4;
x = ?;
enddata
@free(x);
f(1) = a*@sin(x);
f(2) = b*@cos(x);
f(3) = a*@sin(x) + b*@cos(x);
y = @smax(f(1), f(2), f(3));
end
           

思路:建立集合,并将函數值儲存到每個成員中的 f 中。

目的:練習使用集合以及常用函數。

遇到的問題:每次輸入大于1.57(這是弧度,對應的角度就是大于90),就報錯如下:

        

數學模組化--Lingo語言使用總結以及經典例題

意思就是說:f (2)的式子限制太多,不能表示出來,請減少變量限制;

其實也很好了解,當大于90時,cos(x)是小于0的,這時候就不能正常表示,需要free ( f ),讓f可以為任意數。

代碼加一句

@for(object(i): @free(f(i)));

即可(這是針對集合的語句呦)。

2、關于經典例題–職員時序安排問題求解思路

題目:職員時序安排模型 一項工作一周七天都需要有人,每天(周一至周日)所需的

最少職員數位20,16,13,19,14和12

,并要求每個職員

一周連續工作5天

,試求每周所需

最少的職員數

,并給出安排。注意這裡我們考慮穩定後的情況。

  • 按照決策變量,目标函數,限制條件的思路從題目中提取相關資訊。

    ① 根據

    一周連續工作5天

    ,設決策變量為從周x開始的員工。(我用集合來表示:n(1)為周一開始工作的員工數目,…n(7)為周日開始工作的員工數目)

    ② 根據

    最少的職員數

    ,确定木匾函數為n(1) + … + n(7)的最小值。

    ③ 根據

    最少職員數位20,16,13,19,14和12

    ,确定限制條件。

                

數學模組化--Lingo語言使用總結以及經典例題

N(1) + N(4) + N(5) + N(6) + N(7) >= 20;

N(1) + N(2) + N(5) + N(6) + N(7) >= 16;

N(1) + N(2) + N(3) + N(6) + N(7) >= 13;

N(1) + N(2) + N(3) + N(4) + N(7) >= 16;

N(1) + N(2) + N(3) + N(4) + N(5) >= 19;

N(2) + N(3) + N(4) + N(5) + N(6) >= 14;

N(3) + N(4) + N(5) + N(6) + N(7) >= 12;

  • 這些分析完成之後,寫代碼就很簡單了:
model:

sets:
!決策變量:設員工周x開始工作的員工數目為n(x);
workers/1 .. 7/:n;
endsets
!員工數目為整數;
@for(workers(i): @gin(n));
!目标函數;
min = @sum(workers(i):n);
!限制條件;
n(1) + n(4) + n(5) + n(6) + n(7) >=20;
n(1) + n(2) + n(5) + n(6) + n(7) >= 16;
n(1) + n(2) + n(3) + n(6) + n(7) >= 13;
n(1) + n(2) + n(3) + n(4) + n(7) >= 16;
n(1) + n(2) + n(3) + n(4) + n(5) >= 19;
n(6) + n(2) + n(3) + n(4) + n(5) >= 14;
n(5) + n(6) + n(3) + n(4) + n(7) >= 12;

end
           

這是我的很直覺的解法,思路沒問題,就是語句繁瑣,标準答案參見:

https://blog.csdn.net/m307617071/article/details/5514489#commentsedit

3、經典例題–TSP問題(旅行商問題)

題目:有一個銷售員,從城市1出發,要遍訪城市2,3,…,n個一次,最後傳回城市1.已知從城市i到j的距離為C(ij),問他該按怎樣的次序通路這些城市,是得總距離最少?

這個旅行商問題可以轉換成混合整數線性規劃問題(MILP)。

  • 對TSP 的數學描述:

    引入0-1 變量??? (? ≠ ?):???=1 表示路線從i 到j;???=0 表示不走i→j 這條路。

    則TSP 可表示為:

            

數學模組化--Lingo語言使用總結以及經典例題

上述限制條件中的前三個類似指派型問題,隻是TSP 的必要條件;是以我們針對第四條限制條件用下列數學表達式來實作:

增加變量?? (? = 1,2, … , ?),并且?? − ?? + ???? ≤ ? − 1; ?? , ?? ≥ 0, ? = 1,2, … , ?, ? = 2,3, … , ?, i ≠ j.

于是TSP 問題轉化成了一個混合整數線性規劃模型。

決策變量:每個城市之間的距離Cij(代碼中是dist表示)以及xij;

目标函數:總距離的最小值,min = @sum(link: dist * x);

限制條件:① @for(city(i):@sum(city(j) | i#ne#j:x(i, j)) = 1);

       @for(city(i):@sum(city(j) | i#ne#j:x(j, i)) = 1);!行和以及列和都是1

     ② @for(city(i):@for(city(j) | i#gt#1 #and# i#ne#j : u(i) - u(j) + n*x(i, j) <= n - 1 ) ; );!添加的額外限制

     ③ @for(link:@bin(x));!隻能是0或1

分析完畢之後,寫代碼就很簡單了。

源代碼:

model:
!5個城市;
sets:
city/1 .. 5/:u;
link(city, city):dist, x;
endsets
!将距離資訊放到dist檔案中;
data:
dist = @file('dist.txt');
enddata
!城市的數量;
n = @size(city);

!限制條件;
!行 列和為1;
@for(city(i):
	@sum(city(j)|i#ne#j:x(i, j)) = 1;
	@sum(city(j)|i#ne#j:x(j, i)) = 1);
!新限制;
@for(city(i):
	@for(city(j)| j#gt#1 #and# i#ne#j:
	u(i) - u(j) + n*x(i, j) <= n - 1););
@for(city(i):u(i) <= n - 1);
!隻能是0, 1;
@for(link: @bin(x));
!目标函數;
min = @sum(link:dist*x);
end
           

檔案dist中内容是(我選取的是5個城市。)

              

數學模組化--Lingo語言使用總結以及經典例題
4、最短路徑問題。(動态規劃法求解)

題目:給定N個點Pi組成集合{Pi},由集合中任一點Pi到另一點Pj的距離用Cij表示,如果Pi到Pj沒有弧連接配接,則規定Cij=正無窮大,有規定Cii=0,指定一個終點PN,要求從Pi到PN的最短路線。

假設F(i)是第i點到第N點的最短距離,那麼 F(i) = min(j)(Cij + F(j));

                    F(N) = 0;

  • 原理了解之後寫代碼就很簡單了:

    決策變量:城市之間的連接配接和距離W,那麼就定義兩個集合:

    city/1 … 10/:F;

    road(city, city)/1,2 1,3 2,4 2,5 2,6 3,4 3,5 3,6 4,7 4,8 5,7 5,8 5,9 6,8 6,9 7,10 8,10 9,10/:W,P;

    目标函數:

    @for(city(i) i#lt# n : F(i) = @min(road(i, j): W(i, j) + F(j)));

    由于沒有限制條件,是以不考慮限制。

    求解P(i, j)的語句如下:

    @for(road(i, j): P(i, j) = @if(F(i) #eq# W(i, j) + F(j), 1, 0));

那麼代碼如下:

model:
sets:
!定義集合城市,屬性是到終點的最短距離;
city/1 .. 10/:F;
!繼承集合包含圖的連接配接部分的權重W以及P(若該連接配接是最短路徑的子集,那麼P為1否則為0,是為了友善找最佳路徑);
road(city, city)/
			1,2 1,3
			2,4 2,5 2,6
			3,4 3,5 3,6
			4,7 4,8
			5,7 5,8 5,9
			6,8 6,9 
			7,10
			8,10
			9,10
			/:W, P;
endsets
data:
W = 
	6 5
	3 6 9
	7 5 11
	9 1
	8 7 5 
	4 10
	5
	7
	9;

enddata

n = @size(city);
! 動态規劃式子;
@for(city(i)| i#lt#n:F(i) = @min( road(i, j): W(i, j) + F(j)) );
!尋找路徑;
@for(road(i, j): P(i, j) = @if(F(i) #eq# W(i, j) + F(j), 1, 0));

end
           
5、指派問題(配置設定問題)

題目:這是給n個人配置設定n項工作以獲得最高效率的問題。第i個人完成第j項工作需要的平均時間為Cij。要求給每個人配置設定一項工作,并要求配置設定完這些工作,以使完成全部任務的總時間最小。

思路:

①決策變量:設集合person是勞工,集合work是需要指派的任務,那麼派生集合allocate(person, work),并加上屬性Tij為第i個勞工做第j個工作的時間,Aij是如果dii個勞工做第j個工作,那麼Aij = 1,否則Aij = 0.

②目标函數:

          

數學模組化--Lingo語言使用總結以及經典例題

③限制條件:

          

數學模組化--Lingo語言使用總結以及經典例題

那麼代碼就很好寫了:

model:

sets:
work/1 .. 7/;
person/1 .. 7/;
allocate(person, work):T, A;
endsets

data:
T = 
	6 2 6 7 4 2 5
	4 9 5 3 8 5 8
	5 2 1 9 7 4 3
	7 6 7 3 9 2 7
	2 3 9 5 7 2 6
	5 5 2 2 8 11 4
	9 2 3 12 4 5 10;

enddata
!目标函數;
!min = @sum(@for(person(i):
			@for(work(j):T(i, j)*A(i, j))));
min = @sum(allocate(i, j): T(i, j)*A(i, j));
!限制條件;
@for(person(i):
		@sum(work(j): A(i, j)) = 1);
@for(work(i):
		@sum(person(j): A(j, i)) = 1);

@for(allocate : @bin(A));

end
           
6、最優選擇問題。

題目: 某鑽井隊要從10個可供選擇的井位中确定5個鑽井探油,使總的鑽探費用為最小。若10個井位的代号為s1,s2,…,s10,相應的鑽探費用c1,c2,…,c10為5,8,10,6,9,5,7,6,10,8.并且井位選擇上要滿足下列限制條件:

(1) 或選擇s1和s7,或選擇鑽探s9;

(2) 選擇了s3或s4就不能選s5,或反過來也一樣;

(3) 在s5,s6,s7,s8中最多隻能選兩個.

試建立這個問題的整數規劃模型,确定選擇的井位。

明顯這是一個混合整數線性規劃問題。

  • 思路:根據題意,确定:

    決策變量:集合 井oilplace/s1 … s10/ : c,f;包含屬性價格c和是否開采f。

    目标函數:min = @sum(oilplace:c*f);費用和的最小值。

    限制條件:(s1 + s7 - 2)(s9 - 1) = 0;

          s(3)*s(5) + s(4)*s(5) = 0;

          s5 + s6 + s7 + s8 <= 2;

          @for(oilplace:@bin(f));

          @sum(oilplace: f) = 5.

核心就是将限制條件變換成程式。

代碼就很簡單寫了:

model:

sets:
oilplace/s1 .. s10/:c, f;
endsets

data:
c = 5 8 10 6 9 5 7 6 10 8;
enddata

min = @sum(oilplace: c*f);

@sum(oilplace(i)| i#gt#4 #and# i#lt#9: f(i)) <= 2;
@sum(oilplace: f) = 5;
(f(1) + f(7) - 2)*(f(9) - 1) = 0;
!f(9) = @if(f(1)#eq#1 #and# f(7)#eq#1,  0, 1);
!f(5) = @if(f(3)#eq#1 #or# f(4)#eq#1, 0, 1);
!f(3) = @if(f(5)#eq#1, 0, 1);
!f(4) = @if(f(5)#eq#1, 0, 1);
f(3)*f(5) + f(4)*f(5) = 0;
@for(oilplace:@bin(f));

end
           
7、選址問題(1)

某公司有六個建築工地,位置坐标(ai,bi)(機關:公裡),水泥日用量di(機關:噸)

數學模組化--Lingo語言使用總結以及經典例題

(1) 現有2個料場,位于A(5,1),B(2,7),記(xj,yj),及,2,日存儲量ej各有20噸。假設工地和料場之間有直線道路,制定每天的供應計劃,即從A,B兩料場分别向工地運送水泥,是得總的噸公裡數最小,其中Cij表示i工地從j料場運來的水泥量。則可以建立模型

數學模組化--Lingo語言使用總結以及經典例題

分析得到:

決策變量:工地:workplace/1 … 6/: a, b, d;

      料場 ;material/A B/:x, y, e;

      兩者合集all(material, workplace):c;

目标函數:min = @sum(all(i, j):@sqrt((x(i) - a(j))^2 + (y(i) - b(j))^2)*c(i, j));

限制條件:@for(material(i):

             @sum(workplace(j):c(i, j)) <= 20);

      @for(workplace(j):

             @sum(material(i):c(i, j)) = d(j));

那麼代碼就很好寫了:

model:

sets:
workplace/1 .. 6/:a, b, d;
material/A B/:x, y, e;
all(material, workplace): c;
endsets

data:
e = 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 ;
x = 5, 2;
y = 1, 7;
d = 3 5 4 7 6 11;
enddata

min = @sum(all(i, j):((x(i) - a(j))^2 + (y(i) - b(j))^2)^.5*c(i, j));

@for(material(i):
			@sum(workplace(j): c(i, j)) <= 20);
!c(1, 1) + c(2, 1) = 3;
!c(1, 2) + c(2, 2) = 5;
!c(1, 3) + c(2, 3) = 4;
!c(1, 4) + c(2, 4) = 7;
!c(1, 5) + c(2, 5) = 6;
!c(1, 6) + c(2, 6) = 11;

@for(workplace(j):
			@sum(material(i): c(i, j)) = d(j));
end
           

(2)改建兩個新料場,需要确定新料場位置(xj,yj)和運量cij,在其他條件不變下使總公裡數最小。模型與上面的一樣,位置變量變為料場位置(xj,yj),變為非線性優化問題。

加一個init初始化就可以,給兩個料場賦初值,找最近點。新代碼如下:

model:

sets:
workplace/1 .. 6/:a, b, d;
material/A B/:x, y, e;
all(material, workplace): c;
endsets

data:
e = 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;
enddata

init:
x = 5 2;
y = 1 7;
endinit

min = @sum(all(i, j):((x(i) - a(j))^2 + (y(i) - b(j))^2)^.5*c(i, j));

@for(material(i):
			@sum(workplace(j): c(i, j)) <= 20);
!c(1, 1) + c(2, 1) = 3;
!c(1, 2) + c(2, 2) = 5;
!c(1, 3) + c(2, 3) = 4;
!c(1, 4) + c(2, 4) = 7;
!c(1, 5) + c(2, 5) = 6;
!c(1, 6) + c(2, 6) = 11;

@for(workplace(j):
			@sum(material(i): c(i, j)) = d(j));
end
           

8、選址問題(2)

題目:某海島上有12個主要的居民點,每個居民點的位置(用平面坐标x,y表示,機關km)和居住人數(r)如下表所示。現在準備在海島上建一個服務中心為居民提供各種服務,那麼服務中心應該建在那裡?

數學模組化--Lingo語言使用總結以及經典例題

這個題目沒有限制變量,僅僅要一個最小值的目标函數就可以。

數學模組化--Lingo語言使用總結以及經典例題

代碼:

model:

sets:
live/1 .. 12/: x, y, r;
server/A/:a, b;
all(server, live);
endsets

data:
x = 0 8.20 0.50 5.70 0.77 2.87 4.43 2.58 0.72 9.76 3.19 5.55;
y = 0 0.50 4.90 5.00 6.49 8.75 3.26 9.32 9.96 3.16 7.20 7.88;
r = 600 1000 800 1400 1200 700 600 800 1000 1200 1000 1100;
enddata

init:
a = 0;
b = 0;
endinit

min = @sum(all(i, j): ((a(i) - x(j))^2 + (b(i) - y(j))^2)^.5*r(j));

end
           
9、非線性整數規劃
數學模組化--Lingo語言使用總結以及經典例題

還要求Xi是整數。

這就很明顯的題目了,直接寫就可以。

最顯然的寫法:

model:

sets:
data1/1 .. 5/:d;
endsets

max = d(1)^2 + d(2)^2 + 3*d(3)^2 + 4*d(4)^2 + 2*d(5)^2 - 8*d(1) - 2*d(2) - 3*d(3) - d(4) - 2*d(5);

[email protected](data1:d >= 0);
[email protected](data1:d <= 99);

d(1) + d(2) + d(3) + d(4) + d(5) <= 400;
d(1) + 2*d(2) + 2*d(3) + d(4) + 6*d(5) <= 800;
2*d(1) + d(2) + 6*d(3)  <= 200;
d(3) + d(4) +5* d(5) <= 200;
@for(data1:@gin(d));
@for(data1:@bnd(0, d, 99));
end
           

應用Lingo比較熟練的代碼:

model:

sets:
row/1 .. 4/:r;
col/1 .. 5/:c1, c2, x;
all(row, col):a;
endsets

data:
c1 = 1 1 3 4 2;
c2 = -8 -2 -3 -1 -2;
a = 
	1 1 1 1 1
	1 2 2 1 6
	2 1 6 0 0
	0 0 1 1 5;
r = 400 800 200 200;
enddata

max = @sum(col: c1*x^2 + c2*x);

@for(row(i):
		@sum(col(j): a(i, j)*x(j)) <= r(i));
@for(col:@gin(x));
@for(col:@bnd(0, x, 99));

end
           

繼續閱讀