CPLEX中定义为dvar flaot+的变量返回负值及OPL约束报错问题求助
savings Values in CPLEX OPL Let's break down what's going wrong here and fix the issue step by step.
Root Cause of the Problem
Looking at your constraint and variable setup, two key issues are causing the unexpected negative values and model infeasibility:
Constraint Logic Conflict
Your current constraint forsavingsis:forall(h in truck) sum(n in order) (x_[h,n])*fixed_cost- fixed_cost == savings[h];When a truck
hisn't assigned any orders (i.e.,sum(n in order) x[h,n] = 0), the left-hand side calculates to0*75 -75 = -75. But you definedsavingsasdvar int+(a non-negative integer variable). This creates a contradiction: the constraint demandssavings[h] = -75, which violates the variable's non-negative requirement. CPLEX returns the negative value because it prioritizes satisfying the equality constraint over the variable's type definition.Infeasibility When Adding Non-Negative Constraint
When you addedforall(h in truck) savings[h] >= 0;, the model becomes impossible to solve. For unused trucks, you’re now asking CPLEX to satisfy bothsavings[h] = -75(from your original constraint) andsavings[h] >= 0—a logical impossibility.
Also, note the possible typo: you defined x[truck, order] but referenced x_[h,n] in the constraint. Double-check that this matches in your actual code.
Solution: Fix the savings Constraint Logic
You want savings[h] to be 0 for unused trucks, and fixed_cost*(sum(x[h,n]) -1) for used trucks. Here are two clean ways to implement this:
Option 1: Use OPL's Conditional Expressions (Simplest)
OPL supports ternary operators to directly encode your desired logic:
int fixed_cost = 75; dvar int+ x[truck, order] in 0..1; dvar int+ savings[truck]; forall(h in truck) { // If the truck is used (has at least one order), calculate savings; else set to 0 savings[h] == (sum(n in order) x[h,n] >= 1) ? (sum(n in order) x[h,n]*fixed_cost - fixed_cost) : 0; }
Option 2: Use Linear Constraints (For Strict Linear Models)
If you need fully linear constraints (e.g., for compatibility with solvers that don’t support logical expressions), add a binary variable to track whether a truck is used:
int fixed_cost = 75; int num_orders = ...; // Replace with the total number of your orders dvar int+ x[truck, order] in 0..1; dvar int+ savings[truck]; dvar boolean used[truck]; // 1 = truck is used, 0 = unused // Link the `used` variable to order assignments forall(h in truck) { used[h] <= sum(n in order) x[h,n]; // If the truck has orders, it must be marked as used sum(n in order) x[h,n] <= used[h] * num_orders; // If unused, no orders can be assigned } // Calculate savings only for used trucks forall(h in truck) { savings[h] == (sum(n in order) x[h,n] * fixed_cost - fixed_cost) * used[h]; }
Why This Works
- For unused trucks,
used[h](or the conditional check) ensuressavings[h] = 0, matching your expected result. - For used trucks,
savings[h]uses your original calculation, which will be non-negative (sincesum(x[h,n]) >= 1impliessum*75 -75 >= 0).
After implementing either fix, your model should return the expected savings = [0, 75] without infeasibility issues.
内容的提问来源于stack exchange,提问作者FrT

