Simplex Method Calculator Code Guide
Simplex Method Calculator Code Guide
import numpy as np
• This lets the code convert decimals into nice fractions like 1/2.
class Color:
BLUE = '\033[94m'
CYAN = '\033[96m'
GREEN = '\033[92m'
YELLOW = '\033[93m'
RED = '\033[91m'
BOLD = '\033[1m'
END = '\033[0m'
• This class stores color codes for printing text in color. Symbols '\033[94m' are ANSI
escape codes, which tell the terminal like, turn this text into blue, and so on...
class SimplexSolver:
def __init__(self):
# Simplex tableau
[Link] = None
self.basic_vars = []
[Link] = 0
Variable What it is
tableau The matrix used by simplex
basic_vars The variables currently in the basis (like s1, s2, x2...)
iteration Counting simplex steps
def show_banner(self):
print(f"{[Link]}{[Link]}")
print(" " * 30 + "SIMPLEX METHOD CALCULATOR")
print(" " * 20 + "Solve Linear Programming Problems Step-by-Step\n")
print(f"{[Link]}{[Link]}")
print(" " * 32 + """Programmed by Group 5:
Achilles Pyrrhus A. Rosales
Justine Mae Delorino
Crysler Arcebuche
Paul Balena\n""")
print(" " * 37 + """Submitted to:
Sir Norcelito Galvan""")
print(f"{[Link]}\n")
// gingamit na nato an kulay nga Cyan using [Link] dikan gin bold nato para mas kita
[Link].
“ “ * 30 , ibig sabihin times 30 nga spaces para ma butnga itun nga string.
Implement:
while True:
choice = input(f"\n{[Link]}Your choice (1 or 2):
{[Link]}").strip()
if choice == '1':
self.is_maximize = True
print(f"{[Link]}Selected: MAXIMIZE{[Link]}")
break
elif choice == '2':
self.is_maximize = False
print(f"{[Link]}Selected: MINIMIZE{[Link]}")
break
else:
print(f"{[Link]} Please enter 1 or 2{[Link]}")
Output:
# === STEP 2: Get Problem Size ===
def get_problem_size(self):
self.show_section("STEP 2: Problem Dimensions")
Line-by-line explanation
• def get_problem_size(self):
o Method to collect how many variables and constraints the problem has.
• self.show_section("STEP 2: Problem Dimensions")
o Prints a labeled section header.
• while True: and try/except block for num_vars
o Repeatedly ask the number of variables until user enters a valid positive
integer.
o int(input(...)) converts the typed string to an integer.
o if self.num_vars > 0: ensures it's positive.
o break exits the loop on valid input.
o except: triggers when conversion fails (user typed non-number), printing an
error.
• The second while True: do the same for num_constraints.
• if self.num_vars == 2: self.var_names = ['x', 'y'] (and similar)
o Sets friendly variable names for the first few common sizes (x, y, z, w).
o For other sizes, [f'x{i + 1}' for i in range(self.num_vars)] creates
['x1', 'x2', ...].
• print(...)
o Confirms to the user what was entered: the number of variables and
constraints.
print(f"{[Link]}{obj_type} Z = {var_display}{[Link]}")
print(f"Enter coefficients c1, c2, ..., c{self.num_vars}")
while True:
try:
coeffs = input(f"\n{[Link]}Coefficients (space-separated):
{[Link]}").strip().split()
coeffs = [float(x) for x in coeffs]
if len(coeffs) == self.num_vars:
self.obj_coeffs = coeffs
break
print(f"{[Link]} Need exactly {self.num_vars}
coefficients{[Link]}")
except:
print(f"{[Link]} Please enter valid numbers{[Link]}")
for i in range(self.num_constraints):
print(f"\n{[Link]} Constraint {i + 1} {[Link]}")
# Get coefficients
while True:
try:
coeffs = input(f"Coefficients: ").strip().split()
coeffs = [float(x) for x in coeffs]
if len(coeffs) == self.num_vars:
break
print(f"{[Link]}✗ Need {self.num_vars}
coefficients{[Link]}")
except:
print(f"{[Link]}✗ Please enter valid
numbers{[Link]}")
# Get type
while True:
ctype = input("Type (1=≤, 2=≥, 3==): ").strip()
if ctype in ['1', '2', '3']:
self.constraint_types.append(int(ctype))
break
print(f"{[Link]}✗ Enter 1, 2, or 3{[Link]}")
# Get RHS
while True:
try:
rhs = float(input("Right-hand side: "))
break
except:
print(f"{[Link]}✗ Please enter a valid
number{[Link]}")
[Link](coeffs)
self.rhs_values.append(rhs)
Line-by-line explanation
• def get_constraints(self):
o Collects each constraint row: coefficients, relation (≤, ≥, =), and RHS number.
• self.show_section("STEP 4: Constraints")
o Prints header.
• The print lines describe to the user what to do.
• for i in range(self.num_constraints):
o Loop once per constraint (index i from 0 to num_constraints-1).
• print(f"\n{[Link]}━━━ Constraint {i + 1} ━━━{[Link]}")
o Print a mini-header for the current constraint.
• Coefficients input loop:
o input("Coefficients: ").strip().split() reads list of numbers.
o coeffs = [float(x) for x in coeffs] converts to floats.
o if len(coeffs) == self.num_vars: ensures the user entered exactly the
expected number of coefficients.
o On error, show message and repeat.
• Type selection loop:
o ctype = input("Type (1=≤, 2=≥, 3==): ").strip() reads user choice.
o If ctype is one of '1', '2', '3', append it as int(ctype) to
self.constraint_types.
o Otherwise error and repeat.
• RHS value loop:
o rhs = float(input("Right-hand side: ")) reads RHS as float inside
try/except to catch invalid inputs.
• [Link](coeffs)
o Store the coefficient list for this constraint.
• self.rhs_values.append(rhs)
o Store the RHS value.
• Build a nice printable LHS:
o lhs_parts = [f"{self.format_number(c)}{v}" for c, v in
zip(coeffs, self.var_names)]
▪ zip pairs every coefficient with its variable name.
o lhs = ' + '.join(lhs_parts).replace('+ -', '- ')
▪ Join and clean signs.
• symbols = ['≤', '≥', '=']
o Map the ctype numeric to a symbol.
• print(f"{[Link]}✓ {lhs} {symbols[int(ctype) - 1]}
{self.format_number(rhs)}{[Link]}")
o Print confirmation of the constraint entered.
print(f"{[Link]}{obj_type} Z = {obj_str}{[Link]}\n")
print(f"{[Link]}Subject to:{[Link]}")
print(f"\n{[Link]}{'─' * 90}{[Link]}")
choice = input(f"\n{[Link]}Is this correct? (y/n):
{[Link]}").strip().lower()
return choice == 'y'
Line-by-line explanation
• def show_problem_summary(self):
o Summarizes everything entered and asks user to confirm.
• self.show_section("PROBLEM SUMMARY")
o Show section header.
• obj_type = "Maximize" if self.is_maximize else "Minimize"
o Text label for objective type.
• obj_parts = [f"{self.format_number(c)}{v}" for c, v in
zip(self.obj_coeffs, self.var_names)]
o Build readable objective terms using stored coefficients and variable names.
• obj_str = ' + '.join(obj_parts).replace('+ -', '- ')
o Join and clean signs.
• print(f"{[Link]}{obj_type} Z = {obj_str}{[Link]}\n")
o Print the objective function.
• print(f"{[Link]}Subject to:{[Link]}")
o Print "Subject to" label.
• symbols = ['≤', '≥', '=']
o Mapping as before.
• for i in range(self.num_constraints): ... print(...)
o Loop over constraints, build lhs similarly and print each constraint with
correct symbol and RHS.
• var_str = ', '.join(self.var_names)
o Build a string of variable names separated by comma.
• print(f"\n {var_str} ≥ 0")
o Remind user that variables are non-negative (standard LP assumption).
• print(f"\n{[Link]}{'─' * 90}{[Link]}")
o Print separator.
• choice = input(f"\n{[Link]}Is this correct? (y/n):
{[Link]}").strip().lower()
o Ask for confirmation; .lower() allows Y or y.
• return choice == 'y'
o Returns True if user typed y, else False. Caller uses this to decide whether to
proceed or re-enter inputs.
# Objective function
obj_parts = [f"{self.format_number(c)}{v}" for c, v in
zip(self.obj_coeffs, self.var_names)]
obj_str = ' + '.join(obj_parts).replace('+ -', '- ')
print(f"{obj_str} {[Link]}→{[Link]} z - {obj_str} = 0")
if self.constraint_types[i] == 1: # ≤
slack_count += 1
print(f"\n{lhs} {[Link]}→{[Link]} {lhs} +
s{slack_count} = {rhs}")
elif self.constraint_types[i] == 2: # ≥
slack_count += 1
print(f"\n{lhs} {[Link]}→{[Link]} {lhs} -
s{slack_count} = {rhs}")
else: # =
print(f"\n{lhs} {[Link]}→{[Link]} {lhs} = {rhs}")
Line-by-line explanation
• def show_standard_form(self):
o Displays how the input LP is converted into standard form for simplex (adding
slack variables, etc.).
• self.show_section("STANDARD FORM CONVERSION")
o Header.
• print(f"{[Link]}Converting to standard form...{[Link]}\n")
o Informational message.
• Build objective string (obj_parts, obj_str) as before and print a conversion arrow:
o print(f"{obj_str} {[Link]}→{[Link]} z - {obj_str} = 0")
▪ Shows the objective in the equation form z - (objective) = 0,
which is a standard algebraic representation.
• slack_count = 0
o Counter to number slack variables (s1, s2, ...). Slack variables are added to
transform ≤ or ≥ constraints into equalities.
• for i in range(self.num_constraints):
o Loop over each constraint.
• Build lhs and rhs as before.
• if self.constraint_types[i] == 1: # ≤
o If constraint is ≤, we convert to equality by adding a slack variable: lhs + s
= rhs.
o slack_count += 1 increments slack variable index.
o Print the converted equality with + s{slack_count}.
• elif self.constraint_types[i] == 2: # ≥
o For ≥, the conventional (simple) conversion prints lhs - s = rhs (note: in a
full solver one might add surplus and artificial variables; this simple version
prints subtraction of a slack variable).
• else: # =
o Equality constraints are printed unchanged.
• non_neg = ', '.join(self.var_names)
o Build the string of original variables.
• slack_vars = ', '.join([f's{i + 1}' for i in range(slack_count)])
o Build list of slack variable names.
• print(f"\n{non_neg} ≥ 0 {[Link]}→{[Link]} {non_neg},
{slack_vars} ≥ 0")
o Print the final non-negativity statement: original variables and slack variables
are non-negative.
Line-by-line explanation
• def setup_tableau(self):
o Builds the initial simplex tableau from the constraints and objective.
• total_vars = self.num_vars + self.num_constraints
o Total columns (excluding RHS) we will represent: original variables + slack
variables (one slack per constraint in this simple setup).
• rows = self.num_constraints + 1
o Number of rows: one row per constraint plus one row for the objective (Z-
row).
• [Link] = [Link]((rows, total_vars + 1))
o Create a NumPy 2D array (matrix) of zeros with shape (rows, columns).
o total_vars + 1 because the extra column is the RHS (right-hand side)
values.
• for i in range(self.num_constraints):
o Loop through each constraint row to fill its coefficients.
• for j in range(self.num_vars): [Link][i][j] =
[Link][i][j]
o Copy the coefficients of the decision variables into the tableau row.
• [Link][i][self.num_vars + i] = 1 # Slack variable
o Place a 1 for the slack variable corresponding to constraint i.
o Slack variables are placed as identity columns so we have an initial basic
feasible solution.
• [Link][i][-1] = self.rhs_values[i] # RHS
o Set the last column in the row (index -1) to the RHS value.
• for j in range(self.num_vars): [Link][-1][j] = -
self.obj_coeffs[j]
o Fill the objective (Z) row's coefficients.
o The simplex tableau stores objective coefficients often as -c for maximizing Z
= c·x. Using -obj_coeffs lets the algorithm look for negative entries to
improve the objective.
• self.basic_vars = [f"s{i + 1}" for i in range(self.num_constraints)]
o Initialize the list of basic variables to the slack variables s1, s2, .... These
are currently the variables in the basis corresponding to identity columns we
added.
# Header
var_names = self.var_names + [f"s{i + 1}" for i in
range(self.num_constraints)]
print(f"{'Basic':^10}", end="")
for var in var_names:
print(f"{var:>14}", end="")
print(f"{'RHS':>14}", end="")
if show_pivot and pivot_col >= 0:
print(f"{'Ratio':>14}", end="")
print()
print("─" * 100)
# Constraint rows
for i in range(self.num_constraints):
marker = "─" if (show_pivot and i == pivot_row) else " "
print(f"{marker}{self.basic_vars[i]:^8}", end="")
for j in range(len(var_names)):
val = Fraction([Link][i][j]).limit_denominator(100)
val_str = str(val)
val = Fraction([Link][i][-1]).limit_denominator(100)
print(f"{str(val):>14}", end="")
print()
print("─" * 100)
# Z row
print(f" {'Z':^8}", end="")
for j in range(len(var_names)):
val = Fraction([Link][-1][j]).limit_denominator(100)
print(f"{str(val):>14}", end="")
val = Fraction([Link][-1][-1]).limit_denominator(100)
print(f"{str(val):>14}")
print("═" * 100)
Line-by-line explanation
• def print_tableau(self, title="", show_pivot=False, pivot_row=-1,
pivot_col=-1):
o A function to print the current tableau nicely formatted.
o title optional header. show_pivot and pivot indices used to highlight pivot
element and show ratio column.
• print(f"\n{[Link]}{title}{[Link]}")
o Print title in bold.
• print("═" * 100)
o Print a heavy horizontal separator.
• var_names = self.var_names + [f"s{i + 1}" for i in
range(self.num_constraints)]
o Build header row combining decision variable names and slack variable
names.
• print(f"{'Basic':^10}", end="")
o Print the "Basic" column header centered in 10 spaces; end="" means don’t
start a new line yet.
• for var in var_names: print(f"{var:>14}", end="")
o For each variable name, print it right-aligned in 14-character wide column.
This builds column headers.
• print(f"{'RHS':>14}", end="")
o Print RHS header right-aligned in the last column.
• if show_pivot and pivot_col >= 0: print(f"{'Ratio':>14}", end="")
o If showing pivot info, reserve an extra column for the ratio values used in the
minimum ratio test.
• print()
o Finish the header line (new line).
• print("─" * 100)
o Print a separator.
• for i in range(self.num_constraints):
o Loop over constraint rows to print each row.
• marker = "→ " if (show_pivot and i == pivot_row) else " "
o If we are highlighting the pivot row, prefix it with → marker.
• print(f"{marker}{self.basic_vars[i]:^8}", end="")
o Print the basic variable name for the row, centered in 8 spaces, with marker
prefix.
• for j in range(len(var_names)):
o Loop over each variable column for this row.
• val = Fraction([Link][i][j]).limit_denominator(100)
o Convert the floating point number to a Fraction with denominator limited to
100, so output is cleaner (e.g., 1/2 instead of 0.5 sometimes).
• val_str = str(val)
o Convert fraction to string.
• if show_pivot and i == pivot_row and j == pivot_col:
o If this is the pivot element and pivot display requested, highlight it.
• print(f"{[Link]}{[Link]}{val_str:>14}{[Link]}", end="")
o Print pivot element in red bold, right-aligned in 14 spaces.
• else: print(f"{val_str:>14}", end="")
o Otherwise just print normally.
• val = Fraction([Link][i][-1]).limit_denominator(100)
o Convert RHS value to fraction and print it in the RHS column.
• if show_pivot and pivot_col >= 0 and [Link][i][pivot_col] > 0:
o If we show pivot and the pivot column coefficient in this row is positive,
compute the ratio for minimum ratio test.
• ratio = [Link][i][-1] / [Link][i][pivot_col]
o Ratio = RHS / coefficient. Used to choose leaving variable.
• ratio_frac = Fraction(ratio).limit_denominator(100)
o Convert ratio to nice fraction.
• print(f"{str(ratio_frac):>14}", end="")
o Print ratio in the ratio column.
• print()
o End current constraint row line.
• print("─" * 100)
o Separator between constraint rows and Z-row.
• print(f" {'Z':^8}", end="")
o Print header for Z-row.
• for j in range(len(var_names)):
o Loop columns for Z-row values.
• val = Fraction([Link][-1][j]).limit_denominator(100)
o Get Z-row entry as fraction and print.
• val = Fraction([Link][-1][-1]).limit_denominator(100)
o Final print of Z-row RHS (value of objective stored in tableau).
• print("═" * 100)
o End printing with a heavy separator.
This function is purely formatting — it does not change any numbers; it only reads
[Link] and self.basic_vars to display them.
return [Link](obj_row)
for i in range(self.num_constraints):
coeff = [Link][i][pivot_col]
rhs = [Link][i][-1]
return pivot_row
• obj_row = [Link][-1][:-1]
o [Link][-1] selects last row (objective row).
o [:-1] slices to exclude the RHS column, leaving only coefficients of
variables.
• min_val = min(obj_row)
o Finds the minimum value in the objective row. For a max problem, negative
entries indicate variables that can improve objective.
• if min_val >= -1e-10: return -1
o If the smallest value is (nearly) non-negative, the solution is optimal: no more
negative coefficients to pivot on. Return -1 as sentinel for "no pivot column".
• return [Link](obj_row)
o Otherwise return the index (column) of the most negative coefficient — the
entering variable (pivot column).
print(f"\n{[Link]}PIVOT INFORMATION{[Link]}")
print("─" * 90)
Line-by-line explanation
• def show_pivot_info(self, pivot_row, pivot_col):
o Shows details about the pivot selected (for user understanding).
• pivot_val = [Link][pivot_row][pivot_col]
o Retrieve the pivot element value.
• Print heading and separator.
• col_name = self.var_names[pivot_col] if pivot_col < self.num_vars
else f"s{pivot_col - self.num_vars + 1}"
o Determine the variable name for the pivot column.
o If pivot_col is less than number of original variables, it's an original variable
(x, y, ...).
o Otherwise it's a slack variable; compute slack variable index with pivot_col
- self.num_vars.
• The next prints show:
o Pivot Column name,
o Pivot Row basic variable (the one leaving),
o Pivot Element value (formatted :.4g uses 4 significant digits),
o Entering Variable (same as column name),
o Leaving Variable (basic var from the pivot row).
Line-by-line explanation
• def do_pivot(self, pivot_row, pivot_col):
o Actually performs the Gaussian-elimination style pivot operation on the
tableau.
• pivot_val = [Link][pivot_row][pivot_col]
o Get pivot element (the number at intersection row/column).
• entering_var = ...
o Determine entering variable name (same logic as in show_pivot_info).
• self.basic_vars[pivot_row] = entering_var
o Replace the basic variable name for the pivot row with the entering variable.
This updates the bookkeeping of which variable is basic in that row.
• [Link][pivot_row] = [Link][pivot_row] / pivot_val
o Divide the entire pivot row by pivot value. This normalizes the pivot element
to 1 (so pivot column has a leading 1 in the pivot row).
• for i in range(len([Link])): if i != pivot_row:
o Iterate over all rows except pivot row to eliminate the pivot column entries.
• multiplier = [Link][i][pivot_col]
o The coefficient in the pivot column for row i. We'll remove this by
subtracting multiplier * pivot_row.
• [Link][i] = [Link][i] - multiplier *
[Link][pivot_row]
o Classic row operation: R_i = R_i - multiplier * R_pivot. This makes
the pivot column zero in row i, leaving identity-like column for the entering
var.
This function changes the tableau values and updates basic_vars. After this, the tableau
reflects one simplex pivot step.
[Link] = 0
self.print_tableau(f"TABLEAU {[Link]} (Initial)")
max_iterations = 50
print(f"\n{[Link]}{'═' * 90}")
print(f"ITERATION {[Link]}")
print(f"{'═' * 90}{[Link]}")
if pivot_col == -1:
print(f"\n{[Link]}{[Link]}✓ OPTIMAL SOLUTION
FOUND!{[Link]}")
print(f"{[Link]}All coefficients in Z-row are non-
negative.{[Link]}")
self.print_tableau(f"\nFINAL TABLEAU")
self.show_solution()
return True
if pivot_row == -1:
print(f"\n{[Link]}✗ UNBOUNDED SOLUTION{[Link]}")
print(f"{[Link]}No finite optimal solution
exists.{[Link]}")
return False
self.show_pivot_info(pivot_row, pivot_col)
# Perform pivot
self.do_pivot(pivot_row, pivot_col)
# Show result
input(f"\n{[Link]}Press Enter to see updated
tableau...{[Link]}")
self.print_tableau(f"\nTABLEAU {[Link]} (after pivot)")
Line-by-line explanation
• def solve(self):
o Runs the simplex algorithm loop until an optimal solution is found, problem is
declared unbounded, or iteration limit is reached.
• self.show_section("SOLUTION STEPS") and print(...)
o Print header and notify user.
• input(f"{[Link]}Press Enter to see initial
tableau...{[Link]}")
o Wait for user to press Enter before displaying initial tableau — the program is
interactive.
• [Link] = 0
o Initialize iteration counter.
• self.print_tableau(f"TABLEAU {[Link]} (Initial)")
o Print initial tableau built by setup_tableau().
• max_iterations = 50
o Safety limit to prevent infinite loops.
• while [Link] < max_iterations:
o Main loop that will perform pivot steps until something happens.
• [Link] += 1
o Increment the iteration count.
• input(f"\n{[Link]}Press Enter to continue to iteration
{[Link]}...{[Link]}")
o Pause so the user can step through each iteration manually.
• Print iteration header lines.
• pivot_col = self.find_pivot_column()
o Find entering variable column. If it returns -1, we have an optimal solution.
• if pivot_col == -1:
o If no negative coefficients (in max problem), it's optimal.
• Inside the if:
o Print success messages.
o self.print_tableau(f"\nFINAL TABLEAU")
▪ Show final tableau.
o self.show_solution()
▪ Print the actual solution values.
o return True
▪ Exit solve() indicating success.
• pivot_row = self.find_pivot_row(pivot_col)
o If pivot column exists, find the pivot row by minimum ratio test.
• if pivot_row == -1:
o If no pivot row found (no positive coefficients in pivot column), the LP is
unbounded.
• Inside unbounded if:
o Print error messages, return False.
• self.print_tableau(..., True, pivot_row, pivot_col)
o Print the tableau highlighting the pivot element and showing ratios.
• self.show_pivot_info(pivot_row, pivot_col)
o Print pivot details (entering/leaving variable, element).
• self.do_pivot(pivot_row, pivot_col)
o Perform the pivot operation; this updates the tableau and basic variables.
• input(f"\n{[Link]}Press Enter to see updated
tableau...{[Link]}")
o Pause before showing updated tableau.
• self.print_tableau(f"\nTABLEAU {[Link]} (after pivot)")
o Show the new tableau after the pivot step.
• If loop continues, it goes back to find next pivot column.
• If loop ends because [Link] >= max_iterations:
o Print "Maximum iterations reached" and return False.
This solve() function controls the algorithm flow and uses all helper functions we covered.
solution = {}
print(f"{[Link]}Decision Variables:{[Link]}")
for i in range(self.num_vars):
var = self.var_names[i]
value = 0
if var in self.basic_vars:
idx = self.basic_vars.index(var)
value = [Link][idx][-1]
solution[var] = value
value_str = self.format_number(value)
print(f" {var:>3} = {[Link]}{value_str:>12}{[Link]}")
optimal_z = [Link][-1][-1]
if not self.is_maximize:
optimal_z = -optimal_z
z_str = self.format_number(optimal_z)
print(f"\n{[Link]}Optimal Value:{[Link]}")
print(f" Z = {[Link]}{[Link]}{z_str:>12}{[Link]}")
# Verification
print(f"\n{[Link]}Verification:{[Link]}")
# Check objective
calc_z = sum(self.obj_coeffs[i] * solution[self.var_names[i]] for i in
range(self.num_vars))
calc_z_str = self.format_number(calc_z)
print(f" Calculated Z = {calc_z_str}")
print(f" {[Link]}✓ Objective verified{[Link]}" if abs(
calc_z - optimal_z) < 1e-6 else f" {[Link]}✗
Mismatch{[Link]}")
# Check constraints
print(f"\n Constraint Verification:")
symbols = ['≤', '≥', '=']
all_satisfied = True
for i in range(self.num_constraints):
lhs = sum([Link][i][j] * solution[self.var_names[j]] for
j in range(self.num_vars))
rhs = self.rhs_values[i]
symbol = symbols[self.constraint_types[i] - 1]
satisfied = False
if self.constraint_types[i] == 1 and lhs <= rhs + 1e-6:
satisfied = True
elif self.constraint_types[i] == 2 and lhs >= rhs - 1e-6:
satisfied = True
elif self.constraint_types[i] == 3 and abs(lhs - rhs) < 1e-6:
satisfied = True
lhs_str = self.format_number(lhs)
rhs_str = self.format_number(rhs)
status = f"{[Link]}✓{[Link]}" if satisfied else
f"{[Link]}✗{[Link]}"
print(f" {i + 1}. {lhs_str:>8} {symbol} {rhs_str:>8} {status}")
if not satisfied:
all_satisfied = False
if all_satisfied:
print(f"\n {[Link]}✓ All constraints satisfied{[Link]}")
Line-by-line explanation
• def show_solution(self):
o Prints the optimal solution and verifies it.
• self.show_section("OPTIMAL SOLUTION")
o Header.
• solution = {}
o Dictionary to store numeric value of each decision variable.
• print(f"{[Link]}Decision Variables:{[Link]}")
o Print label.
• for i in range(self.num_vars):
o For each original variable:
• var = self.var_names[i] and value = 0
o Get variable name and default value 0.
• if var in self.basic_vars: idx = self.basic_vars.index(var); value =
[Link][idx][-1]
o If the variable is currently a basic variable, find its row (idx) and take its RHS
value from the tableau as the value of that variable.
o Non-basic variables have value 0 in standard simplex.
• solution[var] = value
o Store it in the dictionary.
• value_str = self.format_number(value)
o Format for nice printing.
• print(f" {var:>3} = {[Link]}{value_str:>12}{[Link]}")
o Print variable and value.
• optimal_z = [Link][-1][-1]
o Get objective value from tableau. In the stored tableau, Z value is in the RHS
of the last row.
• if not self.is_maximize: optimal_z = -optimal_z
o If the user originally wanted minimization, sign might have been flipped
earlier. This corrects for display.
• z_str = self.format_number(optimal_z)
o Format Z for printing.
• Print optimal Z header and value.
• print(f"\n{[Link]}Verification:{[Link]}")
o Start verification section.
• calc_z = sum(self.obj_coeffs[i] * solution[self.var_names[i]] for i
in range(self.num_vars))
o Recalculate objective Z by computing c·x using obj_coeffs and solution
found.
• calc_z_str = self.format_number(calc_z)
o Format.
• print(f" Calculated Z = {calc_z_str}")
o Print the recalculated Z.
• print(...) if abs(calc_z - optimal_z) < 1e-6 else ...
o Compare the recalculated Z with the tableau Z within tolerance 1e-6.
o Print ✓ Objective verified if they are close, else print a mismatch
warning.
• print(f"\n Constraint Verification:")
o Start constraint verification.
• symbols = ['≤', '≥', '=']
o Symbol mapping.
• all_satisfied = True
o Flag assuming all constraints satisfied until proven otherwise.
• For each constraint:
o lhs = sum([Link][i][j] * solution[self.var_names[j]]
for j in range(self.num_vars))
▪ Compute left-hand side value by summing coefficient * variable value.
o rhs = self.rhs_values[i]
▪ Right-hand side stored earlier.
o symbol = symbols[self.constraint_types[i] - 1]
▪ Choose symbol for printing.
o Determine satisfied based on constraint type and numerical tolerance:
▪ For ≤, check lhs <= rhs + 1e-6
▪ For ≥, lhs >= rhs - 1e-6
▪ For =, abs(lhs - rhs) < 1e-6
o Format lhs_str, rhs_str and set status green tick or red cross.
o Print the verification result for each constraint.
o If any constraint not satisfied, set all_satisfied = False.
• if all_satisfied: print(f"\n {[Link]}✓ All constraints
satisfied{[Link]}")
o Print final message if every constraint passed verification.
# Confirm problem
if not self.show_problem_summary():
print(f"\n{[Link]}Restarting input...{[Link]}")
input("Press Enter to continue...")
continue
# Solve
self.setup_tableau()
[Link]()
Line-by-line explanation
• def run(self):
o Top-level method to run the interactive program repeatedly until user quits.
• while True:
o Infinite loop, broken when user chooses not to solve another problem.
• self.show_banner()
o Clear screen and show the banner header.
• self.get_objective_type() etc.
o Calls the data entry helpers in order: objective type, sizes, objective
coefficients, constraints.
• if not self.show_problem_summary():
o Shows the summary and asks for confirmation; if the user says no, we restart
input.
• print("Restarting input...") and input("Press Enter to continue...")
then continue
o Let user know we restart, pause, then go back to the top of the loop to re-enter
everything.
• self.show_standard_form()
o Show transformation to standard form (informational).
• input(f"...Press Enter to start solving...")
o Pause until user is ready.
• self.setup_tableau()
o Build initial tableau structure.
• [Link]()
o Run simplex algorithm until finish. solve() handles success/failure printing.
• After solve(), ask user:
o choice = input("Solve another problem? (y/n):
").strip().lower()
o If user does not type 'y', say goodbye and break to exit the while True loop
(ending the program).
traceback.print_exc()
Explanation
• if __name__ == "__main__": makes sure this block runs only when the file is
executed directly (not when imported as a module).
• solver = SimplexSolver() creates the solver object and runs it.
• try/except catches KeyboardInterrupt (Ctrl+C) to print a friendly message.
• Other exceptions are caught and printed with a stack trace
(traceback.print_exc()), useful for debugging.
Short summary
1. Program starts, creates SimplexSolver object.
2. run() displays banner and asks user for problem type, size, objective coefficients,
and constraints.
3. User confirms input summary.
4. Program shows standard-form conversion (informational).
5. setup_tableau() creates a numeric tableau representing constraints and objective.
6. solve() runs the simplex loop:
o find_pivot_column() picks entering variable (most negative coefficient in
Z-row).
o find_pivot_row() picks leaving variable using minimum ratio test.
o do_pivot() performs row operations to update tableau and basis.
o Repeat until optimal (pivot_col == -1) or unbounded (pivot_row == -1)
or iteration limit.
7. show_solution() prints solution values and verifies the objective and constraints.
8. run() optionally repeats for another problem.
"""
This is a Simplex Method Calculator programmed by Group 5 for compliance in
our project in Quantitative Methods
A simple tool for solving Linear Programming Problems
import numpy as np
from fractions import Fraction
# This class stores color codes for printing text in color. Symbols
'\033[94m' are ANSI escape codes,
# which tell the terminal like, turn this text into blue, and so on...
class Color:
BLUE = '\033[94m'
CYAN = '\033[96m'
GREEN = '\033[92m'
YELLOW = '\033[93m'
RED = '\033[91m'
BOLD = '\033[1m'
END = '\033[0m'
# Simplex tableau
[Link] = None
self.basic_vars = []
[Link] = 0
def show_banner(self):
print(f"{[Link]}{[Link]}")
print(" " * 30 + "SIMPLEX METHOD CALCULATOR")
print(" " * 20 + "Solve Linear Programming Problems Step-by-
Step\n")
print(f"{[Link]}{[Link]}")
print(" " * 32 + """Programmed by Group 5:
Achilles Pyrrhus A. Rosales
Justine Mae Delorino
Crysler Arcebuche
Paul Balena\n""")
print(" " * 37 + """Submitted to:
Sir Norcelito Galvan""")
print(f"{[Link]}\n")
while True:
choice = input(f"\n{[Link]}Your choice (1 or 2):
{[Link]}").strip()
if choice == '1':
self.is_maximize = True
print(f"{[Link]}Selected: MAXIMIZE{[Link]}")
break
elif choice == '2':
self.is_maximize = False
print(f"{[Link]}Selected: MINIMIZE{[Link]}")
break
else:
print(f"{[Link]} Please enter 1 or 2{[Link]}")
print(f"{[Link]}{obj_type} Z = {var_display}{[Link]}")
print(f"Enter coefficients c1, c2, ..., c{self.num_vars}")
while True:
try:
coeffs = input(f"\n{[Link]}Coefficients (space-
separated): {[Link]}").strip().split()
coeffs = [float(x) for x in coeffs]
if len(coeffs) == self.num_vars:
self.obj_coeffs = coeffs
break
print(f"{[Link]} Need exactly {self.num_vars}
coefficients{[Link]}")
except:
print(f"{[Link]} Please enter valid numbers{[Link]}")
for i in range(self.num_constraints):
print(f"\n{[Link]} Constraint {i + 1} {[Link]}")
# Get coefficients
while True:
try:
coeffs = input(f"Coefficients: ").strip().split()
coeffs = [float(x) for x in coeffs]
if len(coeffs) == self.num_vars:
break
print(f"{[Link]}✗ Need {self.num_vars}
coefficients{[Link]}")
except:
print(f"{[Link]}✗ Please enter valid
numbers{[Link]}")
# Get type
while True:
ctype = input("Type (1=≤, 2=≥, 3==): ").strip()
if ctype in ['1', '2', '3']:
self.constraint_types.append(int(ctype))
break
print(f"{[Link]}✗ Enter 1, 2, or 3{[Link]}")
# Get RHS
while True:
try:
rhs = float(input("Right-hand side: "))
break
except:
print(f"{[Link]}✗ Please enter a valid
number{[Link]}")
[Link](coeffs)
self.rhs_values.append(rhs)
print(f"{[Link]}{obj_type} Z = {obj_str}{[Link]}\n")
print(f"{[Link]}Subject to:{[Link]}")
print(f"\n{[Link]}{'─' * 90}{[Link]}")
choice = input(f"\n{[Link]}Is this correct? (y/n):
{[Link]}").strip().lower()
return choice == 'y'
# Objective function
obj_parts = [f"{self.format_number(c)}{v}" for c, v in
zip(self.obj_coeffs, self.var_names)]
obj_str = ' + '.join(obj_parts).replace('+ -', '- ')
print(f"{obj_str} {[Link]}→{[Link]} z - {obj_str} = 0")
if self.constraint_types[i] == 1: # ≤
slack_count += 1
print(f"\n{lhs} {[Link]}→{[Link]} {lhs} +
s{slack_count} = {rhs}")
elif self.constraint_types[i] == 2: # ≥
slack_count += 1
print(f"\n{lhs} {[Link]}→{[Link]} {lhs} -
s{slack_count} = {rhs}")
else: # =
print(f"\n{lhs} {[Link]}→{[Link]} {lhs} = {rhs}")
print(f"{'Basic':^10}", end="")
for var in var_names:
print(f"{var:>14}", end="")
print(f"{'RHS':>14}", end="")
if show_pivot and pivot_col >= 0:
print(f"{'Ratio':>14}", end="")
print()
print("─" * 100)
# Constraint rows
for i in range(self.num_constraints):
marker = "─" if (show_pivot and i == pivot_row) else " "
print(f"{marker}{self.basic_vars[i]:^8}", end="")
for j in range(len(var_names)):
val = Fraction([Link][i][j]).limit_denominator(100)
val_str = str(val)
print(f"{[Link]}{[Link]}{val_str:>14}{[Link]}", end="")
else:
print(f"{val_str:>14}", end="")
val = Fraction([Link][i][-1]).limit_denominator(100)
print(f"{str(val):>14}", end="")
print()
print("─" * 100)
# Z row
print(f" {'Z':^8}", end="")
for j in range(len(var_names)):
val = Fraction([Link][-1][j]).limit_denominator(100)
print(f"{str(val):>14}", end="")
val = Fraction([Link][-1][-1]).limit_denominator(100)
print(f"{str(val):>14}")
print("═" * 100)
return [Link](obj_row)
for i in range(self.num_constraints):
coeff = [Link][i][pivot_col]
rhs = [Link][i][-1]
return pivot_row
print(f"\n{[Link]}PIVOT INFORMATION{[Link]}")
print("─" * 90)
[Link] = 0
self.print_tableau(f"TABLEAU {[Link]} (Initial)")
max_iterations = 50
print(f"\n{[Link]}{'═' * 90}")
print(f"ITERATION {[Link]}")
print(f"{'═' * 90}{[Link]}")
if pivot_col == -1:
print(f"\n{[Link]}{[Link]}✓ OPTIMAL SOLUTION
FOUND!{[Link]}")
print(f"{[Link]}All coefficients in Z-row are non-
negative.{[Link]}")
self.print_tableau(f"\nFINAL TABLEAU")
self.show_solution()
return True
if pivot_row == -1:
print(f"\n{[Link]}✗ UNBOUNDED SOLUTION{[Link]}")
print(f"{[Link]}No finite optimal solution
exists.{[Link]}")
return False
# Perform pivot
self.do_pivot(pivot_row, pivot_col)
# Show result
input(f"\n{[Link]}Press Enter to see updated
tableau...{[Link]}")
self.print_tableau(f"\nTABLEAU {[Link]} (after pivot)")
solution = {}
print(f"{[Link]}Decision Variables:{[Link]}")
for i in range(self.num_vars):
var = self.var_names[i]
value = 0
if var in self.basic_vars:
idx = self.basic_vars.index(var)
value = [Link][idx][-1]
solution[var] = value
value_str = self.format_number(value)
print(f" {var:>3} = {[Link]}{value_str:>12}{[Link]}")
optimal_z = [Link][-1][-1]
if not self.is_maximize:
optimal_z = -optimal_z
z_str = self.format_number(optimal_z)
print(f"\n{[Link]}Optimal Value:{[Link]}")
print(f" Z = {[Link]}{[Link]}{z_str:>12}{[Link]}")
# Verification
print(f"\n{[Link]}Verification:{[Link]}")
# Check objective
calc_z = sum(self.obj_coeffs[i] * solution[self.var_names[i]] for i
in range(self.num_vars))
calc_z_str = self.format_number(calc_z)
print(f" Calculated Z = {calc_z_str}")
print(f" {[Link]}✓ Objective verified{[Link]}" if abs(
calc_z - optimal_z) < 1e-6 else f" {[Link]}✗
Mismatch{[Link]}")
# Check constraints
print(f"\n Constraint Verification:")
symbols = ['≤', '≥', '=']
all_satisfied = True
for i in range(self.num_constraints):
lhs = sum([Link][i][j] * solution[self.var_names[j]]
for j in range(self.num_vars))
rhs = self.rhs_values[i]
symbol = symbols[self.constraint_types[i] - 1]
satisfied = False
if self.constraint_types[i] == 1 and lhs <= rhs + 1e-6:
satisfied = True
elif self.constraint_types[i] == 2 and lhs >= rhs - 1e-6:
satisfied = True
elif self.constraint_types[i] == 3 and abs(lhs - rhs) < 1e-6:
satisfied = True
lhs_str = self.format_number(lhs)
rhs_str = self.format_number(rhs)
status = f"{[Link]}✓{[Link]}" if satisfied else
f"{[Link]}✗{[Link]}"
print(f" {i + 1}. {lhs_str:>8} {symbol} {rhs_str:>8}
{status}")
if not satisfied:
all_satisfied = False
if all_satisfied:
print(f"\n {[Link]}✓ All constraints
satisfied{[Link]}")
# Confirm problem
if not self.show_problem_summary():
print(f"\n{[Link]}Restarting input...{[Link]}")
input("Press Enter to continue...")
continue
# Solve
self.setup_tableau()
[Link]()
traceback.print_exc()