Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
simplex_example.C
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
148#include <iostream>
149#include <iomanip>
150#include <string>
151#include <vector>
152#include <Simplex.H>
153#include <tclap/CmdLine.h>
154
155using namespace std;
156using namespace Aleph;
157
162{
163 switch (state)
164 {
165 case Simplex<double>::Not_Solved: return "Not Solved";
166 case Simplex<double>::Solving: return "Solving";
167 case Simplex<double>::Unbounded: return "Unbounded";
168 case Simplex<double>::Solved: return "Solved";
169 case Simplex<double>::Unfeasible: return "Unfeasible";
170 default: return "Unknown";
171 }
172}
173
187{
188 cout << "\n" << string(60, '=') << endl;
189 cout << "Example 1: Production Planning Problem" << endl;
190 cout << string(60, '=') << endl;
191
192 cout << "\nProblem:" << endl;
193 cout << " Factory produces two products (A and B)" << endl;
194 cout << " Product A: $40 profit, 1 hr labor, 2 hrs machine" << endl;
195 cout << " Product B: $30 profit, 1 hr labor, 1 hr machine" << endl;
196 cout << " Available: 40 labor hours, 60 machine hours" << endl;
197
198 cout << "\nMathematical formulation:" << endl;
199 cout << " Maximize: Z = 40*xA + 30*xB" << endl;
200 cout << " Subject to: xA + xB <= 40 (labor)" << endl;
201 cout << " 2*xA + xB <= 60 (machine)" << endl;
202 cout << " xA, xB >= 0" << endl;
203
204 // Create solver with 2 decision variables
206
207 // Set objective function: maximize 40*xA + 30*xB
208 solver.put_objetive_function_coef(0, 40.0); // xA coefficient
209 solver.put_objetive_function_coef(1, 30.0); // xB coefficient
210
211 // Add constraints: {coef_xA, coef_xB, RHS}
212 double labor[] = {1.0, 1.0, 40.0}; // xA + xB <= 40
213 double machine[] = {2.0, 1.0, 60.0}; // 2*xA + xB <= 60
214
215 solver.put_restriction(labor);
216 solver.put_restriction(machine);
217
218 // Solve
219 solver.prepare_linear_program();
220 auto state = solver.solve();
221
222 cout << "\n--- Solution ---" << endl;
223 cout << "Status: " << state_to_string(state) << endl;
224
225 if (state == Simplex<double>::Solved)
226 {
227 solver.load_solution();
228
229 double xA = solver.get_solution(0);
230 double xB = solver.get_solution(1);
231 double profit = solver.objetive_value();
232
233 cout << fixed << setprecision(2);
234 cout << " Product A (xA): " << xA << " units" << endl;
235 cout << " Product B (xB): " << xB << " units" << endl;
236 cout << " Maximum profit: $" << profit << endl;
237
238 // Verify constraints
239 cout << "\n--- Constraint Verification ---" << endl;
240 cout << " Labor used: " << (xA + xB) << " / 40 hours" << endl;
241 cout << " Machine used: " << (2*xA + xB) << " / 60 hours" << endl;
242
243 if (solver.verify_solution())
244 cout << " All constraints satisfied: YES" << endl;
245 }
246}
247
268{
269 cout << "\n" << string(60, '=') << endl;
270 cout << "Example 2: Diet Problem (Minimization)" << endl;
271 cout << string(60, '=') << endl;
272
273 cout << "\nProblem:" << endl;
274 cout << " Food 1: $2/unit, 3g protein, 1g fat" << endl;
275 cout << " Food 2: $4/unit, 4g protein, 3g fat" << endl;
276 cout << " Requirements: >= 12g protein, >= 6g fat" << endl;
277
278 cout << "\nOriginal formulation:" << endl;
279 cout << " Minimize: C = 2*x1 + 4*x2" << endl;
280 cout << " Subject to: 3*x1 + 4*x2 >= 12" << endl;
281 cout << " x1 + 3*x2 >= 6" << endl;
282
283 cout << "\nConverted to standard form:" << endl;
284 cout << " Maximize: -C = -2*x1 - 4*x2" << endl;
285 cout << " Constraints multiplied by -1 for <= form" << endl;
286
288
289 // Objective: maximize -2*x1 - 4*x2 (to minimize 2*x1 + 4*x2)
290 solver.put_objetive_function_coef(0, -2.0);
291 solver.put_objetive_function_coef(1, -4.0);
292
293 // Constraints (converted from >= to <=)
294 double protein[] = {-3.0, -4.0, -12.0}; // -3*x1 - 4*x2 <= -12
295 double fat[] = {-1.0, -3.0, -6.0}; // -x1 - 3*x2 <= -6
296
297 solver.put_restriction(protein);
298 solver.put_restriction(fat);
299
300 solver.prepare_linear_program();
301 auto state = solver.solve();
302
303 cout << "\n--- Solution ---" << endl;
304 cout << "Status: " << state_to_string(state) << endl;
305
306 if (state == Simplex<double>::Solved)
307 {
308 solver.load_solution();
309
310 double x1 = solver.get_solution(0);
311 double x2 = solver.get_solution(1);
312 double cost = -solver.objetive_value(); // Negate to get original min
313
314 cout << fixed << setprecision(2);
315 cout << " Food 1 (x1): " << x1 << " units" << endl;
316 cout << " Food 2 (x2): " << x2 << " units" << endl;
317 cout << " Minimum cost: $" << cost << endl;
318
319 cout << "\n--- Nutritional Check ---" << endl;
320 cout << " Protein: " << (3*x1 + 4*x2) << "g (need >= 12g)" << endl;
321 cout << " Fat: " << (x1 + 3*x2) << "g (need >= 6g)" << endl;
322 }
323}
324
335{
336 cout << "\n" << string(60, '=') << endl;
337 cout << "Example 3: Resource Allocation" << endl;
338 cout << string(60, '=') << endl;
339
340 cout << "\nProblem:" << endl;
341 cout << " Resource X: max 2 units, yields 5/unit" << endl;
342 cout << " Resource Y: max 3 units, yields 4/unit" << endl;
343 cout << " Resource Z: max 4 units, yields 3/unit" << endl;
344 cout << " Total capacity: max 6 units" << endl;
345
346 cout << "\nFormulation:" << endl;
347 cout << " Maximize: Z = 5*x + 4*y + 3*z" << endl;
348 cout << " Subject to: x <= 2" << endl;
349 cout << " y <= 3" << endl;
350 cout << " z <= 4" << endl;
351 cout << " x + y + z <= 6" << endl;
352
354
355 // Objective: maximize 5x + 4y + 3z
356 solver.put_objetive_function_coef(0, 5.0); // x
357 solver.put_objetive_function_coef(1, 4.0); // y
358 solver.put_objetive_function_coef(2, 3.0); // z
359
360 // Constraints
361 double limit_x[] = {1.0, 0.0, 0.0, 2.0}; // x <= 2
362 double limit_y[] = {0.0, 1.0, 0.0, 3.0}; // y <= 3
363 double limit_z[] = {0.0, 0.0, 1.0, 4.0}; // z <= 4
364 double total[] = {1.0, 1.0, 1.0, 6.0}; // x + y + z <= 6
365
366 solver.put_restriction(limit_x);
367 solver.put_restriction(limit_y);
368 solver.put_restriction(limit_z);
369 solver.put_restriction(total);
370
371 solver.prepare_linear_program();
372 auto state = solver.solve();
373
374 cout << "\n--- Solution ---" << endl;
375 cout << "Status: " << state_to_string(state) << endl;
376
377 if (state == Simplex<double>::Solved)
378 {
379 solver.load_solution();
380
381 double x = solver.get_solution(0);
382 double y = solver.get_solution(1);
383 double z = solver.get_solution(2);
384 double yield = solver.objetive_value();
385
386 cout << fixed << setprecision(2);
387 cout << " Resource X: " << x << " units" << endl;
388 cout << " Resource Y: " << y << " units" << endl;
389 cout << " Resource Z: " << z << " units" << endl;
390 cout << " Total allocated: " << (x + y + z) << " / 6 units" << endl;
391 cout << " Maximum yield: " << yield << endl;
392
393 cout << "\n--- Analysis ---" << endl;
394 cout << "Notice how the algorithm prioritizes higher-yield resources" << endl;
395 cout << "while respecting all constraints." << endl;
396 }
397}
398
403{
404 cout << "\n" << string(60, '=') << endl;
405 cout << "Special Cases: Unbounded and Infeasible" << endl;
406 cout << string(60, '=') << endl;
407
408 // Example of potentially unbounded (if no upper bound)
409 cout << "\n--- Case 1: Well-defined problem ---" << endl;
410 cout << "Maximize: Z = x + y" << endl;
411 cout << "Subject to: x + y <= 10" << endl;
412
413 {
415 solver.put_objetive_function_coef(0, 1.0);
416 solver.put_objetive_function_coef(1, 1.0);
417
418 double limit[] = {1.0, 1.0, 10.0};
419 solver.put_restriction(limit);
420
421 solver.prepare_linear_program();
422 auto state = solver.solve();
423
424 cout << "Status: " << state_to_string(state) << endl;
425 if (state == Simplex<double>::Solved)
426 {
427 solver.load_solution();
428 cout << "Optimal value: " << solver.objetive_value() << endl;
429 }
430 }
431
432 // Example with conflicting constraints
433 cout << "\n--- Case 2: Conflicting constraints ---" << endl;
434 cout << "Maximize: Z = x + y" << endl;
435 cout << "Subject to: x + y <= 5" << endl;
436 cout << " x + y >= 10 (converted to -x - y <= -10)" << endl;
437
438 {
440 solver.put_objetive_function_coef(0, 1.0);
441 solver.put_objetive_function_coef(1, 1.0);
442
443 double limit1[] = {1.0, 1.0, 5.0}; // x + y <= 5
444 double limit2[] = {-1.0, -1.0, -10.0}; // x + y >= 10
445
446 solver.put_restriction(limit1);
447 solver.put_restriction(limit2);
448
449 solver.prepare_linear_program();
450 auto state = solver.solve();
451
452 cout << "Status: " << state_to_string(state) << endl;
453 cout << "(x + y can't be both <= 5 and >= 10 simultaneously)" << endl;
454 }
455}
456
461{
462 cout << "\n" << string(60, '=') << endl;
463 cout << "Understanding the Simplex Algorithm" << endl;
464 cout << string(60, '=') << endl;
465
466 cout << "\n--- The Simplex Method Steps ---" << endl;
467 cout << "1. Convert to standard form (slack variables)" << endl;
468 cout << "2. Build initial simplex tableau" << endl;
469 cout << "3. Find pivot column (most negative in objective row)" << endl;
470 cout << "4. Find pivot row (minimum ratio test)" << endl;
471 cout << "5. Pivot to improve solution" << endl;
472 cout << "6. Repeat until optimal (no negative in objective row)" << endl;
473
474 cout << "\n--- Geometric Interpretation ---" << endl;
475 cout << "The constraints define a convex polytope (feasible region)." << endl;
476 cout << "Simplex moves along edges of this polytope," << endl;
477 cout << "visiting vertices until it finds the optimum." << endl;
478 cout << "Each pivot operation moves to an adjacent vertex" << endl;
479 cout << "with a better (or equal) objective value." << endl;
480
481 cout << "\n--- Simple Example Visualization ---" << endl;
482 cout << "Maximize: Z = x + y" << endl;
483 cout << "Subject to: x <= 3, y <= 2, x + y <= 4" << endl;
484
486 solver.put_objetive_function_coef(0, 1.0);
487 solver.put_objetive_function_coef(1, 1.0);
488
489 double c1[] = {1.0, 0.0, 3.0}; // x <= 3
490 double c2[] = {0.0, 1.0, 2.0}; // y <= 2
491 double c3[] = {1.0, 1.0, 4.0}; // x + y <= 4
492
493 solver.put_restriction(c1);
494 solver.put_restriction(c2);
495 solver.put_restriction(c3);
496
497 solver.prepare_linear_program();
498 auto state = solver.solve();
499
500 if (state == Simplex<double>::Solved)
501 {
502 solver.load_solution();
503
504 cout << "\nFeasible region vertices:" << endl;
505 cout << " (0, 0): Z = 0" << endl;
506 cout << " (3, 0): Z = 3" << endl;
507 cout << " (3, 1): Z = 4 <-- binding x<=3 and x+y<=4" << endl;
508 cout << " (2, 2): Z = 4 <-- binding y<=2 and x+y<=4" << endl;
509 cout << " (0, 2): Z = 2" << endl;
510
511 cout << fixed << setprecision(2);
512 cout << "\nSimplex found: (" << solver.get_solution(0)
513 << ", " << solver.get_solution(1) << ")" << endl;
514 cout << "Optimal value: Z = " << solver.objetive_value() << endl;
515 }
516}
517
518int main(int argc, char* argv[])
519{
520 try
521 {
522 TCLAP::CmdLine cmd("Simplex Linear Programming Example", ' ', "1.0");
523
524 TCLAP::SwitchArg prodArg("p", "production",
525 "Show production planning example", false);
526 TCLAP::SwitchArg dietArg("d", "diet",
527 "Show diet problem example", false);
528 TCLAP::SwitchArg resArg("r", "resources",
529 "Show resource allocation example", false);
530 TCLAP::SwitchArg specArg("s", "special",
531 "Show special cases (unbounded, infeasible)", false);
532 TCLAP::SwitchArg algoArg("g", "algorithm",
533 "Show algorithm explanation", false);
534 TCLAP::SwitchArg allArg("a", "all",
535 "Run all demos", false);
536
537 cmd.add(prodArg);
538 cmd.add(dietArg);
539 cmd.add(resArg);
540 cmd.add(specArg);
541 cmd.add(algoArg);
542 cmd.add(allArg);
543
544 cmd.parse(argc, argv);
545
546 bool runProd = prodArg.getValue();
547 bool runDiet = dietArg.getValue();
548 bool runRes = resArg.getValue();
549 bool runSpec = specArg.getValue();
550 bool runAlgo = algoArg.getValue();
551 bool runAll = allArg.getValue();
552
555 runAll = true;
556
557 cout << "=== Simplex Algorithm: Linear Programming ===" << endl;
558 cout << "Find optimal solutions subject to linear constraints" << endl;
559
560 if (runAll or runProd)
562
563 if (runAll or runDiet)
565
566 if (runAll or runRes)
568
569 if (runAll or runSpec)
571
572 if (runAll or runAlgo)
574
575 cout << "\n=== Summary ===" << endl;
576 cout << "Simplex is the workhorse of linear programming." << endl;
577 cout << "Standard form: Maximize c'x subject to Ax <= b, x >= 0" << endl;
578 cout << "Convert: Min -> Max (negate), >= -> <= (negate)" << endl;
579 cout << "Applications: Production, logistics, finance, scheduling" << endl;
580
581 return 0;
582 }
583 catch (TCLAP::ArgException& e)
584 {
585 cerr << "Error: " << e.error() << " for arg " << e.argId() << endl;
586 return 1;
587 }
588}
589
Simplex algorithm for linear programming.
int main()
Linear program solver using the Simplex method.
Definition Simplex.H:227
State
Solution states for the linear program.
Definition Simplex.H:237
static mpfr_t y
Definition mpfr_mul_d.c:3
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
void demo_special_cases()
Demonstrate unbounded and infeasible cases.
string state_to_string(Simplex< double >::State state)
Helper to print solution state.
void demo_diet_problem()
Diet Problem (classic LP problem)
void demo_resource_allocation()
Transportation Problem (simplified)
void demo_production_planning()
Classic example: Production Planning.
void demo_algorithm_steps()
Demonstrate the algorithm steps.