i want to define an equation in gekko, but than comes the error:
Traceback (most recent call last):
File "/Users/stefantomaschko/Desktop/Bundeswettbewerb Informatik/2.Runde/Päckchen/paeckchen_gurobi.py", line 131, in <module>
m.solve()
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/gekko/gekko.py", line 2166, in solve
raise Exception(apm_error)
Exception: @error: Equation Definition
Equation without an equality (=) or inequality (>,<)
true
STOPPING...
my Code (not all functions, but the most important):
def fitness(var):
anzahl_sorte_stil = {}
boxes = convert(var)
print(boxes)
stile = set()
for var_box in var:
#anzahl_box = []
for v in var_box:
try:
value = int(str(v.value))
except:
value = int(float(str(v.value[0])))# if v.value != None else 0
info = info_name(v)
stile.add(info[1])
if info not in anzahl_sorte_stil:
anzahl_sorte_stil[info] = value
else:
anzahl_sorte_stil[info] += value
#anzahl_box.append(value)
# if min(anzahl_box) == 0:
gruppen = finde_gruppen(stile)
for g in gruppen:
if g not in kombinierbar:
return unmoeglich
#print(anzahl_sorte_stil)
uebrig = 0
for kleid in kleider:
dif = kleid[2] - anzahl_sorte_stil[(kleid[0],kleid[1])]
if dif<0:
print("ZU OFT VERWENDET!")
return unmoeglich
else:
uebrig += dif
return uebrig
sorten,stile,kombinierbar,kleider,gesamt = read_data("paeckchen0.txt")
unmoeglich = gesamt+1
min_boxen,max_boxen = get_min_max_boxen(sorten,kleider)
print("Min. Anzahl Boxen: ", min_boxen)
print("Max. Anzahl Boxen: ", max_boxen)
m = GEKKO(remote=False)
m.options.max_time = 1000
m.options.max_iter = 1000
m.options.max_memory = 1000
var = [[] for _ in range(max_boxen)]
for i,var_box in enumerate(var):
for kleid in kleider:
#print(kleid[:2])
var_box.append(m.Var(0,lb=1,ub=min((kleid[2],3)),integer=True,name=f"{kleid[0]}_{kleid[1]}_{i}"))#wie oft ist Kleid {kleid[:2]} in Box {i}
#m.Equation(fitness(var) < gesamt)
m.Minimize(fitness(var))
m.Equation(fitness(var) <= unmoeglich)
m.options.SOLVER=1
m.solve()
in the docmentation i didnt found anything related to that. can anybody help me to change it. I would also be happy about some looks at my code and why it did not find the right solution. now i want to implement the equation to not even allow incorrect solutions.
Gekko optimization models can be defined by function calls but then the model is compiled into byte-code. The function fitness()
is called only twice with the definition of the objective function and the equation:
m.Minimize(fitness(var))
m.Equation(fitness(var) <= unmoeglich)
You can inspect the model in the folder that is opened with m.open_folder()
in the file gk0_model.apm
as a text file. The fitness()
function overwrites the Gekko variable and returns a scalar value. That is why a True
is returned as the equation because Gekko operator overloading is not used to evaluate the inequality constraint. It becomes a simple Python expression that evaluates to True
. To remedy this problem, use Gekko expressions that provide continuous first and second derivative information to the gradient-based solvers such as m.if3(condition,val1,val2)
or m.max3(0,expression)
.
From the constraints and variable names, I'm guessing that the application is a packing optimization problem with categories and combinations to evaluate a packing configuration and calculate a score based on the number of items, the types, and how they are distributed among the boxes. The objective appears to be a cost or inefficiency metric. Feasibility constraints in the solver should work to find a solution without needing to help with if
statements. Here is an example packing optimization in Gekko:
from gekko import GEKKO
m = GEKKO(remote=False)
# 5 types of items, and a maximum of 10 boxes to use
num_items = 5
max_boxes = 10
# size of each item type (units of volume or weight)
item_sizes = [3, 4, 2, 5, 3]
# number of each item type available
item_counts = [10, 6, 8, 5, 7]
# max capacity of each box
box_capacity = [10,10,10,15,15,15,15,20,20,20]
# number of each item type in each box
item_in_box = [[m.Var(lb=0, ub=item_counts[i], integer=True)
for i in range(num_items)]
for _ in range(max_boxes)]
# Objective: minimize the number of boxes used
# could also minimize unused volume or another metric
boxes_used = m.Array(m.Var,max_boxes,lb=0,ub=1,integer=True)
m.Minimize(sum(boxes_used))
# total size of items in each box does not exceed box capacity
for box in range(max_boxes):
m.Equation(m.sum([item_in_box[box][i] * item_sizes[i]
for i in range(num_items)])
<= box_capacity[box] * boxes_used[box])
# all items are packed
for i in range(num_items):
m.Equation(m.sum([item_in_box[box][i]
for box in range(max_boxes)])==item_counts[i])
# Solve the problem with APOPT solver
m.options.SOLVER = 1
m.solve(disp=True)
# Output the solution
print("Optimal Packing Solution:")
for box in range(max_boxes):
if boxes_used[box].value[0] > 0.5: # box is used
print(f"Box {box + 1}:")
for i in range(num_items):
iib = int(item_in_box[box][i].value[0])
if iib > 0:
print(f" - Item Type {i+1}: {iib}")
The optimizer chooses the largest boxes because the objective is to minimize the number of boxes used. Here is the solution:
---------------------------------------------------
Solver : APOPT (v1.0)
Solution time : 2.23269999999320 sec
Objective : 7.00000000000000
Successful solution
---------------------------------------------------
Optimal Packing Solution:
Box 4:
- Item Type 2: 1
- Item Type 3: 1
- Item Type 4: 1
- Item Type 5: 1
Box 5:
- Item Type 1: 1
- Item Type 3: 2
- Item Type 4: 1
- Item Type 5: 1
Box 6:
- Item Type 1: 1
- Item Type 2: 1
- Item Type 3: 1
- Item Type 5: 1
Box 7:
- Item Type 1: 2
- Item Type 2: 1
- Item Type 3: 1
- Item Type 5: 1
Box 8:
- Item Type 1: 2
- Item Type 2: 1
- Item Type 3: 1
- Item Type 4: 1
- Item Type 5: 1
Box 9:
- Item Type 1: 2
- Item Type 2: 1
- Item Type 3: 1
- Item Type 4: 1
- Item Type 5: 1
Box 10:
- Item Type 1: 2
- Item Type 2: 1
- Item Type 3: 1
- Item Type 4: 1
- Item Type 5: 1
The objective could be adjusted to minimize unused volume or another metric. There is a related circle packing optimization in the Design Optimization course.