Как кодировать в гибкой мастерской, что преемник операции выполняется на той же машине? - PullRequest
1 голос
/ 19 апреля 2019

В модели у нас есть 3 операции, которые должны быть выполнены для каждой работы.Я хотел бы, чтобы, если операция 1 обрабатывается на машине типа OR, операция 2 и операция 3 также должны выполняться на той же машине типа OR, если они выполняются на машине типа OR.

using CP;   
int nbJobs = ...;  
int nbMchs = ...;  
int nbOR=...;     //special machine type OR  
int nbIR=...;     //special machine type IR  
int nbSR=...;     //special machine type SR   

range Jobs = 1..nbJobs;  
range Mchs = 1..nbMchs;   
range OR  =1..nbOR;  
range IR = nbOR+1..(nbOR+nbIR);  
range SR=(nbOR+nbIR+1)..(nbOR+nbIR+nbSR);  

tuple Operation {  
int id;    // Operation id  
int jobId; // Job id  
int pos;   // Position in the Job  
};  

tuple Mode {  
int opId; // Operation id  
int mch;  // Machine  
int pt;   // Processing time  
};  
{Operation} Ops=...;  
{Mode}  Modes=...;  

execute {  
    cp.param.FailLimit = 10000;  
}  
// Position of last operation of job j  
int jlast[j in Jobs] = max(o in Ops: o.jobId==j) o.pos;  

dvar interval ops[Ops];   
dvar interval modes[md in Modes] optional size md.pt;  
dvar sequence mchs[m in Mchs] in 
     all(md in Modes: md.mch == m) modes[md];  


minimize 
   max(j in Jobs, o in Ops: o.pos==jlast[j]) endOf(ops[o]);  

subject to {  

    forall (j in Jobs, o1 in Ops, o2 in Ops: 
            o1.jobId==j && o2.jobId==j && o1.pos==2 && o2.pos==3)  
        endAtStart(ops[o1],ops[o2]);  

    forall (j in Jobs, o3 in Ops, o4 in Ops, o5 in Ops: 
            o3.jobId==j && o4.jobId==j && o5.jobId==j && 
            o3.pos==1 && o4.pos==2 && o5.pos==3) {  
        (endOf(ops[o3]) != startOf(ops[o4])) =>
            (endOf(ops[o3]) == startOf(ops[o5]));  
        (endOf(ops[o3]) != startOf(ops[o5])) =>
            (endOf(ops[o3]) == startOf(ops[o4]));    
    }     

    // How to code the following in a correct way?
    // From here...

    forall (j in Jobs, k in OR, l in OR,  m1 in Modes, m2 in Modes:    
            m1.opId == 1+(j-1)*3 && m2.opId == j*3) {  
        if (m1.mch == k && m2.mch == l){  
            m1.mch == m2.mch;  
        }  
    }    

    forall (j in Jobs, k in OR, l in OR, m1 in Modes, m2 in Modes:               
            m1.opId == 2+(j-1)*3 && m2.opId == j*3 && 
            m1.mch == k && m2.mch == l) {  
        if (m1.mch == k && m2.mch == l) {  
            m1.mch == m2.mch;  
        }    
    }   

    forall (j in Jobs, k in OR, l in OR, m in OR, m1 in Modes, 
            m2 in Modes, m3 in Modes: 
            m1.opId == 1+(j-1)*3 && m2.opId == 2+(j-1)*3 &&
            m3.opId == j*3 && m1.mch == k && m2.mch == l && m3.mch == m) {  
        if (m1.mch == k && m2.mch == l && m3.mch == m) {        
            m1.mch == m2.mch == m3.mch;
        }  
    }  

    // ... to here    

    forall (o in Ops)  
        alternative(ops[o], all(md in Modes: md.opId==o.id) modes[md]);  
    forall (m in Mchs)  
        noOverlap(mchs[m]);  

}

1 Ответ

1 голос
/ 23 апреля 2019

Я думаю, что все, что вам нужно сделать, это опубликовать некоторые двоичные ограничения между наличием интервальных переменных. Что-то вроде: presenceOf(mode1) => !presenceOf(mode2), где mode1 - это присвоение операции 1 на машине типа OR, а mode2 - это присвоение операции 2 на машине типа OR, отличной от операции mode1. Это то, что вы хотите: запретить выделение операции 2 (то же самое с операцией 3) на машине типа OR, за исключением операции 1.

...