gekko error in resource optimisation-problem

31 views
Skip to first unread message

Alok Mathur

unread,
Sep 10, 2024, 10:16:21 PM9/10/24
to apmonitor
Hi All , 

I faced a problem while using Gekko for resource optimization formulation . I asked about it in stack overflow here:
https://stackoverflow.com/questions/78970689/gekko-error-in-resource-optimisation-problem

Pls let me know if anyone has suggestion regarding the error , i am getting.

Thanks,

John Hedengren

unread,
Sep 12, 2024, 5:44:42 PM9/12/24
to apmo...@googlegroups.com
Alok,
Just went to work on your question and I see that it was deleted. Just checking to see if you still need help on it. The issue is that you don't need the ">0" when defining the m.if3(condition,result1, result2). It isn't m.if3(condition>0,result1,result2)
-John


import numpy as np

from gekko import GEKKO


def allocation(rewards, num_machines, num_users, num_resources, C1, C2, demands, cumulative_gain):

    

    

    m = GEKKO(remote=False)


    # Decision variables

    link = m.Array(m.Var, (num_machines, num_users), lb=0, ub=1, integer=True)

    weights = m.Array(m.Var, num_users, lb=0.1, ub=1)


    # Constraints

    for u in range(num_users):

        m.Equation(m.sum(link[:, u]) <= 1)  # each user is assigned to only 1 machine


    for b in range(num_machines):

        m.Equation(m.sum(link[b, :] * weights) <= 1)  # sum of weights of users allocated to each machine should be 1


    # Compute Fairness

    fairness, reward = compute_fairness(link, weights, rewards, demands, cumulative_gain, num_resources, m)


    # Objective

    m.Maximize(C1 * reward + C2 * fairness)


    m.options.SOLVER = 1  # Change solver (1=APOPT, 3=IPOPT)

    m.open_folder()

    m.solve(disp=True)


    optimized_weights = np.array([weight.value[0] for weight in weights])

    optimized_link = np.ndarray((num_machines, num_users))

    for i in range(link.shape[0]):

        for j in range(link.shape[1]):

            optimized_link[i][j] = link[i][j][0]


    return optimized_link, optimized_weights, m


def compute_fairness(link, weights, rewards, demands, cumulative_gain, num_resources, m):

    """

    Computes the fairness of the system based on the resources allocated to users using GEKKO-compatible logic.

    """

    num_machines = link.shape[0]

    num_users = link.shape[1]

    

    total_gain_u = []

    user_fairness = []

    total_machine_weight = []

    

    for b in range(num_machines):

        total_machine_weight.append(m.Intermediate(m.sum([link[b][u_] * weights[u_] for u_ in range(num_users)])))


    # Compute fairness for each user

    for u in range(num_users):

        total_gain_u.append(m.Intermediate(cumulative_gain[u]))  # Use GEKKO's Intermediate for cumulative gain


        # Loop over machines and calculate gain for user u

        for b in range(num_machines):

            # GEKKO constraint-compatible check if user u is connected to machine b

            link_value = link[b][u]


            # Use GEKKO's if3 function to avoid direct Python conditional checks

            resources_allocated_to_u_b = m.if3(total_machine_weight[b], (weights[u] / total_machine_weight[b]) * num_resources, 0)


            # Add the gain from machine b to user u, conditioned on the link value

            total_gain_u[u] += link_value * resources_allocated_to_u_b * rewards[b, u]


        # Fairness is calculated based on total gain divided by demand

        fairness_u = m.Intermediate(total_gain_u[u] / demands[u]) if demands[u] > 0 else 0

        user_fairness.append(fairness_u)


    # Compute fairness for each machine using the geometric mean of users it serves

    machine_fairness = []

    for b in range(num_machines):

        connected_user_fairness = []

        for u in range(num_users):

            connected_fairness = m.Intermediate(link[b][u] * user_fairness[u])

            connected_user_fairness.append(connected_fairness)


        if connected_user_fairness:

            product = m.Intermediate(1)

            for fairness in connected_user_fairness:

                product *= fairness

            fairness_machine = m.Intermediate(product ** (1 / len(connected_user_fairness)))

            machine_fairness.append(fairness_machine)


    # Compute total system fairness using the geometric mean of the fairness of all machines

    if machine_fairness:

        product1 = m.Intermediate(1)

        for fairness in machine_fairness:

            product1 *= fairness

        total_fairness = m.Intermediate(product1 ** (1 / len(machine_fairness)))

    else:

        total_fairness = 0

      

    total_rewards = m.Var(lb=0)  # Create GEKKO variable for total rewards


    for u in range(num_users):

        # Allocate resources to user u based on its weight relative to the total weight

        resources_allocated_to_u_b = m.if3(total_machine_weight[b], (weights[u] / total_machine_weight[b]) * num_resources, 0)


        # Calculate reward for user u based on resources allocated

        reward_contribution = link[b][u] * resources_allocated_to_u_b * rewards[b, u]

        total_rewards += reward_contribution

    

    return total_fairness, total_rewards



