如何在CPLEX Docplex MILP模型中编写适配任意n与A场景的约束#18代码?
Let's break down and fix your issue step by step:
Root Cause of the Error
The index 2 is out of bounds error happens because you're using range_A = range(len(A)) (the full length of your entire set A) to iterate over z_temp and c_temp, which only correspond to a single element in A. For example, when A contains [1,3], z_temp has a length of 2—but range_A for n=3 is range(4), so when i reaches 2 or 3, you're trying to access an index that doesn't exist in z_temp.
Solution Steps
1. Fix the Storage of Set A
Avoid using np.array for storing mixed scalars and lists (it creates an object-type array that's harder to work with). Use a standard Python list instead:
# n=3 A = [1,2,3,[1,3]] # n=4 A = [1,2,3,4,[1,3],[1,4],[2,4]] # Fixed [2,5] to [2,4] since n=4 # n=5 A = [1,2,3,4,5,[1,3],[1,4],[1,5],[2,4],[2,5],[3,5],[1,3,5]]
2. Rewrite Constraint #18 with Robust Logic
For each element in A, first normalize it to a list (whether it's a single step or a multi-step group), then iterate only over the length of that specific element. This eliminates index out-of-bounds issues and makes the code work for any n.
Here's the corrected constraint #18 code:
# constraint 18 - generalized version for item in A: # Convert single integers to a list for uniform processing idx_list = [item] if isinstance(item, int) else item # Validate step numbers to avoid future index errors for idx in idx_list: if idx > n: raise ValueError(f"Step {idx} in A exceeds total steps n={n}") # Get corresponding z variables and c values (convert 1-based to 0-based index) z_temp = [z[idx-1] for idx in idx_list] c_temp = [c[idx-1] for idx in idx_list] # Calculate sums specific to this element in A sum_z = sum(z_temp) sum_c_term = sum(2*w + v + ci for ci in c_temp) # Note: Double-check the (n + 1 - 2 * len(A)) term in your formula # For n=3, this gives 4 - 8 = -4, which likely doesn't make sense for a time value # You may want to replace this with (n + 1 - len(idx_list)) to use the size of the current group time_term = (n + 1 - 2 * len(A)) * (2*v + 2*w) + sum_c_term mdl.add_constraint(1 + sum_z >= y * time_term)
3. Full Corrected Code
import cplex from docplex.mp.model import Model import numpy as np mdl = Model(name='Marking Optimization') inf = cplex.infinity n = 3 # number of steps A = [1,2,3,[1,3]] # Use Python list instead of np.array p = np.array([40,100,60]) #processing time for PM1 (second) c = np.array([20,100,50]) v = 3 #robot moving time (second) w = 5 #loading or unloading time (second) m = np.array([1,2,1]) # y = 1/obj_lambda y = mdl.continuous_var(lb = 0, ub=inf, name='y') z = np.empty((n,), dtype= object) for i in range(n): z[i] = mdl.integer_var(lb = 0, ub=inf, name='z' + str(i + 1)) # constraint 15 mdl.add_constraint(1 >= y*(n+1)*(2*v + 2*w)) # constraint 16 for i in range(n): mdl.add_constraint(1 >= y*(1/m[i])*(p[i] + c[i] + 2*w)) # constraint 17 for i in range(n): mdl.add_constraint(m[i] - z[i] >= y*(p[i] + 3*v + 4*w)) #constraint 18 - corrected for item in A: idx_list = [item] if isinstance(item, int) else item for idx in idx_list: if idx > n: raise ValueError(f"Step {idx} in A exceeds total steps n={n}") z_temp = [z[idx-1] for idx in idx_list] c_temp = [c[idx-1] for idx in idx_list] sum_z = sum(z_temp) sum_c_term = sum(2*w + v + ci for ci in c_temp) time_term = (n + 1 - 2 * len(A)) * (2*v + 2*w) + sum_c_term mdl.add_constraint(1 + sum_z >= y * time_term) #constraint 19A for i in range(n): mdl.add_constraint(z[i] >= 0) #constraint 19B for i in range(n): mdl.add_constraint(z[i] <= m[i] -1) mdl.maximize(y) mdl.print_information() solver = mdl.solve() #(log_output=True) if solver is not None: mdl.print_solution() else: print("Solver error occurred") obj_lambda = 1/y.solution_value if solver else None
Key Notes
- The code now handles any valid n and corresponding set A, as long as all step numbers in A are ≤ n.
- I added a validation check to catch invalid step numbers in A before they cause index errors.
- Important: The term
(n + 1 - 2 * len(A))in your original formula produces negative values for your test cases (e.g., n=3 gives -4). This is likely a mistake—double-check your mathematical model to ensure this term correctly represents the intended logic (e.g., using the size of the current grouplen(idx_list)instead oflen(A)).
内容的提问来源于stack exchange,提问作者Nicholas Nicholas

