pythonoptimizationgekko

can't use gekko equation


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.


Solution

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

    Circle packing optimization