counting / maths /operations_research /solve_primal_directly.py
spagestic's picture
changed routing from education level to topics in maths
6c13437
raw
history blame
1.92 kB
import numpy as np
from scipy.optimize import linprog # Using SciPy for robust LP solving
import warnings
def solve_primal_directly(objective_type, c, A, relations, b):
"""Helper to solve primal directly using linprog for comparison/fallback"""
primal_c = np.array(c, dtype=float)
primal_A = np.array(A, dtype=float)
primal_b = np.array(b, dtype=float)
num_vars = len(c)
A_ub, b_ub, A_eq, b_eq = [], [], [], []
sign_flip = 1.0
if objective_type.lower() == 'max':
primal_c = -primal_c
sign_flip = -1.0
for i in range(len(relations)):
if relations[i] == '<=':
A_ub.append(primal_A[i])
b_ub.append(primal_b[i])
elif relations[i] == '>=':
A_ub.append(-primal_A[i]) # Convert >= to <= for linprog A_ub
b_ub.append(-primal_b[i])
elif relations[i] == '=':
A_eq.append(primal_A[i])
b_eq.append(primal_b[i])
# Convert lists to arrays, handling empty cases
A_ub = np.array(A_ub) if A_ub else None
b_ub = np.array(b_ub) if b_ub else None
A_eq = np.array(A_eq) if A_eq else None
b_eq = np.array(b_eq) if b_eq else None
try:
result_primal = linprog(primal_c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq=b_eq, bounds=[(0, None)] * num_vars, method='highs') # 'highs' is default and robust
if result_primal.success:
primal_sol_vals = result_primal.x
primal_obj_val = result_primal.fun * sign_flip # Adjust obj value back if Max
primal_sol_dict = {f'x{j+1}': primal_sol_vals[j] for j in range(num_vars)}
return 0, "Solved directly", primal_sol_dict, None, primal_obj_val
else:
return result_primal.status, f"Direct solve failed: {result_primal.message}", None, None, None
except Exception as e:
return -1, f"Direct solve exception: {e}", None, None, None