Определение динамических ограничений для оптимизации scipy в PythonPython

Программы на Python
Anonymous
Определение динамических ограничений для оптимизации scipy в Python

Сообщение Anonymous »

Я хотел абстрагировать следующую функцию, которая вычисляет минимальное значение целевой функции и значения, когда мы можем получить это минимальное значение для произвольного числа g.
Я начал с простого случая две переменные, это нормально

Код: Выделить всё

import numpy as np
from scipy.optimize import minimize

def optimize(g_0, s, g_max, eff, dist):
objective = lambda x: s[0] * x[0] + s[1] * x[1]

cons = [
{'type': 'ineq', 'fun': lambda x: x[0] - ((dist[0] + dist[1]) / eff - g_0)},                   # g_1 > (dist[0] + dist[1]) / eff - g_0
{'type': 'ineq', 'fun': lambda x: x[1] - ((dist[0] + dist[1] + dist[2]) / eff - x[0] - g_0)},  # g_2 > (dist[0] + dist[1] + dist[2]) / eff - g_1 - g_0
{'type': 'ineq', 'fun': lambda x: g_max - (dist[0] / eff - g_0) - x[0]},                       # g_1 < g_max - (dist[0] / eff - g_0)
{'type': 'ineq', 'fun': lambda x: g_max - (g_0 + x[0] - (dist[0] - dist[1]) / eff) - x[1]},    # g_2 < g_max - (g_0 + g_1 - (dist[0] - dist[1]) / eff)
]

# General constraints for all g
for i in range(len(s)):
cons.append({'type': 'ineq', 'fun': lambda x, i=i: x[i]})                   # g_i > 0
cons.append({'type': 'ineq', 'fun': lambda x, i=i: g_max - x[i]})           # g_i < g_max

# Bounds for the variables (g_1 and g_2)
g1_lower_bound = max(0, (dist[0] + dist[1]) / eff - g_0)
g1_upper_bound = min(g_max, g_max - (dist[0] / eff - g_0))

# Initial guess for the variables
x0 = [g1_lower_bound, max(0, ((dist[0] + dist[1] + dist[2]) / eff - g1_lower_bound - g_0) + 1)]

solution = minimize(objective, x0, method='SLSQP', bounds=[(g1_lower_bound, g1_upper_bound), (0, g_max)], constraints=cons)

g_1, g_2 = map(round, solution.x)
return g_1, g_2, round(solution.fun, 2)

g_0 = 80
s = [4.5, 3]
g_max = 135
eff = 5
dist = [400, 500, 600]
optimal_g1, optimal_g2, minimum_value = optimize(g_0, s, g_max, eff, dist)
print(f"Optimal values: g_1 = {optimal_g1}, g_2 = {optimal_g2}")
print(f"Minimum value of the objective function: {minimum_value}")
Затем я начал абстрагировать его для любых произвольных чисел g (i>=1). Вот общее правило неравенства
Изображение

Пока я пришел к этому коду, но когда я попытался отправить одни и те же параметры, он дал другой результат

Код: Выделить всё

import numpy as np
from scipy.optimize import minimize

def optimize(g_0, s, g_max, eff, dist):
objective = lambda x: sum(s[i] * x[i] for i in range(len(x)))

cons = []
for i in range(len(s)):
cons.append({'type': 'ineq', 'fun': lambda x, i=i: x[i] - (sum(dist[:i+2]) / eff - sum([g_0] + x[:i]))})  # g_i > sum of dists from dist[0] to dist[i] / eff - sum of g from g_0 to g_(i-1)

cons.append({'type': 'ineq', 'fun': lambda x, i=i: g_max - (sum([g_0] + x[:i]) - (sum(dist[:i+1]) / eff)) - x[i]})  # g_i < g_max - (sum of g from g_0 to g_(i-1) - sum of dists from dist[0] to dist[i] / eff)

# General constraints to ensure each g is between 0 and g_max
cons.append({'type': 'ineq', 'fun': lambda x, i=i: x[i]})                   # g_i > 0
cons.append({'type': 'ineq', 'fun': lambda x, i=i: g_max - x[i]})           # g_i < g_max

g1_lower_bound = max(0, (dist[0] + dist[1]) / eff - g_0)
g1_upper_bound = min(g_max, g_max - (dist[0] / eff - g_0))

# Initial guess for the variables
x0 = [g1_lower_bound, max(0, ((dist[0] + dist[1] + dist[2]) / eff - g1_lower_bound - g_0) + 1)]
solution = minimize(objective, x0, method='SLSQP', bounds=[(0, g_max) for _ in range(len(s))], constraints=cons)

g_values = list(map(round, solution.x))
return g_values, round(solution.fun, 2)

g_0 = 80
s = [4.5, 3]
g_max = 135
eff = 5
dist = [400, 500, 600]
optimal_g_values, minimum_value = optimize(g_0, s, g_max, eff, dist)
print(f"Optimal values: g = {optimal_g_values}")
print(f"Minimum value of the objective function: {minimum_value}")
Первая функция дает следующий результат, который также является правильным:

Оптимальные значения: g_1 = 100, g_2 = 120
Минимальное значение целевой функции: 810,0

Но во-вторых, после попытки сделать это для произвольной длины g, она возвращает:

Оптимальные значения: g = [135, 85]
Минимальное значение целевой функции: 862,5

Я проверил лямбда-функции во второй функции, и они кажутся правильными. Также, когда я пытаюсь выполнить этот код:

