Julia JuMP变量数组索引报错求解:排列优化场景
Ah, I’ve run into this exact headache when working with permutation problems in JuMP! The core issue here is that JuMP’s VariableRef objects (the variables you declare with @variable) aren’t concrete integer values—they’re symbolic placeholders for the values the solver will compute later. You can’t use them to index into an array like a[b[1]] because the solver has no idea what b[1] will be while you’re building the model.
Here’s how to fix this by modeling the permutation with binary assignment variables, which is the standard approach for these problems:
Step 1: Replace the permutation variable with binary assignment variables
Instead of trying to declare b directly as a permutation, define a binary matrix x where x[i,j] = 1 means the i-th position in your permutation uses the j-th element of a (i.e., b[i] = j). This lets us translate permutation logic into linear constraints that JuMP understands.
Step 2: Add permutation constraints
We need two sets of constraints to enforce that x represents a valid permutation:
- Each position in the permutation selects exactly one element: for every
i,sum(x[i,j] for j in 1:n) = 1 - Each element is used exactly once across all positions: for every
j,sum(x[i,j] for i in 1:n) = 1
Step 3: Rewrite your objective/constraints using x
Any expression that would have used a[b[i]] can be rewritten as sum(a[j] * x[i,j] for j in 1:n). When x[i,j] = 1, this sum picks out exactly a[j]—which is exactly what a[b[i]] would be if b[i] = j.
Full Example Code
Let’s say we want to maximize the sum of the permuted elements (adjust the objective to fit your specific problem):
using JuMP, GLPK # Swap GLPK for your preferred solver (e.g., Gurobi, CPLEX) function optimize_permutation(a::Vector{<:Real}) n = length(a) model = Model(GLPK.Optimizer) # Binary variable: x[i,j] = 1 if permutation position i uses element j of a @variable(model, x[1:n, 1:n], Bin) # Enforce permutation rules # Each position has exactly one element @constraint(model, [i in 1:n], sum(x[i,j] for j in 1:n) == 1) # Each element is used exactly once @constraint(model, [j in 1:n], sum(x[i,j] for i in 1:n) == 1) # Rewrite objective: replace a[b[i]] with sum(a[j] * x[i,j]) # Example: maximize the total sum of the permuted array @objective(model, Max, sum(a[j] * x[i,j] for i in 1:n for j in 1:n)) # Solve the model optimize!(model) # Recover the permutation b from the solved x variables b = zeros(Int, n) for i in 1:n for j in 1:n if value(x[i,j]) ≈ 1.0 # Account for floating point precision b[i] = j break end end end return b, objective_value(model) end # Test with a sample array a = [3, 1, 4, 2] optimal_b, obj_val = optimize_permutation(a) println("Optimal permutation: ", optimal_b) println("Objective value: ", obj_val)
Notes for More Complex Goals
If your problem involves more complex logic (like minimizing the difference between adjacent permuted elements), you can extend this approach:
- For an expression like
abs(a[b[i+1]] - a[b[i]]), rewrite it assum(abs(a[k] - a[j]) * x[i,j] * x[i+1,k] for j in 1:n for k in 1:n) - If you need to linearize absolute values or product terms, you can add auxiliary variables and constraints (standard MIP linearization techniques apply)
Alternative: All-Different Constraints
Some solvers support direct "all-different" constraints for integer variables, which let you declare b as an integer array with @constraint(model, all_different(b)). However, binary assignment variables are more universally supported across solvers and often more efficient for larger n.
内容的提问来源于stack exchange,提问作者jakub1998