# Test setup

num_machines = 2

num_users = 5

num_resources = 2

demands = [100, 100, 100, 100, 100]

cumulative_gain = [0, 0, 0, 0, 0]

sinr_matrix = np.random.randint(1, num_machines * num_users, size=(num_machines, num_users))

C1 = 1

C2 = 1


print('Demands:', demands)

print('Cumulative Gain:', cumulative_gain)


link, weights, m = allocation(sinr_matrix, num_machines, num_users, num_resources, C1, C2, demands, cumulative_gain)


print('Link Matrix:', link)

print('Weights:', weights)




From: 'Alok Mathur' via apmonitor <apmo...@googlegroups.com>
Sent: Tuesday, September 10, 2024 7:39:51 PM
To: apmonitor <apmo...@googlegroups.com>
Subject: [APM] gekko error in resource optimisation-problem
 
--
--
APMonitor user's group e-mail list.
- To post a message, send email to apmo...@googlegroups.com
- To unsubscribe, send email to apmonitor+...@googlegroups.com
- Visit this group at http://groups.google.com/group/apmonitor
---
You received this message because you are subscribed to the Google Groups "apmonitor" group.
To unsubscribe from this group and stop receiving emails from it, send an email to apmonitor+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/apmonitor/3af80fed-b0e8-4d41-aa77-49e454cced87n%40googlegroups.com.

Alok Mathur

unread,
Sep 14, 2024, 2:19:34 AM9/14/24
to apmonitor
Thanks a lot john for the response. I do still need some help. After posting the question i resolved the issue by changing some piece of code. Further i wrote a similar code which is not giving any error but the results are not as expected. If you see inside fairness i have implemented geometric mean of fairness of UE and further geometric mean of machines which serves the user.  But when I am running the code the allocation matrix and weights vector does not allocate any user to machines neither assigns weights to user. 
Following is the running code:
import numpy as np
from gekko import GEKKO


def allocation(sinr, num_machine, num_user, num_resources, C1, C2, cumulative_gain, demands):
    rewards = sinr

   
    m = GEKKO(remote=False)

    # Decision variables
    link = m.Array(m.Var, (num_machine, num_user), lb=0, ub=1, integer=True)
    weights = m.Array(m.Var, num_user, lb=0.1, ub=1)

    # Constraints
    for u in range(num_user):

        m.Equation(m.sum(link[:, u]) <= 1)  # each user is assigned to only 1 machine

    for b in range(num_machine):

        m.Equation(m.sum(link[b, :] * weights) <= 1)  # sum of weights of users allocated to each machine should be 1
        m.Equation(m.sum(link[b, :]) <= num_resources)                
   
    # Compute Fairness
    f = compute_fairness(link, weights, rewards, demands, cumulative_gain, num_resources, m)

    # Objective
    m.Maximize(C2 * f)


    m.options.SOLVER = 1  # Change solver (1=APOPT, 3=IPOPT)
    # m.open_folder()

    m.solve(disp=True)

    optimized_weights = np.array([weight.value[0] for weight in weights])
    optimized_link = np.ndarray((num_machine, num_user))

    for i in range(link.shape[0]):
        for j in range(link.shape[1]):
            optimized_link[i][j] = link[i][j][0]
               
    print('LPScheduler.py rewards are ', rewards)
    print('LPScheduler.py link matrix calculated', link)
    print('LPScheduler.py weights calculated', weights)
    print('LPScheduler.py Objective calculated: ' + str(m.options.objfcnval))

    return optimized_link, optimized_weights, m


def reward(allocation, weights, rewards):
    temp = np.copy(allocation)

    total_rewards = np.sum(temp.flatten() * rewards.flatten())
    return total_rewards


