Skip to content

Instantly share code, notes, and snippets.

@LexSong
Created December 9, 2024 04:46
Show Gist options
  • Select an option

  • Save LexSong/4dfb03b298511814517c54185e437a19 to your computer and use it in GitHub Desktop.

Select an option

Save LexSong/4dfb03b298511814517c54185e437a19 to your computer and use it in GitHub Desktop.
from pulp import LpInteger
from pulp import LpMaximize
from pulp import LpProblem
from pulp import LpVariable
def maximize_score(A_total, B_total, C_total, D_total):
prob = LpProblem("MaximizeScore", LpMaximize)
# Define helper function to create variables for single-resource conversions
def resource_vars(name_prefix):
# Returns variables for 10-set, 4-set, and single-unit usage
return (
LpVariable(f"{name_prefix}_10", lowBound=0, cat=LpInteger),
LpVariable(f"{name_prefix}_4", lowBound=0, cat=LpInteger),
LpVariable(f"{name_prefix}_1", lowBound=0, cat=LpInteger),
)
# Variables for combinations
x1 = LpVariable("combo1", lowBound=0, cat=LpInteger) # A3+B3+C3+D3 = 30 points
x2 = LpVariable("combo2", lowBound=0, cat=LpInteger) # A2+B2+C2+D2 = 18 points
x3 = LpVariable("combo3", lowBound=0, cat=LpInteger) # A1+B1+C1+D1 = 8 points
x4 = LpVariable("combo4", lowBound=0, cat=LpInteger) # A1+D1 = 5 points
x5 = LpVariable("combo5", lowBound=0, cat=LpInteger) # A1+C2 = 8 points
x6 = LpVariable("combo6", lowBound=0, cat=LpInteger) # D1+B2 = 8 points
# Resource conversion variables
A_10, A_4, A_1 = resource_vars("A")
B_10, B_4, B_1 = resource_vars("B")
C_10, C_4, C_1 = resource_vars("C")
D_10, D_4, D_1 = resource_vars("D")
# Objective function
# Combos:
# x1: 30 pts, x2: 18 pts, x3: 8 pts, x4: 5 pts, x5: 8 pts, x6: 8 pts
# Resource conversions:
# Each 10-same-resource: 30 pts, each 4-same-resource: 10 pts, each single: 1 pt
prob += (
30 * x1
+ 18 * x2
+ 8 * x3
+ 5 * x4
+ 8 * x5
+ 8 * x6
+ 30 * (A_10 + B_10 + C_10 + D_10)
+ 10 * (A_4 + B_4 + C_4 + D_4)
+ (A_1 + B_1 + C_1 + D_1)
)
# Constraints for resource usage:
# A resource
prob += (
3 * x1 + 2 * x2 + 1 * x3 + 1 * x4 + 1 * x5 + 0 * x6 + 10 * A_10 + 4 * A_4 + A_1 <= A_total
)
# B resource
prob += (
3 * x1 + 2 * x2 + 1 * x3 + 0 * x4 + 0 * x5 + 2 * x6 + 10 * B_10 + 4 * B_4 + B_1 <= B_total
)
# C resource
prob += (
3 * x1 + 2 * x2 + 1 * x3 + 0 * x4 + 2 * x5 + 0 * x6 + 10 * C_10 + 4 * C_4 + C_1 <= C_total
)
# D resource
prob += (
3 * x1 + 2 * x2 + 1 * x3 + 1 * x4 + 0 * x5 + 1 * x6 + 10 * D_10 + 4 * D_4 + D_1 <= D_total
)
# Solve the problem
prob.solve()
# Extract results
result = {
"Status": prob.status,
"Objective": prob.objective.value(),
"combo1": x1.varValue,
"combo2": x2.varValue,
"combo3": x3.varValue,
"combo4": x4.varValue,
"combo5": x5.varValue,
"combo6": x6.varValue,
"A_10": A_10.varValue,
"A_4": A_4.varValue,
"A_1": A_1.varValue,
"B_10": B_10.varValue,
"B_4": B_4.varValue,
"B_1": B_1.varValue,
"C_10": C_10.varValue,
"C_4": C_4.varValue,
"C_1": C_1.varValue,
"D_10": D_10.varValue,
"D_4": D_4.varValue,
"D_1": D_1.varValue,
}
return result
def print_solution(result):
if result["Status"] != 1:
print("No optimal solution found.")
return
print("Optimal solution found!")
print(f"Total Score: {result['Objective']:.0f}")
print("\nCombinations chosen (and their scoring):")
combo_info = {
"combo1": ("A3 + B3 + C3 + D3 => 30 pts", 30),
"combo2": ("A2 + B2 + C2 + D2 => 18 pts", 18),
"combo3": ("A1 + B1 + C1 + D1 => 8 pts", 8),
"combo4": ("A1 + D1 => 5 pts", 5),
"combo5": ("A1 + C2 => 8 pts", 8),
"combo6": ("D1 + B2 => 8 pts", 8),
}
for combo in combo_info:
qty = result[combo]
if qty > 0:
desc, pts = combo_info[combo]
total_pts = pts * qty
print(f" {combo} x{int(qty)}: {desc}, total {total_pts} pts")
print("\nSingle-resource conversions (and their scoring):")
print(" 10 of the same resource = 30 pts")
print(" 4 of the same resource = 10 pts")
print(" 1 of the same resource = 1 pt")
for res in ["A", "B", "C", "D"]:
used_10 = int(result[f"{res}_10"]) if result[f"{res}_10"] else 0
used_4 = int(result[f"{res}_4"]) if result[f"{res}_4"] else 0
used_1 = int(result[f"{res}_1"]) if result[f"{res}_1"] else 0
if used_10 or used_4 or used_1:
score_10 = used_10 * 30
score_4 = used_4 * 10
score_1 = used_1 * 1
total_res_score = score_10 + score_4 + score_1
print(
f" {res}: 10-sets={used_10} (=>{score_10} pts), 4-sets={used_4} (=>{score_4} pts), singles={used_1} (=>{score_1} pts), total {total_res_score} pts"
)
results = maximize_score(17, 13, 16, 12)
print_solution(results)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment