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)
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
To view this discussion on the web visit https://groups.google.com/d/msgid/apmonitor/e9d56e1e-ddbf-4bd0-9358-4afc46820311n%40googlegroups.com.