Проблема с симплекс-методом на python
Встала потребность написать свой сайт с решением симплекс-метода на поиск максимум.
Решил это сделать на питоне. Пошарил в интернете, нашел какие-то попытки это сделать, посидев несколько дней что-то получилось, но очень кривое. Так как проверив на сайте решение, то оно почти совпадает с ним, но является неправильным.
Сайт который я использовал для проверки задачи:
И что получил у себя после вычислений:
максимально близкие значения, но x2 в никаких видах этого метода(проверял на других задачах), никогда не хочет принимать истинное значение. Помогите найти проблему в методе.
from flask import Flask, request, jsonify
from flask_cors import CORS
import numpy as np
from fractions import Fraction
app = Flask(__name__)
CORS(app)
def display_tableau(tableau, basis):
tableau_str = ""
tableau_str += "Базис | " + " | ".join([f"x{i}" for i in range(1, tableau.shape[1])]) + " | Свободные члены\n"
tableau_str += "-" * (12 + 9 * tableau.shape[1]) + "\n"
for i, row in enumerate(tableau):
basis_var = basis[i] if i < len(basis) else 'F'
row_str = f"{basis_var} | " + " | ".join([str(Fraction(cell).limit_denominator()) for cell in row])
tableau_str += row_str + "\n"
return tableau_str
def simplex_method(c, A, b):
tableau = np.hstack([A, np.eye(len(b)), b.reshape(-1, 1)])
c_extended = np.hstack([c, np.zeros(len(b)+1)])
tableau = np.vstack([tableau, c_extended])
basis = [f"x{i+1}" for i in range(len(b))]
iteration = 0
all_tableaux = []
while True:
iteration += 1
tableau_str = f"\nИтерация {iteration}:\n"
tableau_str += display_tableau(tableau, basis)
all_tableaux.append(tableau_str)
pivot_col = np.argmin(tableau[-1, :-1])
if tableau[-1, pivot_col] >= 0:
break
ratios = tableau[:-1, -1] / tableau[:-1, pivot_col]
positive_ratios = [(ratios[i], i) for i in range(len(ratios)) if ratios[i] > 0]
pivot_row = min(positive_ratios, key=lambda x: x[0])[1]
tableau[pivot_row, :] /= tableau[pivot_row, pivot_col]
for i in range(tableau.shape[0]):
if i != pivot_row:
tableau[i, :] -= tableau[i, pivot_col] * tableau[pivot_row, :]
# Обновляем базис
basis[pivot_row] = f"x{pivot_col+1}"
# Финальное решение
final_solution = np.zeros(len(c))
for i in range(len(basis)):
if 'x' in basis[i]:
var_index = int(basis[i][1:]) - 1
final_solution[var_index] = tableau[i, -1]
max_profit = tableau[-1, -1]
return all_tableaux, final_solution, max_profit
@app.route('/solve', methods=['POST'])
def solve_simplex():
try:
data = request.get_json()
# Целевая функция
c = np.array(parse_objective(data['objectiveFunction']))
# Ограничения
A, b = parse_constraints(data['constraints'])
tableaux, solution, profit = simplex_method(c, A, b)
result = {
"tableaux": tableaux,
"solution": [str(Fraction(x).limit_denominator()) for x in solution],
"profit": str(Fraction(profit).limit_denominator())
}
return jsonify(result)
except Exception as e:
return jsonify({'error': str(e)})
def parse_objective(obj_str):
cleaned_str = obj_str.replace('\u200b', '').replace(' ', '')
terms = cleaned_str.split('+')
return [-int(term.split('x')[0]) for term in terms] # Инвертируем для минимизации
def parse_constraints(con_str):
cleaned_str = con_str.replace('\u200b', '').replace(' ', '')
constraints = []
bounds = []
for line in cleaned_str.split('\n'):
parts = line.split('<=')
left_side = parts[0].split('+')
right_side = int(parts[1])
constraints.append([int(term.split('x')[0]) for term in left_side])
bounds.append(right_side)
return np.array(constraints), np.array(bounds)
if __name__ == '__main__':
app.run(debug=True)