0% found this document useful (0 votes)
5 views36 pages

Simplex Method Calculator Code Guide

The document provides a detailed explanation of a Simplex Method Calculator implemented in Python, utilizing libraries like NumPy and fractions for efficient calculations and formatting. It outlines the structure of the code, including classes for color coding and the Simplex solver, as well as methods for gathering user input on optimization type, problem size, objective function, and constraints. The document also includes step-by-step explanations of the code logic and user interaction for solving linear programming problems.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views36 pages

Simplex Method Calculator Code Guide

The document provides a detailed explanation of a Simplex Method Calculator implemented in Python, utilizing libraries like NumPy and fractions for efficient calculations and formatting. It outlines the structure of the code, including classes for color coding and the Simplex solver, as well as methods for gathering user input on optimization type, problem size, objective function, and constraints. The document also includes step-by-step explanations of the code logic and user interaction for solving linear programming problems.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Step-by-step code explanation

(Simplex Method Calculator)

import numpy as np

• Loads the NumPy library.

• NumPy helps with fast tables, arrays, and math.

• The simplex tableau is stored as a NumPy array.

from fractions import Fraction

• This lets the code convert decimals into nice fractions like 1/2.

• It makes the printed tableau look clean.

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...

For example, print([Link] + "Hello!" + [Link])

// Prints a green “Hello!” and then resets color.

class SimplexSolver:
def __init__(self):

• This defines a class (a machine that stores data + functions).

• __init__() is the constructor → it runs every time you create a solver.


self.num_vars = 0
self.num_constraints = 0
self.is_maximize = True
self.obj_coeffs = []
[Link] = []
self.rhs_values = []
self.constraint_types = []
self.var_names = []
Variable Meaning
num_vars How many variables (x, y, z…)
num_constraints Number of constraints
is_maximize Max or Min problem
obj_coeffs Coefficients of objective function
constraints Coefficients of left-hand sides
rhs_values Right-hand side numbers (b values)
constraint_types ≤ , ≥ , or =
var_names Names of variables (x, y, z...)

# 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.

def show_section(self, title):


print(f"\n{[Link]}{[Link]}{'─' * 90}")
print(f" {title}")
print(f"{'─' * 90}{[Link]}\n")
Output:

Implement:

self.show_section("STEP 1: Objective Type")

def format_number(self, num):


"""Show whole numbers without decimals"""
if abs(num - round(num)) < 1e-10:
return str(int(round(num)))
return str(num)
// Purpose: Make numbers look nice. If a number is very close to a whole number (like
4.000000001), it rounds it and shows it as a simple integer (4) instead of a messy decimal, which is
easier for the user to read.

# === STEP 1: Get Objective Type ===


def get_objective_type(self):
self.show_section("STEP 1: Objective Type")
print(f"{[Link]}Select optimization type:{[Link]}")
print(f" {[Link]}[1]{[Link]} Maximize")
print(f" {[Link]}[2]{[Link]} Minimize")

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")

# Get number of variables


