orkit-edu 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Meghashyam
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,335 @@
1
+ Metadata-Version: 2.4
2
+ Name: orkit-edu
3
+ Version: 0.1.0
4
+ Summary: Educational Operations Research algorithms in plain Python
5
+ Author: Meghashyam
6
+ License-Expression: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Intended Audience :: Education
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: numpy>=1.24.0
13
+ Requires-Dist: matplotlib>=3.7.0
14
+ Dynamic: license-file
15
+
16
+ # ORKit: A Python Library for Operations Research Optimization
17
+
18
+ **ORKit** is a modular, educational Python library implementing classical Operations Research (OR) optimization algorithms from first principles. Built specifically as an undergraduate mini-project, ORKit prioritizes clarity, transparency, and explainability over industrial scale. Every algorithm is implemented with plain Python loops, conditions, and standard data structures so that every step can be traced and understood in an academic viva.
19
+
20
+ ---
21
+
22
+ ## 1. Project Overview & Problem Statement
23
+
24
+ Operations Research algorithms often form the backbone of decision sciences, logistics, and resource allocation. While industrial solvers (such as CPLEX, Gurobi, or PuLP) treat algorithms as black-box solvers, students and educators require clear, inspectable code that mirrors standard textbook steps.
25
+
26
+ **ORKit** provides clean, dependency-minimal implementations of core OR techniques without third-party mathematical programming solvers. Every calculation step—from simplex pivots to Hungarian line coverings—is recorded and accessible in plain Python dictionaries.
27
+
28
+ ---
29
+
30
+ ## 2. Objectives
31
+
32
+ 1. **Pedagogical Clarity**: Code directly reflects formulations from standard undergraduate OR textbooks.
33
+ 2. **First-Principles Implementation**: No solver dependencies (SciPy optimize, PuLP, OR-Tools, CVXPY are strictly excluded).
34
+ 3. **Reproducibility**: Hand-verified examples with complete automated test coverage.
35
+ 4. **Interactive Learning**: Standalone Jupyter notebooks with step-by-step calculations and visual representations.
36
+
37
+ ---
38
+
39
+ ## 3. Features & Implemented Algorithms
40
+
41
+ | Module | Algorithms / Functions | Description |
42
+ | :--- | :--- | :--- |
43
+ | **LPP** (`lpp.py`) | `solve_graphical`<br>`solve_simplex` | Corner-point intersection method for 2-variable linear programs; Tableau-based Simplex method for canonical $\le$ constraints. |
44
+ | **Visualization** (`visualization.py`) | `plot_feasible_region` | Feasible region grid shading, boundary lines, corner point markers, and optimal solution callout (2 variables). |
45
+ | **Transportation** (`transportation.py`) | `balance_problem`<br>`north_west_corner`<br>`least_cost_method`<br>`vogels_approximation`<br>`modi_method` | Initial feasible solutions via North-West Corner, Least Cost (Matrix Minimum), and Vogel's Approximation Method (VAM); optimal solution via Modified Distribution (MODI / $u$-$v$) method with closed-loop stepping stone pivots. |
46
+ | **Assignment** (`assignment.py`) | `hungarian_method` | Classical Hungarian algorithm (Kuhn-Munkres) with row/column reductions, textbook line covering, and zero-assignment matching. Supports negative costs. |
47
+ | **Network** (`network.py`) | `cpm`<br>`pert` | Critical Path Method (topological sort, forward/backward passes, slacks, critical path); PERT analysis using 3-point time estimates ($a, m, b$) and critical variance. |
48
+ | **Game Theory** (`game_theory.py`) | `row_minima`<br>`column_maxima`<br>`maximin`<br>`minimax`<br>`find_saddle_points`<br>`solve_pure_strategy`<br>`solve_mixed_2x2` | Zero-sum two-player matrix games; minimax-maximin pure strategy saddle point determination; analytical odds formulas for $2 \times 2$ mixed strategy games. |
49
+ | **Display** (`display.py`) | `format_result`<br>`display_result` | Formats solver result dictionaries into clean, tabular, viva-ready terminal reports. |
50
+
51
+
52
+ ---
53
+
54
+ ## 4. Project Structure
55
+
56
+ ```text
57
+ ORKit/
58
+ ├── orkit/
59
+ │ ├── __init__.py # Exports public API functions
60
+ │ ├── core.py # Shared validation helpers, clean_number & build_result
61
+ │ ├── display.py # Presentation formatters (display_result, format_result)
62
+ │ ├── lpp.py # Graphical and Simplex LPP solvers
63
+ │ ├── transportation.py # NW Corner, Least Cost, VAM, and MODI methods
64
+ │ ├── assignment.py # Hungarian assignment algorithm (supports negative costs)
65
+ │ ├── network.py # CPM schedule and PERT calculations
66
+ │ ├── game_theory.py # Zero-sum pure and 2x2 mixed strategy solvers
67
+ │ └── visualization.py # LPP feasible-region grid plot
68
+ ├── notebooks/
69
+ │ ├── 01_lpp.ipynb
70
+ │ ├── 02_transportation.ipynb
71
+ │ ├── 03_assignment.ipynb
72
+ │ ├── 04_cpm_pert.ipynb
73
+ │ └── 05_game_theory.ipynb
74
+ ├── tests/
75
+ │ ├── test_assignment.py
76
+ │ ├── test_display.py
77
+ │ ├── test_game_theory.py
78
+ │ ├── test_lpp.py
79
+ │ ├── test_network.py
80
+ │ └── test_transportation.py
81
+ ├── examples/
82
+ │ └── sample_problems.py # Complete runnable demonstration script
83
+ ├── LICENSE # MIT License
84
+ ├── requirements.txt # Core dependencies and notebook tooling
85
+ ├── pyproject.toml # Packaging configuration for editable install
86
+ ├── .gitignore # Git ignore rules for environments and caches
87
+ └── README.md # Project documentation
88
+ ```
89
+
90
+ ---
91
+
92
+ ## 5. Requirements & Installation
93
+
94
+ ORKit requires **Python 3.10+**.
95
+
96
+ ### Installation from PyPI
97
+
98
+ > [!NOTE]
99
+ > PyPI installation will only work after the package is published to PyPI.
100
+
101
+ The package is published as `orkit-edu` on PyPI; import it as `orkit`.
102
+
103
+ ```bash
104
+ pip install orkit-edu
105
+ ```
106
+
107
+ Then in Python:
108
+ ```python
109
+ import orkit
110
+ ```
111
+
112
+ ### Clone and Install in Editable Mode
113
+ ```bash
114
+ # Optional: create and activate a virtual environment
115
+ python -m venv .venv
116
+ # Windows:
117
+ .venv\Scripts\activate
118
+ # Linux/macOS:
119
+ source .venv/bin/activate
120
+
121
+ # Install dependencies and ORKit in editable development mode
122
+ pip install -r requirements.txt
123
+ pip install -e .
124
+ ```
125
+
126
+ Verify installation:
127
+ ```bash
128
+ python -c "import orkit; print('ORKit imported successfully!')"
129
+ ```
130
+
131
+ ---
132
+
133
+ ## 6. Input & Output Formats
134
+
135
+ All ORKit optimization solvers return **plain Python dictionaries** containing standard keys:
136
+ - `"status"`: `"optimal"`, `"infeasible"`, or `"unbounded"` (or `"no_saddle_point"`).
137
+ - `"solution"`: Dictionary or list containing decision variable values or allocations.
138
+ - `"objective_value"`: Numeric optimal value ($Z$, cost, duration, game value).
139
+ - `"steps"`: List of human-readable strings explaining each calculation step.
140
+
141
+ ### Displaying Results
142
+
143
+ ORKit includes presentation helpers in `orkit.display` to render clean, aligned, viva-ready terminal reports. Use `display_result(result, show_steps=True)` to print the formatted report (or `format_result` to retrieve the formatted string):
144
+
145
+ ```python
146
+ from orkit import solve_graphical, display_result
147
+
148
+ c = [3, 5]
149
+ A = [[1, 0], [0, 2], [3, 2]]
150
+ b = [4, 12, 18]
151
+ signs = ["<=", "<=", "<="]
152
+
153
+ result = solve_graphical(c, A, b, signs, maximize=True)
154
+
155
+ # Display result with step-by-step calculations
156
+ display_result(result, show_steps=True)
157
+ ```
158
+
159
+ These helpers are strictly for output formatting; the underlying solver return dictionary remains untouched and directly accessible.
160
+
161
+ ### Quick Usage Examples
162
+
163
+ #### 1. Linear Programming (Graphical & Simplex)
164
+ ```python
165
+ from orkit import solve_graphical, solve_simplex, plot_feasible_region
166
+
167
+ c = [3, 5]
168
+ A = [[1, 0], [0, 2], [3, 2]]
169
+ b = [4, 12, 18]
170
+ signs = ["<=", "<=", "<="]
171
+
172
+ # Graphical solver (2 variables)
173
+ res_graph = solve_graphical(c, A, b, signs, maximize=True)
174
+ print(res_graph["solution"]) # {'x1': 2, 'x2': 6}
175
+ print(res_graph["objective_value"]) # 36
176
+
177
+ # Simplex solver
178
+ res_simp = solve_simplex(c, A, b, maximize=True)
179
+ print(res_simp["solution"]) # {'x1': 2, 'x2': 6}
180
+ print(res_simp["objective_value"]) # 36
181
+
182
+ # Plot feasible region
183
+ fig = plot_feasible_region(c, A, b, signs, maximize=True)
184
+ # fig.savefig("feasible_region.png")
185
+ ```
186
+
187
+ #### 2. Transportation Problem
188
+ ```python
189
+ from orkit import vogels_approximation, modi_method
190
+
191
+ cost_matrix = [
192
+ [19, 30, 50, 10],
193
+ [70, 30, 40, 60],
194
+ [40, 8, 70, 20]
195
+ ]
196
+ supply = [7, 9, 18]
197
+ demand = [5, 8, 7, 14]
198
+
199
+ # Initial solution via VAM
200
+ vam_res = vogels_approximation(cost_matrix, supply, demand)
201
+ print("VAM Cost:", vam_res["objective_value"]) # 779
202
+
203
+ # Optimal solution via MODI (u-v method)
204
+ modi_res = modi_method(cost_matrix, supply, demand, initial_method="vam")
205
+ print("Optimal Cost:", modi_res["objective_value"]) # 743
206
+ print("Allocations:", modi_res["allocation"])
207
+ # [[5, 0, 0, 2], [0, 2, 7, 0], [0, 6, 0, 12]]
208
+ ```
209
+
210
+ #### 3. Assignment Problem (Hungarian Method)
211
+ ```python
212
+ from orkit import hungarian_method
213
+
214
+ cost_matrix = [
215
+ [9, 2, 7, 8],
216
+ [6, 4, 3, 7],
217
+ [5, 8, 1, 8],
218
+ [7, 6, 9, 4]
219
+ ]
220
+ res = hungarian_method(cost_matrix)
221
+ print("Optimal Cost:", res["objective_value"]) # 13
222
+ print("Assignments:", res["assignments"]) # [(0, 1), (1, 0), (2, 2), (3, 3)]
223
+ ```
224
+
225
+ #### 4. Project Network Analysis (CPM & PERT)
226
+ ```python
227
+ from orkit import cpm, pert
228
+
229
+ # Activity dictionary format: name -> {"duration": num, "predecessors": list}
230
+ cpm_activities = {
231
+ "A": {"duration": 3, "predecessors": []},
232
+ "B": {"duration": 4, "predecessors": ["A"]},
233
+ "C": {"duration": 2, "predecessors": ["A"]},
234
+ "D": {"duration": 5, "predecessors": ["B", "C"]},
235
+ }
236
+ cpm_res = cpm(cpm_activities)
237
+ print("Duration:", cpm_res["project_duration"]) # 12
238
+ print("Critical Path:", cpm_res["critical_path"]) # ['A', 'B', 'D']
239
+ print("Slack:", cpm_res["slack"]) # {'A': 0, 'B': 0, 'C': 2, 'D': 0}
240
+
241
+ # PERT 3-point estimates: name -> {"a": opt, "m": likely, "b": pess, "predecessors": list}
242
+ pert_activities = {
243
+ "A": {"a": 1, "m": 3, "b": 5, "predecessors": []},
244
+ "B": {"a": 2, "m": 4, "b": 6, "predecessors": ["A"]},
245
+ "C": {"a": 1, "m": 2, "b": 3, "predecessors": ["A"]},
246
+ "D": {"a": 3, "m": 5, "b": 7, "predecessors": ["B", "C"]},
247
+ }
248
+ pert_res = pert(pert_activities)
249
+ print("Expected Duration:", pert_res["project_expected_duration"]) # 12
250
+ print("Critical Variance:", pert_res["project_variance"]) # 1.33333333
251
+ ```
252
+
253
+ #### 5. Game Theory
254
+ ```python
255
+ from orkit import solve_pure_strategy, solve_mixed_2x2
256
+
257
+ # Pure strategy saddle point game
258
+ saddle_payoff = [[3, 5], [2, 4]]
259
+ print(solve_pure_strategy(saddle_payoff))
260
+ # status: 'optimal', saddle_points: [(0, 0)], objective_value: 3
261
+
262
+ # Mixed strategy 2x2 game
263
+ mixed_payoff = [[2, 4], [3, 1]]
264
+ res = solve_mixed_2x2(mixed_payoff)
265
+ print("p:", res["p"]) # [0.5, 0.5]
266
+ print("q:", res["q"]) # [0.75, 0.25]
267
+ print("Value:", res["objective_value"]) # 2.5
268
+ ```
269
+
270
+ ---
271
+
272
+ ## 7. Running Demonstrations, Tests, and Notebooks
273
+
274
+ ### Run Sample Problems Script
275
+ ```bash
276
+ python examples/sample_problems.py
277
+ ```
278
+
279
+ ### Run Test Suite
280
+ ```bash
281
+ pytest
282
+ ```
283
+
284
+ ### Execute Notebooks
285
+ The five demonstration notebooks can be launched interactively via Jupyter:
286
+ ```bash
287
+ jupyter notebook
288
+ ```
289
+ Or executed headless one notebook per command with outputs saved in-place. The kernel must be installed once per machine with:
290
+ ```bash
291
+ python -m ipykernel install --user --name orkit-venv
292
+ ```
293
+ Then execute each notebook specifying the registered kernel:
294
+ ```bash
295
+ python -m jupyter nbconvert --to notebook --execute --inplace --ExecutePreprocessor.kernel_name=orkit-venv notebooks/01_lpp.ipynb
296
+ python -m jupyter nbconvert --to notebook --execute --inplace --ExecutePreprocessor.kernel_name=orkit-venv notebooks/02_transportation.ipynb
297
+ python -m jupyter nbconvert --to notebook --execute --inplace --ExecutePreprocessor.kernel_name=orkit-venv notebooks/03_assignment.ipynb
298
+ python -m jupyter nbconvert --to notebook --execute --inplace --ExecutePreprocessor.kernel_name=orkit-venv notebooks/04_cpm_pert.ipynb
299
+ python -m jupyter nbconvert --to notebook --execute --inplace --ExecutePreprocessor.kernel_name=orkit-venv notebooks/05_game_theory.ipynb
300
+ ```
301
+
302
+ ---
303
+
304
+ ## 8. Honest Limitations & Design Assumptions
305
+
306
+ In accordance with ORKit's educational purpose, scope is deliberately focused on foundational methods:
307
+ 1. **Linear Programming**:
308
+ - `solve_simplex` strictly supports canonical problems with $\le$ constraints and $b \ge 0$ (variables $\ge 0$). Big-M, Two-Phase simplex, and anti-cycling Bland's rule are not implemented.
309
+ - `solve_graphical` supports exactly 2 decision variables. Unboundedness is detected via an artificial bounding box ($10^6$).
310
+ - `plot_feasible_region` shades the feasible region using a numerical grid across the bounding view window.
311
+ 2. **Transportation**:
312
+ - `modi_method` supports cost minimization only. Degeneracy is resolved by selecting non-loop-forming cells in row-major order with zero allocation.
313
+ 3. **Assignment**:
314
+ - `hungarian_method` supports square and rectangular matrices (padded with zero-cost dummy rows or columns) and accepts negative costs by shifting the matrix via minimum reduction. The $O(n^3)$ dual potential implementation is omitted in favor of the explainable textbook line-covering method.
315
+ 4. **Project Network**:
316
+ - `cpm` returns one deterministic primary critical path (all critical activities with slack 0 are listed in `critical_activities`).
317
+ - `pert` calculates expected critical path duration and variance; normal distribution $Z$-lookup probabilities of completion are not computed. Network diagrams are not generated.
318
+ 5. **Game Theory**:
319
+ - Mixed strategy analytical formulas are implemented strictly for $2 \times 2$ zero-sum games without dominance reduction. LP-based solving for $m \times n$ mixed games is out of scope.
320
+ 6. **Display Helpers**:
321
+ - Formatters in `orkit.display` (`display_result`, `format_result`) are designed strictly for terminal presentation and student demonstration; they do not alter solver data structures.
322
+
323
+ ---
324
+
325
+ ## 9. Future Scope (Not Implemented)
326
+
327
+ The following advanced operations research techniques are **NOT implemented** in this undergraduate release and represent prospective future work:
328
+ - Integer Linear Programming (ILP) and Branch-and-Bound
329
+ - Sensitivity and Post-Optimality Analysis
330
+ - Job Sequencing and Johnson's Algorithm
331
+ - Inventory Control Models (EOQ, EPQ, safety stock)
332
+ - Queuing Theory ($M/M/1$, $M/M/c$)
333
+ - Monte Carlo Simulation
334
+ - $m \times n$ Game Theory via Linear Programming / Subgame Dominance
335
+ - Automated PERT/CPM Network Graph rendering
@@ -0,0 +1,320 @@
1
+ # ORKit: A Python Library for Operations Research Optimization
2
+
3
+ **ORKit** is a modular, educational Python library implementing classical Operations Research (OR) optimization algorithms from first principles. Built specifically as an undergraduate mini-project, ORKit prioritizes clarity, transparency, and explainability over industrial scale. Every algorithm is implemented with plain Python loops, conditions, and standard data structures so that every step can be traced and understood in an academic viva.
4
+
5
+ ---
6
+
7
+ ## 1. Project Overview & Problem Statement
8
+
9
+ Operations Research algorithms often form the backbone of decision sciences, logistics, and resource allocation. While industrial solvers (such as CPLEX, Gurobi, or PuLP) treat algorithms as black-box solvers, students and educators require clear, inspectable code that mirrors standard textbook steps.
10
+
11
+ **ORKit** provides clean, dependency-minimal implementations of core OR techniques without third-party mathematical programming solvers. Every calculation step—from simplex pivots to Hungarian line coverings—is recorded and accessible in plain Python dictionaries.
12
+
13
+ ---
14
+
15
+ ## 2. Objectives
16
+
17
+ 1. **Pedagogical Clarity**: Code directly reflects formulations from standard undergraduate OR textbooks.
18
+ 2. **First-Principles Implementation**: No solver dependencies (SciPy optimize, PuLP, OR-Tools, CVXPY are strictly excluded).
19
+ 3. **Reproducibility**: Hand-verified examples with complete automated test coverage.
20
+ 4. **Interactive Learning**: Standalone Jupyter notebooks with step-by-step calculations and visual representations.
21
+
22
+ ---
23
+
24
+ ## 3. Features & Implemented Algorithms
25
+
26
+ | Module | Algorithms / Functions | Description |
27
+ | :--- | :--- | :--- |
28
+ | **LPP** (`lpp.py`) | `solve_graphical`<br>`solve_simplex` | Corner-point intersection method for 2-variable linear programs; Tableau-based Simplex method for canonical $\le$ constraints. |
29
+ | **Visualization** (`visualization.py`) | `plot_feasible_region` | Feasible region grid shading, boundary lines, corner point markers, and optimal solution callout (2 variables). |
30
+ | **Transportation** (`transportation.py`) | `balance_problem`<br>`north_west_corner`<br>`least_cost_method`<br>`vogels_approximation`<br>`modi_method` | Initial feasible solutions via North-West Corner, Least Cost (Matrix Minimum), and Vogel's Approximation Method (VAM); optimal solution via Modified Distribution (MODI / $u$-$v$) method with closed-loop stepping stone pivots. |
31
+ | **Assignment** (`assignment.py`) | `hungarian_method` | Classical Hungarian algorithm (Kuhn-Munkres) with row/column reductions, textbook line covering, and zero-assignment matching. Supports negative costs. |
32
+ | **Network** (`network.py`) | `cpm`<br>`pert` | Critical Path Method (topological sort, forward/backward passes, slacks, critical path); PERT analysis using 3-point time estimates ($a, m, b$) and critical variance. |
33
+ | **Game Theory** (`game_theory.py`) | `row_minima`<br>`column_maxima`<br>`maximin`<br>`minimax`<br>`find_saddle_points`<br>`solve_pure_strategy`<br>`solve_mixed_2x2` | Zero-sum two-player matrix games; minimax-maximin pure strategy saddle point determination; analytical odds formulas for $2 \times 2$ mixed strategy games. |
34
+ | **Display** (`display.py`) | `format_result`<br>`display_result` | Formats solver result dictionaries into clean, tabular, viva-ready terminal reports. |
35
+
36
+
37
+ ---
38
+
39
+ ## 4. Project Structure
40
+
41
+ ```text
42
+ ORKit/
43
+ ├── orkit/
44
+ │ ├── __init__.py # Exports public API functions
45
+ │ ├── core.py # Shared validation helpers, clean_number & build_result
46
+ │ ├── display.py # Presentation formatters (display_result, format_result)
47
+ │ ├── lpp.py # Graphical and Simplex LPP solvers
48
+ │ ├── transportation.py # NW Corner, Least Cost, VAM, and MODI methods
49
+ │ ├── assignment.py # Hungarian assignment algorithm (supports negative costs)
50
+ │ ├── network.py # CPM schedule and PERT calculations
51
+ │ ├── game_theory.py # Zero-sum pure and 2x2 mixed strategy solvers
52
+ │ └── visualization.py # LPP feasible-region grid plot
53
+ ├── notebooks/
54
+ │ ├── 01_lpp.ipynb
55
+ │ ├── 02_transportation.ipynb
56
+ │ ├── 03_assignment.ipynb
57
+ │ ├── 04_cpm_pert.ipynb
58
+ │ └── 05_game_theory.ipynb
59
+ ├── tests/
60
+ │ ├── test_assignment.py
61
+ │ ├── test_display.py
62
+ │ ├── test_game_theory.py
63
+ │ ├── test_lpp.py
64
+ │ ├── test_network.py
65
+ │ └── test_transportation.py
66
+ ├── examples/
67
+ │ └── sample_problems.py # Complete runnable demonstration script
68
+ ├── LICENSE # MIT License
69
+ ├── requirements.txt # Core dependencies and notebook tooling
70
+ ├── pyproject.toml # Packaging configuration for editable install
71
+ ├── .gitignore # Git ignore rules for environments and caches
72
+ └── README.md # Project documentation
73
+ ```
74
+
75
+ ---
76
+
77
+ ## 5. Requirements & Installation
78
+
79
+ ORKit requires **Python 3.10+**.
80
+
81
+ ### Installation from PyPI
82
+
83
+ > [!NOTE]
84
+ > PyPI installation will only work after the package is published to PyPI.
85
+
86
+ The package is published as `orkit-edu` on PyPI; import it as `orkit`.
87
+
88
+ ```bash
89
+ pip install orkit-edu
90
+ ```
91
+
92
+ Then in Python:
93
+ ```python
94
+ import orkit
95
+ ```
96
+
97
+ ### Clone and Install in Editable Mode
98
+ ```bash
99
+ # Optional: create and activate a virtual environment
100
+ python -m venv .venv
101
+ # Windows:
102
+ .venv\Scripts\activate
103
+ # Linux/macOS:
104
+ source .venv/bin/activate
105
+
106
+ # Install dependencies and ORKit in editable development mode
107
+ pip install -r requirements.txt
108
+ pip install -e .
109
+ ```
110
+
111
+ Verify installation:
112
+ ```bash
113
+ python -c "import orkit; print('ORKit imported successfully!')"
114
+ ```
115
+
116
+ ---
117
+
118
+ ## 6. Input & Output Formats
119
+
120
+ All ORKit optimization solvers return **plain Python dictionaries** containing standard keys:
121
+ - `"status"`: `"optimal"`, `"infeasible"`, or `"unbounded"` (or `"no_saddle_point"`).
122
+ - `"solution"`: Dictionary or list containing decision variable values or allocations.
123
+ - `"objective_value"`: Numeric optimal value ($Z$, cost, duration, game value).
124
+ - `"steps"`: List of human-readable strings explaining each calculation step.
125
+
126
+ ### Displaying Results
127
+
128
+ ORKit includes presentation helpers in `orkit.display` to render clean, aligned, viva-ready terminal reports. Use `display_result(result, show_steps=True)` to print the formatted report (or `format_result` to retrieve the formatted string):
129
+
130
+ ```python
131
+ from orkit import solve_graphical, display_result
132
+
133
+ c = [3, 5]
134
+ A = [[1, 0], [0, 2], [3, 2]]
135
+ b = [4, 12, 18]
136
+ signs = ["<=", "<=", "<="]
137
+
138
+ result = solve_graphical(c, A, b, signs, maximize=True)
139
+
140
+ # Display result with step-by-step calculations
141
+ display_result(result, show_steps=True)
142
+ ```
143
+
144
+ These helpers are strictly for output formatting; the underlying solver return dictionary remains untouched and directly accessible.
145
+
146
+ ### Quick Usage Examples
147
+
148
+ #### 1. Linear Programming (Graphical & Simplex)
149
+ ```python
150
+ from orkit import solve_graphical, solve_simplex, plot_feasible_region
151
+
152
+ c = [3, 5]
153
+ A = [[1, 0], [0, 2], [3, 2]]
154
+ b = [4, 12, 18]
155
+ signs = ["<=", "<=", "<="]
156
+
157
+ # Graphical solver (2 variables)
158
+ res_graph = solve_graphical(c, A, b, signs, maximize=True)
159
+ print(res_graph["solution"]) # {'x1': 2, 'x2': 6}
160
+ print(res_graph["objective_value"]) # 36
161
+
162
+ # Simplex solver
163
+ res_simp = solve_simplex(c, A, b, maximize=True)
164
+ print(res_simp["solution"]) # {'x1': 2, 'x2': 6}
165
+ print(res_simp["objective_value"]) # 36
166
+
167
+ # Plot feasible region
168
+ fig = plot_feasible_region(c, A, b, signs, maximize=True)
169
+ # fig.savefig("feasible_region.png")
170
+ ```
171
+
172
+ #### 2. Transportation Problem
173
+ ```python
174
+ from orkit import vogels_approximation, modi_method
175
+
176
+ cost_matrix = [
177
+ [19, 30, 50, 10],
178
+ [70, 30, 40, 60],
179
+ [40, 8, 70, 20]
180
+ ]
181
+ supply = [7, 9, 18]
182
+ demand = [5, 8, 7, 14]
183
+
184
+ # Initial solution via VAM
185
+ vam_res = vogels_approximation(cost_matrix, supply, demand)
186
+ print("VAM Cost:", vam_res["objective_value"]) # 779
187
+
188
+ # Optimal solution via MODI (u-v method)
189
+ modi_res = modi_method(cost_matrix, supply, demand, initial_method="vam")
190
+ print("Optimal Cost:", modi_res["objective_value"]) # 743
191
+ print("Allocations:", modi_res["allocation"])
192
+ # [[5, 0, 0, 2], [0, 2, 7, 0], [0, 6, 0, 12]]
193
+ ```
194
+
195
+ #### 3. Assignment Problem (Hungarian Method)
196
+ ```python
197
+ from orkit import hungarian_method
198
+
199
+ cost_matrix = [
200
+ [9, 2, 7, 8],
201
+ [6, 4, 3, 7],
202
+ [5, 8, 1, 8],
203
+ [7, 6, 9, 4]
204
+ ]
205
+ res = hungarian_method(cost_matrix)
206
+ print("Optimal Cost:", res["objective_value"]) # 13
207
+ print("Assignments:", res["assignments"]) # [(0, 1), (1, 0), (2, 2), (3, 3)]
208
+ ```
209
+
210
+ #### 4. Project Network Analysis (CPM & PERT)
211
+ ```python
212
+ from orkit import cpm, pert
213
+
214
+ # Activity dictionary format: name -> {"duration": num, "predecessors": list}
215
+ cpm_activities = {
216
+ "A": {"duration": 3, "predecessors": []},
217
+ "B": {"duration": 4, "predecessors": ["A"]},
218
+ "C": {"duration": 2, "predecessors": ["A"]},
219
+ "D": {"duration": 5, "predecessors": ["B", "C"]},
220
+ }
221
+ cpm_res = cpm(cpm_activities)
222
+ print("Duration:", cpm_res["project_duration"]) # 12
223
+ print("Critical Path:", cpm_res["critical_path"]) # ['A', 'B', 'D']
224
+ print("Slack:", cpm_res["slack"]) # {'A': 0, 'B': 0, 'C': 2, 'D': 0}
225
+
226
+ # PERT 3-point estimates: name -> {"a": opt, "m": likely, "b": pess, "predecessors": list}
227
+ pert_activities = {
228
+ "A": {"a": 1, "m": 3, "b": 5, "predecessors": []},
229
+ "B": {"a": 2, "m": 4, "b": 6, "predecessors": ["A"]},
230
+ "C": {"a": 1, "m": 2, "b": 3, "predecessors": ["A"]},
231
+ "D": {"a": 3, "m": 5, "b": 7, "predecessors": ["B", "C"]},
232
+ }
233
+ pert_res = pert(pert_activities)
234
+ print("Expected Duration:", pert_res["project_expected_duration"]) # 12
235
+ print("Critical Variance:", pert_res["project_variance"]) # 1.33333333
236
+ ```
237
+
238
+ #### 5. Game Theory
239
+ ```python
240
+ from orkit import solve_pure_strategy, solve_mixed_2x2
241
+
242
+ # Pure strategy saddle point game
243
+ saddle_payoff = [[3, 5], [2, 4]]
244
+ print(solve_pure_strategy(saddle_payoff))
245
+ # status: 'optimal', saddle_points: [(0, 0)], objective_value: 3
246
+
247
+ # Mixed strategy 2x2 game
248
+ mixed_payoff = [[2, 4], [3, 1]]
249
+ res = solve_mixed_2x2(mixed_payoff)
250
+ print("p:", res["p"]) # [0.5, 0.5]
251
+ print("q:", res["q"]) # [0.75, 0.25]
252
+ print("Value:", res["objective_value"]) # 2.5
253
+ ```
254
+
255
+ ---
256
+
257
+ ## 7. Running Demonstrations, Tests, and Notebooks
258
+
259
+ ### Run Sample Problems Script
260
+ ```bash
261
+ python examples/sample_problems.py
262
+ ```
263
+
264
+ ### Run Test Suite
265
+ ```bash
266
+ pytest
267
+ ```
268
+
269
+ ### Execute Notebooks
270
+ The five demonstration notebooks can be launched interactively via Jupyter:
271
+ ```bash
272
+ jupyter notebook
273
+ ```
274
+ Or executed headless one notebook per command with outputs saved in-place. The kernel must be installed once per machine with:
275
+ ```bash
276
+ python -m ipykernel install --user --name orkit-venv
277
+ ```
278
+ Then execute each notebook specifying the registered kernel:
279
+ ```bash
280
+ python -m jupyter nbconvert --to notebook --execute --inplace --ExecutePreprocessor.kernel_name=orkit-venv notebooks/01_lpp.ipynb
281
+ python -m jupyter nbconvert --to notebook --execute --inplace --ExecutePreprocessor.kernel_name=orkit-venv notebooks/02_transportation.ipynb
282
+ python -m jupyter nbconvert --to notebook --execute --inplace --ExecutePreprocessor.kernel_name=orkit-venv notebooks/03_assignment.ipynb
283
+ python -m jupyter nbconvert --to notebook --execute --inplace --ExecutePreprocessor.kernel_name=orkit-venv notebooks/04_cpm_pert.ipynb
284
+ python -m jupyter nbconvert --to notebook --execute --inplace --ExecutePreprocessor.kernel_name=orkit-venv notebooks/05_game_theory.ipynb
285
+ ```
286
+
287
+ ---
288
+
289
+ ## 8. Honest Limitations & Design Assumptions
290
+
291
+ In accordance with ORKit's educational purpose, scope is deliberately focused on foundational methods:
292
+ 1. **Linear Programming**:
293
+ - `solve_simplex` strictly supports canonical problems with $\le$ constraints and $b \ge 0$ (variables $\ge 0$). Big-M, Two-Phase simplex, and anti-cycling Bland's rule are not implemented.
294
+ - `solve_graphical` supports exactly 2 decision variables. Unboundedness is detected via an artificial bounding box ($10^6$).
295
+ - `plot_feasible_region` shades the feasible region using a numerical grid across the bounding view window.
296
+ 2. **Transportation**:
297
+ - `modi_method` supports cost minimization only. Degeneracy is resolved by selecting non-loop-forming cells in row-major order with zero allocation.
298
+ 3. **Assignment**:
299
+ - `hungarian_method` supports square and rectangular matrices (padded with zero-cost dummy rows or columns) and accepts negative costs by shifting the matrix via minimum reduction. The $O(n^3)$ dual potential implementation is omitted in favor of the explainable textbook line-covering method.
300
+ 4. **Project Network**:
301
+ - `cpm` returns one deterministic primary critical path (all critical activities with slack 0 are listed in `critical_activities`).
302
+ - `pert` calculates expected critical path duration and variance; normal distribution $Z$-lookup probabilities of completion are not computed. Network diagrams are not generated.
303
+ 5. **Game Theory**:
304
+ - Mixed strategy analytical formulas are implemented strictly for $2 \times 2$ zero-sum games without dominance reduction. LP-based solving for $m \times n$ mixed games is out of scope.
305
+ 6. **Display Helpers**:
306
+ - Formatters in `orkit.display` (`display_result`, `format_result`) are designed strictly for terminal presentation and student demonstration; they do not alter solver data structures.
307
+
308
+ ---
309
+
310
+ ## 9. Future Scope (Not Implemented)
311
+
312
+ The following advanced operations research techniques are **NOT implemented** in this undergraduate release and represent prospective future work:
313
+ - Integer Linear Programming (ILP) and Branch-and-Bound
314
+ - Sensitivity and Post-Optimality Analysis
315
+ - Job Sequencing and Johnson's Algorithm
316
+ - Inventory Control Models (EOQ, EPQ, safety stock)
317
+ - Queuing Theory ($M/M/1$, $M/M/c$)
318
+ - Monte Carlo Simulation
319
+ - $m \times n$ Game Theory via Linear Programming / Subgame Dominance
320
+ - Automated PERT/CPM Network Graph rendering