Lanchester战争模型:用可分离变量的微分方程占卜战事
看過國產的戰爭題材電視劇《亮劍》的各位老鐵一定熟悉李云龍集結重兵攻打縣城的故事。在故事中,李云龍利用人數上的優勢對平安縣城進行了圍點打援,最后用二營長的意大利炮消滅了城樓上的鬼子官。
但是眾所周知,抗日時期中國軍隊的單兵作戰能力及武器配備均遠不如日本鬼子。因此最終的勝利是取決于李云龍部隊的數量優勢。
于是矛盾產生了:當我方在單兵作戰效率上不如敵方時,我方需要獲得怎樣的數量優勢已取得戰斗的勝利呢?
早在第一次世界大戰期間,英國工程師F.W Lanchester就利用戰斗中雙方人數的變化率提出了Lanchester戰爭模型用于預測戰爭結果。我相信李云龍在打縣城之前曾研究過這個模型。
(圖源:某貼吧)
//正經的部分來了
模型建立:
首先,我們假設A軍在戰斗開始后的t時刻有x(t)人,B軍在戰斗開始后的t時刻有y(t)人。設,且每支軍隊的減員均由敵方攻擊造成,減員速率與敵方人數成正比。忽略增員部隊與非戰斗減員,我們可以根據雙方的減員速率列出如下的微分方程組
在上述微分方程組中,b與c分別代表B軍與A軍的單兵作戰效率,即每個戰士在單位時間內干掉的敵軍數量。我們可以用這個量來代表士兵的“質量”或“效率”,顯然這個量與軍隊的武器水平,指揮員的指揮水平與戰士的單兵素質有關。
解原微分方程組,
由(2)/(1)得,?bydy=cxdx//注意這一步,我將含y項與含x項分別移入等號兩側
對兩邊同時求不定積分??????
????
兩邊同時求至t的定積分???????
稍作處理,?????????????
?????????????????????????????????????
得到??????????????????????? ??
下面開始分類討論:
我們可以由b,c,與雙方初始人數y0,x0計算出K值
情況1:
當K=0時,有by2=cx2,即當y=0(B軍全部陣亡)時,有x=0(A軍全部陣亡)。故存在一個時刻T,雙方戰平。
情況2:
當K>0時,有by2-cx2=K,此時當x=0(A軍全部陣亡)時,
此時B軍取得勝利。
情況3:
當K<0時,有cx2-by2=-K,此時當y=0(B軍全部陣亡)時,
此時A軍取得勝利。
?
由以上的討論我們可以發現,單兵質量上的優勢對于整體作戰能力的貢獻是線性的,但是數量優勢與對于整體作戰能力的貢獻是成平方關系的。這也就能解釋為什么在二戰中蘇聯紅軍在裝備,指戰員才能與單兵作戰能力均不如德軍的情況下能夠以自身絕對的數量優勢戰勝敵軍。
??? (圖源:百度圖片)
?
作為一個熱愛計算機編程的高二狗,本能告訴我這種數學模型可以代入計算機由程序解決。于是我在學校上課期間(基本上是下課的時候),冒著被老班收掉MacBook Pro的風險寫下了如下Java小程序(不要告訴老師O(∩_∩)O謝謝):
public class Army {
???private String name;
???private double quantity;
???private double warIndex;
???public Army(){
???????name="";
???????quantity=0;
??? }
???public Army(String n,double q,double i){
???????name=n;
???????quantity=q;
???????warIndex=i;
??? }
?
???public double getQuantity() {
???????return quantity;
??? }
?
???public double getWarIndex() {
???????return warIndex;
??? }
?
???public String getName() {
???????return name;
??? }
}
//以上我創建了一個“Army”類(請自動將所有的Index(指數)看成coefficient(系數))
//下面我需要一個客戶端,以進行相關運算
import java.util.Scanner;
public class Client{
???public static void main(String[] args){
???????double K;
???Scanner sc=new Scanner(System.in);
???????Scanner reader=new Scanner(System.in);
???System.out.println("Please input the name/quantity/warIndex of army1:");
???Army army1=new Army(sc.nextLine(),sc.nextDouble(),sc.nextDouble());
???????System.out.println("Please input the name/quantity/warIndex of army2:");
???????Army army2=newArmy(reader.nextLine(),reader.nextDouble(),reader.nextDouble());
???????K=army2.getWarIndex()*Math.pow(army2.getQuantity(),2)-army1.getWarIndex()*Math.pow(army1.getQuantity(),2);
???????if(K==0){
???????????System.out.println("It's a tie");
???????}
???????else if(K<0){
???????????double rest=Math.sqrt((-K)/army1.getWarIndex());
???????????System.out.println(army1.getName()+" "+"wins");
???????????System.out.println("The rest quantity of "+""+army1.getName()+":"+rest);
???????}
???????else if(K>0){
???????????double rest=Math.sqrt((K)/army2.getWarIndex());
???????????System.out.println(army2.getName()+" "+"wins");
???????????System.out.println("The rest quantity of "+""+army2.getName()+":"+rest);
???????}
??? }
}
//(噓!傳說李云龍在戰前用這個程序算了一卦)
下面我們來舉一個栗子:假設李云龍的八路軍有100人,鬼子有50人,設雙方單兵作戰效率均為1(客觀地說,當時不太可能),兩軍交戰.則經過程序處理后,運行得到下列結果:
Please input the name/quantity/warIndex ofarmy 1:
Balu
100
1
Please input the name/quantity/warIndex ofarmy 2:
Guizi
50
1
Balu wins
The rest quantity of? Balu:86.60254037844386
?
Process finished with exit code 0
即當鬼子被全殲時,八路軍剩余約87人(陣亡13人)
?
現在給太君們一個翻盤的機會:將每個鬼子的單兵作戰效率提升至八路軍的4倍(2的平方)
運行客戶端程序,得到下列結果:
Please input the name/quantity/warIndex ofarmy 1:
Balu
100
1
Please input the name/quantity/warIndex ofarmy 2:
Guizi
50
4
It's a tie
?
Process finished with exit code 0
?
Oops!即使擁有了4倍于對方的效率,可憐的鬼子還是贏不了,只能與八路打成平手。(請各位老鐵自己去看看《亮劍》,估計一下李云龍部隊的數量是投入戰斗的鬼子的幾倍)。
?
這樣一來,數量優勢對于整體作戰能力的貢獻是成平方關系的規律得到了驗證。這個規律也就是蘭徹斯特平方定律。
?
利用這個數學模型,我們不用再去廟里給菩薩上香或是夜觀天象,而是可以理性地利用科學占卜戰事走向,根據敵我雙方實力做出合理的兵力分配,以獲得最大程度的作戰效益。
?
這里還有2個問題有待解決:如何確定敵我雙方的單兵作戰效率(即系數b,c)?如何最佳地規定單位時間的設置?對于后者,我作為一個沒有上過軍校或戰場的高中生并沒有資格發言。但是對于前者,我寫了一個程序,但是不確定正確與否,由于時間倉促加之老班太嚴,我并不能在交稿前對其進一步研究。
這里僅附上其源代碼,供評論區各位大佬批評指正。
import java.util.Scanner;
public class warIndex {
???public static void main(String[] args){
???????int n,counter;
???????double sum1,sum2;
???????sum1=0;
???????sum2=0;
???????System.out.println("Please input the quantity (in groups) ofdata");
???????Scanner reader=new Scanner(System.in);
???????n=reader.nextInt();
???????double[] warIndex1=new double[n+1];
???????double[] warIndex2=new double[n+1];
???????System.out.println("Please input the casualty of army1(group bygroup):");
???????Scanner rd=new Scanner(System.in);
???????double[] cas1=new double[n+1];
???????for (counter=0;counter<=(n-1);counter++){
???????????cas1[counter]=rd.nextDouble();
???????}
???????System.out.println("Please input the total quantity of army1(groupby group):");
???????Scanner rdd=new Scanner(System.in);
???? ???double[] quantity1=new double[n+1];
???????for (counter=0;counter<=(n-1);counter++){
???????????quantity1[counter]=rdd.nextDouble();
???????}
???????System.out.println("Please input the casualty of army2(group bygroup):");
???????Scanner scc=new Scanner(System.in);
???????double[] cas2=new double[n+1];
???????for (counter=0;counter<=(n-1);counter++){
???????????cas2[counter]=scc.nextDouble();
???????}
???????System.out.println("Please input the total quantity of army2(groupby group):");
???? ???Scanner rddd=new Scanner(System.in);
???????double[] quantity2=new double[n+1];
???????for (counter=0;counter<=(n-1);counter++){
???????????quantity2[counter]=rddd.nextDouble();
???????}
???????System.out.println("Please input the time consumed forbattles(group by group):");
???????double[] time=new double[n+1];
???????Scanner scanner=new Scanner(System.in);
???????for (counter=0;counter<=(n-1);counter++){
???????????time[counter]=scanner.nextDouble();
???????}
???????for (counter=0;counter<=(n-1);counter++){
???????????warIndex1[counter]=cas2[counter]/(quantity1[counter]*time[counter]);
???????}
???????for (counter=0;counter<=(n-1);counter++){
???????????sum1=sum1+warIndex1[counter];
???????}
???????for (counter=0;counter<=(n-1);counter++){
???????????warIndex2[counter]=cas1[counter]/(quantity2[counter]*time[counter]);
???????}
???????for (counter=0;counter<=(n-1);counter++){
???????????sum2=sum2+warIndex2[counter];
???????}
???????System.out.println("The warIndex of army1="+sum1/n);
???????System.out.println("The warIndex of army2="+sum2/n);
??? }
}
//在上述程序中,用戶需要輸入所需數據的數量,A軍在每場試驗性戰斗中的陣亡人數,A軍在每場試驗性戰斗中的總人數;B軍在每場試驗性戰斗中的陣亡人數,B軍在每場試驗性戰斗中的總人數及每場戰斗的持續時間。最后程序會計算出雙方單兵作戰效率的平均值供指戰員決策時作參考
?
最后,我們應該珍愛和平,決不首先發動戰爭。但是,當祖國受到侵略,人民的生命財產安全受到威脅之時,我們要全方位的武裝自己,保家衛國,維護世界和平。
Dove of peace (圖源:百度圖片)
參考文獻:
《高等數學軍事應用案例》? 主編:但琦 ?國防工業出版社
作者:羅漫,浦東外國語學校
總結
以上是生活随笔為你收集整理的Lanchester战争模型:用可分离变量的微分方程占卜战事的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 快速成长为数据挖掘高手的秘诀
- 下一篇: 通过听力写代码?盲人程序员就是这样做的