def compute_fairness(link, weights, rewards, demands, cumulative_gain, num_resources, m):
   
    num_machine = link.shape[0]
    num_user = link.shape[1]

    fairness_list = []
    for b in range(num_machine):
        row_fairness = []
        for u_ in range(num_user):
            fair_val = ((link[b][u_] * weights[u_] * num_resources * rewards[b][u_]) + cumulative_gain[u_]) / demands[u_]
            row_fairness.append(fair_val)
        fairness_list.append(row_fairness)

    fairness_matrix = np.array(fairness_list)
    fairness_matrix = fairness_matrix.reshape(num_machine, num_user)
   
    # Geometric Mean (avoid zero sum for links)
    epsilon = 1e-8
    machine_gms = []
    for b in range(num_machine):
        link_sum = m.sum([link[b][i] for i in range(num_user)])
        non_zero_link_sum = m.if3(link_sum, link_sum, 1)  # Avoid division by zero
        product = m.Intermediate(1)
        for u_ in range(num_user):
            product = m.if3(fairness_matrix[b][u_], product * fairness_matrix[b, u_], product)
        machine_gms.append(product ** (1 / non_zero_link_sum))    

    gm_of_gms = m.exp(m.sum([m.log(gm + epsilon) for gm in machine_gms]) / num_machine)
   
    return gm_of_gms


# Test case
num_machine = 2
num_user = 5

num_resources = 2
demands = [100, 100, 100, 100, 100]
cumulative_gain = [0.1, 0.1, 0.2, 0.5, 0.1]
sinr_matrix = np.random.randint(1, 100, size=(num_machine, num_user))

C1 = 1
C2 = 100

print('Demand:', demands)
print('Cumulative gain:', cumulative_gain)

link, weights, m = allocation(sinr_matrix, num_machine, num_user, num_resources, C1, C2, cumulative_gain, demands)

The output looks like this:

Demand: [100, 100, 100, 100, 100] Cumulative gain: [0.1, 0.1, 0.2, 0.5, 0.1] ---------------------------------------------------------------- APMonitor, Version 1.0.1 APMonitor Optimization Suite ---------------------------------------------------------------- --------- APM Model Size ------------ Each time step contains Objects : 3 Constants : 0 Variables : 77 Intermediates: 2 Connections : 15 Equations : 50 Residuals : 48 Number of state variables: 77 Number of total equations: - 50 Number of slack variables: - 33 --------------------------------------- Degrees of freedom : -6 * Warning: DOF <= 0 ---------------------------------------------- Steady State Optimization with APOPT Solver ---------------------------------------------- Iter: 1 I: 0 Tm: 0.01 NLPi: 5 Dpth: 0 Lvs: 3 Obj: -1.00E+00 Gap: NaN Iter: 2 I: -1 Tm: 0.00 NLPi: 14 Dpth: 1 Lvs: 2 Obj: -1.00E+00 Gap: NaN Iter: 3 I: 0 Tm: 0.00 NLPi: 2 Dpth: 1 Lvs: 3 Obj: -1.00E+00 Gap: NaN Iter: 4 I: 0 Tm: 0.00 NLPi: 2 Dpth: 1 Lvs: 4 Obj: -1.00E+00 Gap: NaN Iter: 5 I: -1 Tm: 0.01 NLPi: 22 Dpth: 2 Lvs: 3 Obj: -1.00E+00 Gap: NaN Iter: 6 I: -1 Tm: 0.00 NLPi: 18 Dpth: 2 Lvs: 2 Obj: -1.00E+00 Gap: NaN --Integer Solution: -1.00E+00 Lowest Leaf: -1.00E+00 Gap: 0.00E+00 Iter: 7 I: 0 Tm: 0.00 NLPi: 2 Dpth: 2 Lvs: 2 Obj: -1.00E+00 Gap: 0.00E+00 Successful solution --------------------------------------------------- Solver : APOPT (v1.0) Solution time : 4.679999999643769E-002 sec Objective : -1.00000001000000 Successful solution --------------------------------------------------- LPScheduler.py rewards are [[10 97 76 73 1] [71 34 61 42 1]] LPScheduler.py link matrix calculated [[[0.0] [0.0] [0.0] [0.0] [0.0]] [[0.0] [0.0] [0.0] [0.0] [0.0]]] LPScheduler.py weights calculated [[0.1] [0.1] [0.1] [0.1] [0.1]] LPScheduler.py Objective calculated: -1.00000001
Could you please share your thoughts on what could be going wrong here?

Thanks 
Alok

John Hedengren

unread,
Sep 19, 2024, 1:41:19 PM9/19/24
to apmo...@googlegroups.com

Alok,

 

The solver may have found a local minimum at zero or it could be that the function:

 

f = compute_fairness(link, weights, rewards, demands, cumulative_gain, num_resources, m)

 

is not defined with Gekko variables. Make sure that all variables are defined as `m.Var()` and equations are defined with `m.Equation()`. External functions aren’t allowed because Gekko needs to compile the equations for automatic differentiation. The function `compute_fairness` is only evaluated once when the model is initialized and the equations need to be built symbolically for the compiler.

 

For future questions with Gekko, please see the support resource including GPT4 Gekko chatbot and the StackOverflow forum.

 

Best regards,

John Hedengren

Reply all
Reply to author
Forward
0 new messages