while True:
try:
self.num_vars = int(input(f"{[Link]}Number of decision
variables: {[Link]}"))
if self.num_vars > 0:
break
print(f"{[Link]}Must be positive{[Link]}")
except:
print(f"{[Link]}Please enter a valid number{[Link]}")

# Get number of constraints


while True:
try:
self.num_constraints = int(input(f"{[Link]}Number of
constraints: {[Link]}"))
if self.num_constraints > 0:
break
print(f"{[Link]} Must be positive{[Link]}")
except:
print(f"{[Link]} Please enter a valid number{[Link]}")

# Set variable names (x, y for 2 vars; x, y, z for 3; etc.)


if self.num_vars == 2:
self.var_names = ['x', 'y']
elif self.num_vars == 3:
self.var_names = ['x', 'y', 'z']
elif self.num_vars == 4:
self.var_names = ['x', 'y', 'z', 'w']
else:
self.var_names = [f'x{i + 1}' for i in range(self.num_vars)]

print(f"\n{[Link]} Problem: {self.num_vars} variables,


{self.num_constraints} constraints{[Link]}")

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.

# === STEP 3: Get Objective Function ===


def get_objective_function(self):
self.show_section("STEP 3: Objective Function")

obj_type = "Maximize" if self.is_maximize else "Minimize"


var_display = ' + '.join([f"c{i + 1}·{v}" for i, v in
enumerate(self.var_names)])

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]}")

# Show what was entered


parts = [f"{self.format_number(c)}{v}" for c, v in zip(coeffs,
self.var_names)]
obj_str = ' + '.join(parts).replace('+ -', '- ')
print(f"\n{[Link]} Objective: Z = {obj_str}{[Link]}")
Line-by-line explanation
• def get_objective_function(self):
o Method to capture coefficients for the objective function.
• self.show_section("STEP 3: Objective Function")
o Print section header.
• obj_type = "Maximize" if self.is_maximize else "Minimize"
o Sets obj_type text depending on what user chose earlier.
• var_display = ' + '.join([f"c{i + 1}·{v}" for i, v in
enumerate(self.var_names)])
o Builds a readable string showing c1·x, c2·y, etc., for instructions.
o enumerate(self.var_names) gives (index, name) pairs.
• print(f"{[Link]}{obj_type} Z = {var_display}{[Link]}")
o Print the objective template (e.g., "Maximize Z = c1·x + c2·y").
• print(f"Enter coefficients c1, c2, ..., c{self.num_vars}")
o Instruction line.
• while True: loop to read coefficients:
o input(...).strip().split() reads a line, trims whitespace, splits by
spaces. Result: list of strings.
o coeffs = [float(x) for x in coeffs] converts each string to a float
number. If user typed something non-numeric, this raises and goes to except.
o if len(coeffs) == self.num_vars: checks we have the correct number of
coefficients.
▪ If correct, assign to self.obj_coeffs and break out of loop.
o If wrong number, print error and loop again.
o except: catches conversion errors and asks again.
• parts = [f"{self.format_number(c)}{v}" for c, v in zip(coeffs,
self.var_names)]
o Builds human-friendly pieces like 3x, -1y (using format_number to avoid
.0).
• obj_str = ' + '.join(parts).replace('+ -', '- ')
o Joins parts with +, then converts + - into - for nicer math notation.
• print(f"\n{[Link]} Objective: Z = {obj_str}{[Link]}")
o Shows the final objective function that the user input.
• # === STEP 4: Get Constraints ===
def get_constraints(self):
self.show_section("STEP 4: Constraints")

print(f"{[Link]}For each constraint:{[Link]}")


print(" • Enter coefficients (left side)")
print(" • Choose type: 1 (≤), 2 (≥), 3 (=)")
print(" • Enter right-hand side value")

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)

# Show what was entered


lhs_parts = [f"{self.format_number(c)}{v}" for c, v in
zip(coeffs, self.var_names)]
lhs = ' + '.join(lhs_parts).replace('+ -', '- ')
symbols = ['≤', '≥', '=']
print(f"{[Link]}✓ {lhs} {symbols[int(ctype) - 1]}
{self.format_number(rhs)}{[Link]}")

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.

# === Show Problem Summary ===


def show_problem_summary(self):
self.show_section("PROBLEM SUMMARY")

obj_type = "Maximize" if self.is_maximize else "Minimize"


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"{[Link]}{obj_type} Z = {obj_str}{[Link]}\n")
print(f"{[Link]}Subject to:{[Link]}")

symbols = ['≤', '≥', '=']


for i in range(self.num_constraints):
lhs_parts = [f"{self.format_number(c)}{v}" for c, v in
zip([Link][i], self.var_names)]
lhs = ' + '.join(lhs_parts).replace('+ -', '- ')
symbol = symbols[self.constraint_types[i] - 1]
rhs = self.format_number(self.rhs_values[i])
print(f" {lhs} {symbol} {rhs}")

var_str = ', '.join(self.var_names)


print(f"\n {var_str} ≥ 0")

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.

# === Show Standard Form ===


def show_standard_form(self):
self.show_section("STANDARD FORM CONVERSION")

print(f"{[Link]}Converting to standard form...{[Link]}\n")

# 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")

# Constraints with slack variables


slack_count = 0
for i in range(self.num_constraints):
lhs_parts = [f"{self.format_number(c)}{v}" for c, v in
zip([Link][i], self.var_names)]
lhs = ' + '.join(lhs_parts).replace('+ -', '- ')
rhs = self.format_number(self.rhs_values[i])

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}")

non_neg = ', '.join(self.var_names)


slack_vars = ', '.join([f's{i + 1}' for i in range(slack_count)])
print(f"\n{non_neg} ≥ 0 {[Link]}→{[Link]} {non_neg},
{slack_vars} ≥ 0")

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.

# === Setup Initial Tableau ===


def setup_tableau(self):
total_vars = self.num_vars + self.num_constraints
rows = self.num_constraints + 1

[Link] = [Link]((rows, total_vars + 1))

# Fill constraint rows


for i in range(self.num_constraints):
for j in range(self.num_vars):
[Link][i][j] = [Link][i][j]
[Link][i][self.num_vars + i] = 1 # Slack variable
[Link][i][-1] = self.rhs_values[i] # RHS

# Fill objective row


for j in range(self.num_vars):
[Link][-1][j] = -self.obj_coeffs[j]

# Initial basic variables are slack variables


self.basic_vars = [f"s{i + 1}" for i in range(self.num_constraints)]

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.

# === Print Tableau ===


def print_tableau(self, title="", show_pivot=False, pivot_row=-1,
pivot_col=-1):
print(f"\n{[Link]}{title}{[Link]}")
print("═" * 100)

# 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)

if show_pivot and i == pivot_row and j == pivot_col:


# REMOVED BRACKETS: The pivot element is now simply
highlighted
# and right-aligned within the full 14-character width.
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="")

# Show ratio for minimum ratio test


if show_pivot and pivot_col >= 0 and [Link][i][pivot_col] >
0:
ratio = [Link][i][-1] / [Link][i][pivot_col]
ratio_frac = Fraction(ratio).limit_denominator(100)
print(f"{str(ratio_frac):>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.

# === Find Pivot Column ===


def find_pivot_column(self):
obj_row = [Link][-1][:-1]
min_val = min(obj_row)

if min_val >= -1e-10:


return -1 # Optimal solution found

return [Link](obj_row)

# === Find Pivot Row ===


def find_pivot_row(self, pivot_col):
min_ratio = float('inf')
pivot_row = -1

print(f"\n{[Link]}Minimum Ratio Test:{[Link]}")


print(f"{'Row':>5} {'Basic':>8} {'RHS':>12} {'Coeff':>12} {'Ratio':>12}
{'':>10}")
print("─" * 65)

for i in range(self.num_constraints):
coeff = [Link][i][pivot_col]
rhs = [Link][i][-1]

if coeff > 1e-10:


ratio = rhs / coeff
marker = ""
if ratio < min_ratio:
min_ratio = ratio
pivot_row = i
marker = f"{[Link]}← MIN{[Link]}"

print(f"{i + 1:>5} {self.basic_vars[i]:>8} {rhs:>12.4g}


{coeff:>12.4g} {ratio:>12.4g} {marker}")
else:
print(f"{i + 1:>5} {self.basic_vars[i]:>8} {rhs:>12.4g}
{coeff:>12.4g} {'---':>12} {'(skip)'}")

return pivot_row

Line-by-line explanation — find_pivot_column

• 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).

Line-by-line explanation — find_pivot_row


• min_ratio = float('inf')
o Initialize the minimum ratio to infinity so any valid ratio will be smaller.
• pivot_row = -1
o Initialize pivot row index as unknown.
• The print lines show a small table for the ratio test with headers.
• for i in range(self.num_constraints):
o Iterate through each constraint row to compute ratio.
• coeff = [Link][i][pivot_col]
o Coefficient in pivot column for this constraint.
• rhs = [Link][i][-1]
o Right-hand side value for this constraint.
• if coeff > 1e-10:
o Only consider positive coefficients for ratio test (non-positive means row
cannot limit increase of entering variable).
o 1e-10 handles floating point tiny inaccuracies; treat very small numbers as
zero.
• ratio = rhs / coeff
o Compute the ratio used in the minimum ratio test.
• marker = ""
o Temporary string to indicate which row currently has the smallest ratio.
• if ratio < min_ratio:
o If this ratio is smaller than the recorded min, update min_ratio and
pivot_row.
• marker = f"{[Link]}← MIN{[Link]}"
o Set marker to highlight row that currently wins the min ratio test.
• print(...)
o Print row index, basic variable name, RHS, coefficient, ratio and marker,
nicely formatted.
• else: print(...) for coeff <= 1e-10
o Print row details but show --- for ratio and (skip) comment because this row
can't be used (non-positive coefficient).
• return pivot_row
o After checking all rows, return the index of the row chosen by the minimum
ratio test.
o If no row had positive coefficient, pivot_row stays -1 and caller will treat
problem as unbounded.

# === Show Pivot Info ===


def show_pivot_info(self, pivot_row, pivot_col):
pivot_val = [Link][pivot_row][pivot_col]

print(f"\n{[Link]}PIVOT INFORMATION{[Link]}")
print("─" * 90)

col_name = self.var_names[pivot_col] if pivot_col < self.num_vars else


f"s{pivot_col - self.num_vars + 1}"

print(f"Pivot Column: {[Link]}{col_name}{[Link]}")


print(f"Pivot Row:
{[Link]}{self.basic_vars[pivot_row]}{[Link]}")
print(f"Pivot Element:
{[Link]}{[Link]}{pivot_val:.4g}{[Link]}")
print(f"Entering Variable: {[Link]}{col_name}{[Link]}")
print(f"Leaving Variable:
{[Link]}{self.basic_vars[pivot_row]}{[Link]}")

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).

# === Do Pivot Operation ===


def do_pivot(self, pivot_row, pivot_col):
pivot_val = [Link][pivot_row][pivot_col]

# Update basic variable


entering_var = self.var_names[pivot_col] if pivot_col < self.num_vars
else f"s{pivot_col - self.num_vars + 1}"
self.basic_vars[pivot_row] = entering_var

# Divide pivot row by pivot element


[Link][pivot_row] = [Link][pivot_row] / pivot_val

# Eliminate other rows


for i in range(len([Link])):
if i != pivot_row:
multiplier = [Link][i][pivot_col]
[Link][i] = [Link][i] - multiplier *
[Link][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.

# === Solve Using Simplex ===


def solve(self):
self.show_section("SOLUTION STEPS")

print(f"{[Link]}Starting simplex algorithm...{[Link]}\n")


input(f"{[Link]}Press Enter to see initial tableau...{[Link]}")

[Link] = 0
self.print_tableau(f"TABLEAU {[Link]} (Initial)")

max_iterations = 50

while [Link] < max_iterations:


[Link] += 1

input(f"\n{[Link]}Press Enter to continue to iteration


{[Link]}...{[Link]}")

print(f"\n{[Link]}{'═' * 90}")
print(f"ITERATION {[Link]}")
print(f"{'═' * 90}{[Link]}")

# Find pivot column (entering variable)


pivot_col = self.find_pivot_column()

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

# Find pivot row (leaving variable)


pivot_row = self.find_pivot_row(pivot_col)

if pivot_row == -1:
print(f"\n{[Link]}✗ UNBOUNDED SOLUTION{[Link]}")
print(f"{[Link]}No finite optimal solution
exists.{[Link]}")
return False

# Show tableau with pivot


self.print_tableau(f"\nTABLEAU {[Link] - 1} (with pivot)",
True, pivot_row, pivot_col)

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)")

print(f"\n{[Link]}✗ Maximum iterations reached{[Link]}")


return False

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.

# === Show Solution ===


def show_solution(self):
self.show_section("OPTIMAL SOLUTION")

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.

# === Main Run ===


def run(self):
while True:
self.show_banner()

# Get all inputs


self.get_objective_type()
self.get_problem_size()
self.get_objective_function()
self.get_constraints()

# Confirm problem
if not self.show_problem_summary():
print(f"\n{[Link]}Restarting input...{[Link]}")
input("Press Enter to continue...")
continue

# Show standard form


self.show_standard_form()
input(f"\n{[Link]}Press Enter to start solving...{[Link]}")

# Solve
self.setup_tableau()
[Link]()

# Ask to solve another


print(f"\n{'═' * 90}")
choice = input(f"\n{[Link]}Solve another problem? (y/n):
{[Link]}").strip().lower()
if choice != 'y':
print(f"\n{[Link]}Thank you for using Simplex Method
Calculator!{[Link]}")
print(f"{[Link]}{'═' * 90}{[Link]}\n")
break

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).

• # Run the program


if __name__ == "__main__":
try:
solver = SimplexSolver()
[Link]()
except KeyboardInterrupt:
print(f"\n\n{[Link]}Program interrupted by
user.{[Link]}")
except Exception as e:
print(f"\n{[Link]} Error: {str(e)}{[Link]}")
import traceback

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.

//The WHOLE CODE

"""
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

Submitted by Group 5 BSIT - 2A:


Achilles Pyrrhus A. Rosales
Justine Mae Delorino
Crysler Arcebuche
Paul Balena
Submitted to:
Sir Norcelito Galvan
"""

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'

#This defines a class (a machine that stores data + functions).


#__init__() is the constructor which runs every time nga ig-rurun mo an
solver/system.
class SimplexSolver:
def __init__(self):
# Problem data
self.num_vars = 0
self.num_constraints = 0
self.is_maximize = True
self.obj_coeffs = []
[Link] = []
self.rhs_values = []
self.constraint_types = []
self.var_names = []

# 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")

def show_section(self, title):


print(f"\n{[Link]}{[Link]}{'─' * 90}")
print(f" {title}")
print(f"{'─' * 90}{[Link]}\n")
def format_number(self, num):
"""Show whole numbers without decimals"""
if abs(num - round(num)) < 1e-10:
return str(int(round(num)))
return str(num)

# === STEP 1: Get Objective Type ===


def get_objective_type(self):
self.show_section("STEP 1: Objective Type")
print(f"{[Link]}Select optimization type:{[Link]}")
print(f" {[Link]}[1]{[Link]} Maximize")
print(f" {[Link]}[2]{[Link]} Minimize")

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]}")

# === STEP 2: Get Problem Size ===


def get_problem_size(self):
self.show_section("STEP 2: Problem Dimensions")

# Get number of variables


while True:
try:
self.num_vars = int(input(f"{[Link]}Number of decision
variables: {[Link]}"))
if self.num_vars > 0:
break
print(f"{[Link]}Must be positive{[Link]}")
except:
print(f"{[Link]}Please enter a valid number{[Link]}")

# Get number of constraints


while True:
try:
self.num_constraints = int(input(f"{[Link]}Number of
constraints: {[Link]}"))
if self.num_constraints > 0:
break
print(f"{[Link]} Must be positive{[Link]}")
except:
print(f"{[Link]} Please enter a valid
number{[Link]}")

# Set variable names (x, y for 2 vars; x, y, z for 3; etc.)


if self.num_vars == 2:
self.var_names = ['x', 'y']
elif self.num_vars == 3:
self.var_names = ['x', 'y', 'z']
elif self.num_vars == 4:
self.var_names = ['x', 'y', 'z', 'w']
else:
self.var_names = [f'x{i + 1}' for i in range(self.num_vars)]

print(f"\n{[Link]} Problem: {self.num_vars} variables,


{self.num_constraints} constraints{[Link]}")

# === STEP 3: Get Objective Function ===


def get_objective_function(self):
self.show_section("STEP 3: Objective Function")

obj_type = "Maximize" if self.is_maximize else "Minimize"


var_display = ' + '.join([f"c{i + 1}·{v}" for i, v in
enumerate(self.var_names)])

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]}")

# Show what was entered


parts = [f"{self.format_number(c)}{v}" for c, v in zip(coeffs,
self.var_names)]
obj_str = ' + '.join(parts).replace('+ -', '- ')
print(f"\n{[Link]} Objective: Z = {obj_str}{[Link]}")

# === STEP 4: Get Constraints ===


def get_constraints(self):
self.show_section("STEP 4: Constraints")

print(f"{[Link]}For each constraint:{[Link]}")


print(" • Enter coefficients (left side)")
print(" • Choose type: 1 (≤), 2 (≥), 3 (=)")
print(" • Enter right-hand side value")

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)

# Show what was entered


lhs_parts = [f"{self.format_number(c)}{v}" for c, v in
zip(coeffs, self.var_names)]
lhs = ' + '.join(lhs_parts).replace('+ -', '- ')
symbols = ['≤', '≥', '=']
print(f"{[Link]}✓ {lhs} {symbols[int(ctype) - 1]}
{self.format_number(rhs)}{[Link]}")

# === Show Problem Summary ===


def show_problem_summary(self):
self.show_section("PROBLEM SUMMARY")

obj_type = "Maximize" if self.is_maximize else "Minimize"


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"{[Link]}{obj_type} Z = {obj_str}{[Link]}\n")
print(f"{[Link]}Subject to:{[Link]}")

symbols = ['≤', '≥', '=']


for i in range(self.num_constraints):
lhs_parts = [f"{self.format_number(c)}{v}" for c, v in
zip([Link][i], self.var_names)]
lhs = ' + '.join(lhs_parts).replace('+ -', '- ')
symbol = symbols[self.constraint_types[i] - 1]
rhs = self.format_number(self.rhs_values[i])
print(f" {lhs} {symbol} {rhs}")

var_str = ', '.join(self.var_names)


print(f"\n {var_str} ≥ 0")

print(f"\n{[Link]}{'─' * 90}{[Link]}")
choice = input(f"\n{[Link]}Is this correct? (y/n):
{[Link]}").strip().lower()
return choice == 'y'

# === Show Standard Form ===


def show_standard_form(self):
self.show_section("STANDARD FORM CONVERSION")
print(f"{[Link]}Converting to standard form...{[Link]}\n")

# 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")

# Constraints with slack variables


slack_count = 0
for i in range(self.num_constraints):
lhs_parts = [f"{self.format_number(c)}{v}" for c, v in
zip([Link][i], self.var_names)]
lhs = ' + '.join(lhs_parts).replace('+ -', '- ')
rhs = self.format_number(self.rhs_values[i])

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}")

non_neg = ', '.join(self.var_names)


slack_vars = ', '.join([f's{i + 1}' for i in range(slack_count)])
print(f"\n{non_neg} ≥ 0 {[Link]}→{[Link]} {non_neg},
{slack_vars} ≥ 0")

# === Setup Initial Tableau ===


def setup_tableau(self):
total_vars = self.num_vars + self.num_constraints
rows = self.num_constraints + 1

[Link] = [Link]((rows, total_vars + 1))

# Fill constraint rows


for i in range(self.num_constraints):
for j in range(self.num_vars):
[Link][i][j] = [Link][i][j]
[Link][i][self.num_vars + i] = 1 # Slack variable
[Link][i][-1] = self.rhs_values[i] # RHS

# Fill objective row


for j in range(self.num_vars):
[Link][-1][j] = -self.obj_coeffs[j]

# Initial basic variables are slack variables


self.basic_vars = [f"s{i + 1}" for i in
range(self.num_constraints)]

# === Print Tableau ===


def print_tableau(self, title="", show_pivot=False, pivot_row=-1,
pivot_col=-1):
print(f"\n{[Link]}{title}{[Link]}")
print("═" * 100)
# 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)

if show_pivot and i == pivot_row and j == pivot_col:


# REMOVED BRACKETS: The pivot element is now simply
highlighted
# and right-aligned within the full 14-character width.

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="")

# Show ratio for minimum ratio test


if show_pivot and pivot_col >= 0 and [Link][i][pivot_col]
> 0:
ratio = [Link][i][-1] / [Link][i][pivot_col]
ratio_frac = Fraction(ratio).limit_denominator(100)
print(f"{str(ratio_frac):>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)

# === Find Pivot Column ===


def find_pivot_column(self):
obj_row = [Link][-1][:-1]
min_val = min(obj_row)
if min_val >= -1e-10:
return -1 # Optimal solution found

return [Link](obj_row)

# === Find Pivot Row ===


def find_pivot_row(self, pivot_col):
min_ratio = float('inf')
pivot_row = -1

print(f"\n{[Link]}Minimum Ratio Test:{[Link]}")


print(f"{'Row':>5} {'Basic':>8} {'RHS':>12} {'Coeff':>12}
{'Ratio':>12} {'':>10}")
print("─" * 65)

for i in range(self.num_constraints):
coeff = [Link][i][pivot_col]
rhs = [Link][i][-1]

if coeff > 1e-10:


ratio = rhs / coeff
marker = ""
if ratio < min_ratio:
min_ratio = ratio
pivot_row = i
marker = f"{[Link]}← MIN{[Link]}"

print(f"{i + 1:>5} {self.basic_vars[i]:>8} {rhs:>12.4g}


{coeff:>12.4g} {ratio:>12.4g} {marker}")
else:
print(f"{i + 1:>5} {self.basic_vars[i]:>8} {rhs:>12.4g}
{coeff:>12.4g} {'---':>12} {'(skip)'}")

return pivot_row

# === Show Pivot Info ===


def show_pivot_info(self, pivot_row, pivot_col):
pivot_val = [Link][pivot_row][pivot_col]

print(f"\n{[Link]}PIVOT INFORMATION{[Link]}")
print("─" * 90)

col_name = self.var_names[pivot_col] if pivot_col < self.num_vars


else f"s{pivot_col - self.num_vars + 1}"

print(f"Pivot Column: {[Link]}{col_name}{[Link]}")


print(f"Pivot Row:
{[Link]}{self.basic_vars[pivot_row]}{[Link]}")
print(f"Pivot Element:
{[Link]}{[Link]}{pivot_val:.4g}{[Link]}")
print(f"Entering Variable: {[Link]}{col_name}{[Link]}")
print(f"Leaving Variable:
{[Link]}{self.basic_vars[pivot_row]}{[Link]}")

# === Do Pivot Operation ===


def do_pivot(self, pivot_row, pivot_col):
pivot_val = [Link][pivot_row][pivot_col]

# Update basic variable


entering_var = self.var_names[pivot_col] if pivot_col <
self.num_vars else f"s{pivot_col - self.num_vars + 1}"
self.basic_vars[pivot_row] = entering_var

# Divide pivot row by pivot element


[Link][pivot_row] = [Link][pivot_row] / pivot_val

# Eliminate other rows


for i in range(len([Link])):
if i != pivot_row:
multiplier = [Link][i][pivot_col]
[Link][i] = [Link][i] - multiplier *
[Link][pivot_row]

# === Solve Using Simplex ===


def solve(self):
self.show_section("SOLUTION STEPS")

print(f"{[Link]}Starting simplex algorithm...{[Link]}\n")


input(f"{[Link]}Press Enter to see initial
tableau...{[Link]}")

[Link] = 0
self.print_tableau(f"TABLEAU {[Link]} (Initial)")

max_iterations = 50

while [Link] < max_iterations:


[Link] += 1

input(f"\n{[Link]}Press Enter to continue to iteration


{[Link]}...{[Link]}")

print(f"\n{[Link]}{'═' * 90}")
print(f"ITERATION {[Link]}")
print(f"{'═' * 90}{[Link]}")

# Find pivot column (entering variable)


pivot_col = self.find_pivot_column()

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

# Find pivot row (leaving variable)


pivot_row = self.find_pivot_row(pivot_col)

if pivot_row == -1:
print(f"\n{[Link]}✗ UNBOUNDED SOLUTION{[Link]}")
print(f"{[Link]}No finite optimal solution
exists.{[Link]}")
return False

# Show tableau with pivot


self.print_tableau(f"\nTABLEAU {[Link] - 1} (with
pivot)", True, pivot_row, pivot_col)
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)")

print(f"\n{[Link]}✗ Maximum iterations reached{[Link]}")


return False

# === Show Solution ===


def show_solution(self):
self.show_section("OPTIMAL SOLUTION")

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]}")

# === Main Run ===


def run(self):
while True:
self.show_banner()

# Get all inputs


self.get_objective_type()
self.get_problem_size()
self.get_objective_function()
self.get_constraints()

# Confirm problem
if not self.show_problem_summary():
print(f"\n{[Link]}Restarting input...{[Link]}")
input("Press Enter to continue...")
continue

# Show standard form


self.show_standard_form()
input(f"\n{[Link]}Press Enter to start
solving...{[Link]}")

# Solve
self.setup_tableau()
[Link]()

# Ask to solve another


print(f"\n{'═' * 90}")
choice = input(f"\n{[Link]}Solve another problem? (y/n):
{[Link]}").strip().lower()
if choice != 'y':
print(f"\n{[Link]}Thank you for using Simplex Method
Calculator!{[Link]}")
print(f"{[Link]}{'═' * 90}{[Link]}\n")
break
# Run the program
if __name__ == "__main__":
try:
solver = SimplexSolver()
[Link]()
except KeyboardInterrupt:
print(f"\n\n{[Link]}Program interrupted by user.{[Link]}")
except Exception as e:
print(f"\n{[Link]} Error: {str(e)}{[Link]}")
import traceback

traceback.print_exc()

You might also like