Код: Выделить всё

import numpy as np
from scipy.optimize import minimize

def optimize(g_0, s, g_max, eff, dist):
objective = lambda x: sum(s[i] * x[i] for i in range(len(x)))

cons = [
{'type': 'ineq', 'fun': lambda x: x[0] - ((dist[0] + dist[1]) / eff - g_0)},                   # g_1 > (dist[0] + dist[1]) / eff - g_0
{'type': 'ineq', 'fun': lambda x: x[1] - ((dist[0] + dist[1] + dist[2]) / eff - x[0] - g_0)},  # g_2 > (dist[0] + dist[1] + dist[2]) / eff - g_1 - g_0
]

for i in range(len(s)):
#cons.append({'type': 'ineq', 'fun': lambda x, i=i: x[i] - (sum(dist[:i+2]) / eff - sum([g_0] + x[:i]))})  # g_i > sum of dists from dist[0] to dist[i] / eff - sum of g from g_0 to g_(i-1)

cons.append({'type': 'ineq', 'fun': lambda x, i=i: g_max - (sum([g_0] + x[:i]) - (sum(dist[:i+1]) / eff)) - x[i]})  # g_i < g_max - (sum of g from g_0 to g_(i-1) - sum of dists from dist[0] to dist[i] / eff)

# General constraints to ensure each g is between 0 and g_max
cons.append({'type': 'ineq', 'fun': lambda x, i=i: x[i]})                   # g_i > 0
cons.append({'type': 'ineq', 'fun': lambda x, i=i: g_max - x[i]})           # g_i < g_max

g1_lower_bound = max(0, (dist[0] + dist[1]) / eff - g_0)
g1_upper_bound = min(g_max, g_max - (dist[0] / eff - g_0))

# Initial guess for the variables
x0 = [g1_lower_bound, max(0, ((dist[0] + dist[1] + dist[2]) / eff - g1_lower_bound - g_0) + 1)]
solution = minimize(objective, x0, method='SLSQP', bounds=[(0, g_max) for _ in range(len(s))], constraints=cons)

g_values = list(map(round, solution.x))
return g_values, round(solution.fun, 2)

g_0 = 80
s = [4.5, 3]
g_max = 135
eff = 5
dist = [400, 500, 600]
optimal_g_values, minimum_value = optimize(g_0, s, g_max, eff, dist)
print(f"Optimal values: g = {optimal_g_values}")
print(f"Minimum value of the objective function: {minimum_value}")
Правильный ответ:

Оптимальные значения: g_1 = 100, g_2 = 120
Минимум значение целевой функции: 810,0

Но если мы применим другое ограничение:

Код: Выделить всё

import numpy as np
from scipy.optimize import minimize

def optimize(g_0, s, g_max, eff, dist):
objective = lambda x: sum(s[i] * x[i] for i in range(len(x)))

cons = [
{'type': 'ineq', 'fun': lambda x: g_max - (dist[0] / eff - g_0) - x[0]},                       # g_1 < g_max - (dist[0] / eff - g_0)
{'type': 'ineq', 'fun': lambda x: g_max - (g_0 + x[0] - (dist[0] - dist[1]) / eff) - x[1]},    # g_2 < g_max - (g_0 + g_1 - (dist[0] - dist[1]) / eff)
]

for i in range(len(s)):
cons.append({'type': 'ineq', 'fun': lambda x, i=i: x[i] - (sum(dist[:i+2]) / eff - sum([g_0] + x[:i]))})  # g_i > sum of dists from dist[0] to dist[i] / eff - sum of g from g_0 to g_(i-1)

#cons.append({'type': 'ineq', 'fun': lambda x, i=i: g_max - (sum([g_0] + x[:i]) - (sum(dist[:i+1]) / eff)) - x[i]})  # g_i < g_max - (sum of g from g_0 to g_(i-1) - sum of dists from dist[0] to dist[i] / eff)

# General constraints to ensure each g is between 0 and g_max
cons.append({'type': 'ineq', 'fun': lambda x, i=i: x[i]})                   # g_i > 0
cons.append({'type': 'ineq', 'fun': lambda x, i=i: g_max - x[i]})           # g_i < g_max

g1_lower_bound = max(0, (dist[0] + dist[1]) / eff - g_0)
g1_upper_bound = min(g_max, g_max - (dist[0] / eff - g_0))

# Initial guess for the variables
x0 = [g1_lower_bound, max(0, ((dist[0] + dist[1] + dist[2]) / eff - g1_lower_bound - g_0) + 1)]
solution = minimize(objective, x0, method='SLSQP', bounds=[(0, g_max) for _ in range(len(s))], constraints=cons)

g_values = list(map(round, solution.x))
return g_values, round(solution.fun, 2)

g_0 = 80
s = [4.5, 3]
g_max = 135
eff = 5
dist = [400, 500, 600]
optimal_g_values, minimum_value = optimize(g_0, s, g_max, eff, dist)
print(f"Optimal values: g = {optimal_g_values}")
print(f"Minimum value of the objective function: {minimum_value}")
Он дает правильные значения, но неправильное минимальное значение целевой функции:

Оптимальные значения: g = [100 , 120]
Минимальное значение целевой функции: 810,65

На данный момент я могу предположить, что либо я написал неверную лямбда-функцию в вторая функция или что-то неожиданное происходит в цикле

Подробнее здесь: https://stackoverflow.com/questions/786 ... -in-python

Вернуться в «Python»