Created
December 9, 2024 04:46
-
-
Save LexSong/4dfb03b298511814517c54185e437a19 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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