|
1 | | -# python-lanchester |
2 | | -Python Lanchester |
| 1 | + |
| 2 | +**Python 3+**, current release: **1.0.0** build 2022-07-21 |
| 3 | + |
| 4 | +# Python Lanchester's laws |
| 5 | + |
| 6 | +**A Python module, a Jupyter notebook and a sample application for predicting the result of a battle using Lanchester differential equations. The module can predict the result with 3 different models: `linear law`, `square law` and `modernized model`. An example included in the repository allows you to predict the result using one of these 3 models and display the result and a plot with the course of the battle over time. The module can be easily used in any Python application.** |
| 7 | + |
| 8 | +## What are Lanchester's laws? |
| 9 | +from: https://en.wikipedia.org/wiki/Lanchester%27s_laws |
| 10 | +> Lanchester's laws are mathematical formulae for calculating the relative strengths of military forces. The Lanchester equations are differential equations describing the time dependence of two armies' strengths A and B as a function of time, with the function depending only on A and B. |
| 11 | +In 1915 and 1916, during World War I, M. Osipov and Frederick Lanchester independently devised a series of differential equations to demonstrate the power relationships between opposing forces. Among these are what is known as Lanchester's linear law (for ancient combat) and Lanchester's square law (for modern combat with long-range weapons such as firearms). |
| 12 | + |
| 13 | + |
| 14 | + |
| 15 | +## Repository contents: |
| 16 | + |
| 17 | +- `lanchester.py` - Python module with functions that solve the Lanchester equations in time |
| 18 | +- `app.py` - sample example application that uses the module |
| 19 | +- `notebook.ipynb` - Jupyter notebook with an example of how it works in real-time |
| 20 | + |
| 21 | + |
| 22 | +### Example of use: |
| 23 | + |
| 24 | +The module can predict the result using 3 different models: `linear law`, `square law` and `modernized model`. |
| 25 | + |
| 26 | +**Required libraries** |
| 27 | + |
| 28 | +- `numpy` |
| 29 | +- `matplotlib` |
| 30 | + |
| 31 | + |
| 32 | +**Method #1: linear law** |
| 33 | + |
| 34 | +```python |
| 35 | +# app.py |
| 36 | + |
| 37 | +import numpy as np |
| 38 | +import matplotlib.pyplot as plt |
| 39 | +import lanchester |
| 40 | + |
| 41 | +# base parameters: |
| 42 | +R0 = 8000 # number of RED units |
| 43 | +B0 = 10000 # number of BLUE units |
| 44 | +T = 100 # total number of steps in the simulation |
| 45 | +dt = 1 # time interval |
| 46 | + |
| 47 | + |
| 48 | +# parameters for "linear" and "modernized" models: |
| 49 | +r_l = 0.00001 # combat efficiency of RED units |
| 50 | +b_l = 0.00002 # combat efficiency of BLUE units |
| 51 | + |
| 52 | +R, B = lanchester.linear(R0, B0, r_l, b_l, T, dt) # result |
| 53 | + |
| 54 | +``` |
| 55 | + |
| 56 | +**Method #2: square law** |
| 57 | + |
| 58 | +```python |
| 59 | +# app.py |
| 60 | + |
| 61 | +import numpy as np |
| 62 | +import matplotlib.pyplot as plt |
| 63 | +import lanchester |
| 64 | + |
| 65 | +# base parameters: |
| 66 | +R0 = 8000 # number of RED units |
| 67 | +B0 = 10000 # number of BLUE units |
| 68 | +T = 100 # total number of steps in the simulation |
| 69 | +dt = 1 # time interval |
| 70 | + |
| 71 | +# parameters for "square" and "modernized" models: |
| 72 | +r_s = 0.2 # average number of RED units that damage each other per unit of time |
| 73 | +b_s = 0.1 # average number of BLUE units that damage each other per unit of time |
| 74 | + |
| 75 | +R, B = lanchester.square(R0, B0, r_s, b_s, T, dt) # result |
| 76 | + |
| 77 | +``` |
| 78 | + |
| 79 | +**Method #3: modernized model** |
| 80 | + |
| 81 | +```python |
| 82 | +# app.py |
| 83 | + |
| 84 | +import numpy as np |
| 85 | +import matplotlib.pyplot as plt |
| 86 | +import lanchester |
| 87 | + |
| 88 | +# base parameters: |
| 89 | +R0 = 8000 # number of RED units |
| 90 | +B0 = 10000 # number of BLUE units |
| 91 | +T = 100 # total number of steps in the simulation |
| 92 | +dt = 1 # time interval |
| 93 | + |
| 94 | +# parameters for "linear" and "modernized" models: |
| 95 | +r_l = 0.00001 # combat efficiency of RED units |
| 96 | +b_l = 0.00002 # combat efficiency of BLUE units |
| 97 | + |
| 98 | + |
| 99 | +# parameters for "square" and "modernized" models: |
| 100 | +r_s = 0.2 # average number of RED units that damage each other per unit of time |
| 101 | +b_s = 0.1 # average number of BLUE units that damage each other per unit of time |
| 102 | + |
| 103 | + |
| 104 | +# parameters for "modernized" model only: |
| 105 | +r_f = 0.6 # RED units camouflage ability factor |
| 106 | +b_f = 0.2 # BLUE units camouflage ability factor |
| 107 | + |
| 108 | +r_a = 0.6 # RED units ability to recognize |
| 109 | +b_a = 0.2 # BLUE units ability to recognize |
| 110 | + |
| 111 | +r_i = 4 # RED units information warfare ability coefficient |
| 112 | +b_i = 4 # BLUE units information warfare ability coefficient |
| 113 | + |
| 114 | +R, B = lanchester.modernized(R0, B0, r_l, b_l, r_s, b_s, r_f, r_a, b_f, b_a, r_i, b_i, T, dt) # result |
| 115 | +``` |
| 116 | + |
| 117 | +**Displaying result and plot from obtained predictions** |
| 118 | + |
| 119 | +```python |
| 120 | + |
| 121 | +# display result |
| 122 | +print("Predicted result of the battle:\n") |
| 123 | + |
| 124 | +if R[-1] > B[-1]: |
| 125 | + print("Winner: RED") |
| 126 | +else: |
| 127 | + print("Winner: BLUE") |
| 128 | + |
| 129 | +# display remaining units info |
| 130 | +print("Remaining RED units [", R[-1], "]") |
| 131 | +print("Remaining BLUE units [", B[-1], "]") |
| 132 | + |
| 133 | +# display result on plot |
| 134 | +t = np.arange(0, len(R) * dt, dt) |
| 135 | + |
| 136 | +plt.figure(1) |
| 137 | +plt.plot(t, R, '--r', label='RED units') |
| 138 | +plt.plot(t, B, 'b', label='BLUE units') |
| 139 | +plt.xlabel("Time (round)") |
| 140 | +plt.ylabel("Number of units") |
| 141 | +plt.title("Lanchester's model simulation") |
| 142 | +plt.legend() |
| 143 | +plt.show() |
| 144 | +``` |
| 145 | + |
| 146 | +**Result:** |
| 147 | + |
| 148 | + |
| 149 | + |
| 150 | + |
| 151 | +## Changelog |
| 152 | +**- 1.0.0** - published first release (2022-07-21) |
| 153 | + |
| 154 | +## Credits |
| 155 | + |
| 156 | +### Python Lanchester is free to use but if you liked then you can donate project via BTC: |
| 157 | + |
| 158 | +**14X6zSCbkU5wojcXZMgT9a4EnJNcieTrcr** |
| 159 | + |
| 160 | +or by PayPal: |
| 161 | + **[https://www.paypal.me/szczyglinski](https://www.paypal.me/szczyglinski)** |
| 162 | + |
| 163 | + |
| 164 | +**Enjoy!** |
| 165 | + |
| 166 | +MIT License | 2022 Marcin 'szczyglis' Szczygliński |
| 167 | + |
| 168 | +https://github.com/szczyglis-dev/python-lanchester |
| 169 | + |
| 170 | + |
0 commit comments