基于CP的灵活作业车间OR类型机器同机约束编码实现问询
Hey there! Let's work through fixing that OR machine constraint you're struggling with. First, let's restate the requirement to make sure we're on the same page:
For any job, if Operation 1 is processed on an OR-type machine, then any subsequent operation (Operation 2 or 3) in that job that also chooses an OR-type machine must use the exact same OR machine as Operation 1.
What Was Wrong With the Original Code?
Your original approach had a few key issues:
- No check for active modes: You were comparing machine IDs regardless of whether the mode (specific machine assignment) was actually selected for the operation. Since
modesare optional variables, we only care about constraints when a mode is active. - Redundant and over-broad logic: The multiple nested
forallloops were creating unnecessary constraints and didn't properly target the "if Op1 uses OR, then Op2/Op3 must match if they also use OR" logic. - Hardcoded operation ID assumptions: While your opID calculation might work, relying on
1+(j-1)*3is less robust than targeting operations by their position in the job.
Corrected Constraint Implementation
Replace your problematic constraint block with this code. It focuses on the core logic and uses presenceOf() to only apply constraints when a mode is actually selected:
// Correct implementation of the OR machine constraint forall(j in Jobs) { // Get the three operations for job j using their position in the job let o1 = first(o in Ops where o.jobId == j && o.pos == 1); let o2 = first(o in Ops where o.jobId == j && o.pos == 2); let o3 = first(o in Ops where o.jobId == j && o.pos == 3); // If Operation 1 uses an OR machine (mode m1 is active), then any OR mode chosen for Operation 2 must match m1's machine forall(m1 in Modes where m1.opId == o1.id && m1.mch in OR) { presenceOf(modes[m1]) => forall(m2 in Modes where m2.opId == o2.id && m2.mch in OR) { presenceOf(modes[m2]) => (m2.mch == m1.mch); } } // If Operation 1 uses an OR machine (mode m1 is active), then any OR mode chosen for Operation 3 must match m1's machine forall(m1 in Modes where m1.opId == o1.id && m1.mch in OR) { presenceOf(modes[m1]) => forall(m3 in Modes where m3.opId == o3.id && m3.mch in OR) { presenceOf(modes[m3]) => (m3.mch == m1.mch); } } }
How This Works
Let's break down the logic:
- Target operations by position: Using
first(o in Ops where o.jobId == j && o.pos == X)ensures we always get the correct operation for each job, regardless of how youropIdvalues are assigned. - Check active modes:
presenceOf(modes[m1])returns 1 if the modem1is selected for Operation 1. We only apply the subsequent constraint when this is true. - Conditional matching: For each OR mode of Operation 2/3, we say: if this mode is selected (i.e., the operation uses an OR machine), then its machine must match the OR machine used by Operation 1.
Optional: If You Prefer Using OpID Calculations
If you're confident your operation IDs follow the pattern 1+(j-1)*3 (Op1), 2+(j-1)*3 (Op2), j*3 (Op3), you can replace the let statements with hardcoded opID checks instead:
forall(j in Jobs) { int op1Id = 1 + (j-1)*3; int op2Id = 2 + (j-1)*3; int op3Id = j*3; // Rest of the constraint logic remains the same, using op1Id, op2Id, op3Id instead of o1.id, o2.id, o3.id forall(m1 in Modes where m1.opId == op1Id && m1.mch in OR) { presenceOf(modes[m1]) => forall(m2 in Modes where m2.opId == op2Id && m2.mch in OR) { presenceOf(modes[m2]) => (m2.mch == m1.mch); } } forall(m1 in Modes where m1.opId == op1Id && m1.mch in OR) { presenceOf(modes[m1]) => forall(m3 in Modes where m3.opId == op3Id && m3.mch in OR) { presenceOf(modes[m3]) => (m3.mch == m1.mch); } } }
This should correctly enforce your desired constraint without the issues from the original code.
内容的提问来源于stack exchange,提问作者Alex

