1 / 51

Constraint Programming con ILOG Solver

Constraint Programming con ILOG Solver. Modellare e risolvere problemi con CP. Michele Lombardi <michele.lombardi2@unibo.it>. Cosa ci aspetta. Di cosa parleremo. Modellazione e soluzione di problemi con CP Strumenti per modellare (variabili, vincoli) Problematiche di modellazione

julio
Download Presentation

Constraint Programming con ILOG Solver

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Constraint Programming con ILOG Solver Modellare e risolvere problemi con CP Michele Lombardi <michele.lombardi2@unibo.it>

  2. Cosa ci aspetta Di cosa parleremo... • Modellazione e soluzione di problemi con CP • Strumenti per modellare (variabili, vincoli) • Problematiche di modellazione • Ottimizzazione del modello e del metodo di soluzione • Risolutore: ILOG solver ...e come ne parleremo • Considereremo un unico esempio di riferiento... • ...e TANTE sue varianti ;-) • Ad ogni passo sarà introdotto qualcosa di nuovo... • ...e vi sarà proposto qualche esercizio

  3. Modellare un problema Modellare un problema con CP Introduzione a ILOG Concert & Solver

  4. Il nostro esempio Supponiamo di dover ottimizzare l’esecuzione di tasks su un sistema multiprocessore Siano: • T = {t0, t1, ..., tn-1} = insieme degli n tasks • P = {p0, p1, ..., pp-1} = insieme dei p processori • dur(ti) = durata del task i-mo • Ogni task esegue su un solo processore • Su ogni processore i task eseguono in sequenza • Il tempo totale di esecuzione non deve superare una deadline Obiettivo: usare il minimo numero di processori Modellare un problema

  5. t0 t1 t2 t3 t4 t0 t2 t3 p0 t1 t4 p1 p2 Semplice, no? • Come lo affrontiamo? • Vediamo che strumenti abbiamo a disposizione Modellare un problema

  6. Introduzione ad ILOG CP Che cosa è ILOG? • ILOG è una azienda francese • Produce strumenti per la gestione efficiente di processi di manageriali e per la soluzione di problemi di ottimizzazione A noi ci interessano questi In particolare: • Strumenti per modellare problemi • Strumenti per risolvere problemi Modellare un problema

  7. Linguaggio di Modellazione MILP Linguaggio di modellazione a vincoli AMPL Cplex Math Programming Solver Semi-automatic CP solver OPL CP Optimizer CP Solvers Solver Scheduler Dispatcher Concert ILOG CP API per modellazione Modellare un problema

  8. In pratica... • AMPL e OPL sono linguaggi per descrivere modelli • Concert è una libreria in C++ • Fornisce classi e funzioni per costruire modelli Per esempio: • class IloModel modello • class IloIntVar variabile intera • class IloNumVar variabile reale • class IloBoolVar variabile logica • class IloConstraintvincolo • ... • Solver è un risolutore (sempre in C++) che dato un modello (ex. costruito in concert) trova una soluzione Modellare un problema

  9. Allora da dove partiamo? Da carta e penna Modellare un problema

  10. Un primo modello One dimensional bin packing: • Variabili: • Vincoli: • Ogni task esegue su un solo processore • Il tempo totale di esecuzione non deve superare una deadline Modellare un problema

  11. Nel complesso: obiettivo: soggetto a: Formulato il modello su carta, possiamo “costruirlo” usando Concert Modellare un problema

  12. Struttura di un programma ILOG #include <ilconcert/ilomodel.h> #include <ilsolver/ilosolver.h> ILOSTLBEGIN int main(int argc, char** argv){ IloEnv env; IloModel model(env); <inizializzazione modello> <invocazione del solver> <output> } Per usare concert e solver MACRO: definisce il namespace std IloEnv: gestore della memoria, fa da contenitore per il modello Classe che rappresenta un modello Variabili e vincoli vengono “aggiunti” al modello Modellare un problema

  13. Costruzione del modello • Per inizializzare un modello innanzitutto vanno definite le sue variabili: IloIntVarArray Y(env, nproc, 0, 1); IloArray<IloIntVarArray> X(env, nproc); for(int i = 0; i < nproc; i++){ X[i] = IloIntVarArray(env, ntask, 0, 1); } Array di arrays • Parametri di IloIntVarArray: • IloEnv: gestore della memoria • IloInt: dimensione • IloInt: lower bound del dominio • IloInt: upper bound del dominio Array di variabili intere Modellare un problema

  14. Costruzione del modello • Poi vanno specificati i vincoli Costruisce una espressione vuota... ...che può essere estesa con i normali operatori aritmetici! for(int j = 0; j < ntask; j++){ IloIntExpr sum(env); for(int i = 0; i < nproc; i++){ sum += X[i][j]; } model.add(sum == 1); } I vincoli vanno aggiunti al modello (vengono aggiunte anche le variabili su cui sono definiti) L’operatore di confronto (“==“) tra espressioni restituisce un vincolo Modellare un problema

  15. Costruzione del modello for(int i = 0; i < nproc; i++){ IloIntExpr sum(env); for(int j = 0; j < ntask; j++){ sum += durations[j]*X[i][j]; } model.add(sum <= deadline*Y[i]); } Modellare un problema

  16. Costruzione del modello • In qualunque punto (dopo la definizione delle variabili) si può specificare una funzione obiettivo model.add(IloMinimize(env, IloSum(Y))); Un modo compatto per costruire una espressione di somma (Y è un array) Indica che la soluzione deve minimizzare l’espressione specificata Modellare un problema

  17. Utilizzo del solver Costruisce un solver (classe IloSolver) <inizializzazione del modello> IloSolver solver(env); solver.extract(model); solver.solve(); <output> Trova la soluzione ottima (se esiste) “estrae” il modello • Prima di iniziare la ricerca di una soluzione il modello deve essere convertito nel formato interno del solver • Questa operazione si chiama “estrazione” • Classi concert: Ilo... (ex IloIntVar) • Classi solver: Ilc... (ex. IlcIntVar) Modellare un problema

  18. Input & Output intntask = 10; intnproc = 6; int durations[] = {3, 4, 7, 2, 2, 8, 7, 10, 8, 9}; int deadline = 16; Number of fails : 9282 Number of choice points : 9312 ... Running time since creation : 0.2 Y[0]:0 Y[1]:0 Y[2]:1 Y[3]:1 Y[4]:1 Y[5]:1 Modellare un problema

  19. Stili di modellazione Modelli alternativi

  20. Un altro modello • CP ha un linguaggio di modellazione molto “ricco” (molti tipi di vincoli) • Questo permette di migliorare le performance adottando stili di modellazione differenti Esempio: Cambiamo le variabili! Solo una variabile per task IloIntVarArray Proc(env, ntask, 0, nproc-1); • Tra l’altro in questo modo ogni task esegue per forza su un solo processore Stili di modellazione

  21. Un altro modello Come definire i vincoli di deadline? METAVINCOLI • Un vincolo può essere utilizzato all’interno di una espressione: denota 1 se è vero, 0 se è falso for(int i = 0; i < ntask; i++){ IloIntExpr sum(env); for(int j = 0; j < ntask; j++){ sum += durations[j]*(Proc[j] == i); } model.add(sum <= deadline); } Stili di modellazione

  22. Un altro modello Cambia anche la funzione obiettivo: Il più alto indice di processore utilizzato model.add(IloMinimize(env, IloMax(Proc))); Il nuovo modello ha la stessa semantica (=> le stesse soluzioni), ma un numero minore di variabili e una diversa funzione obiettivo Stili di modellazione

  23. Output Number of fails : 425 Number of choice points : 432 ... Running time since creation : 0.03 Proc[0]:0 Proc[1]:0 Proc[2]:0 Proc[3]:0 Proc[4]:1 Proc[5]:2 Proc[6]:3 Proc[7]:1 Proc[8]:2 Proc[9]:3 Stili di modellazione

  24. Esercizio 1 (base2.cpp) • Cosa succede con i due modelli aumentando il numero di processori a 16? • Perché? Stili di modellazione

  25. Vincoli globali Utilizzo dei vincoli globali

  26. Perché i vincoli globali I vincoli globali modellano alcune sottostrutture particolarmente frequenti. Hanno diversi vantaggi: • modellazione più compatta • propagazione più efficace • (a volte) propagazione più efficiente Esempio: Gli ultimi ptask devono essere assegnati a processori diversi Vincoli globali

  27. Modello con vincoli binari • Modellando con vincoli “!=“: for (inti = ntask-nproc; i < ntask; i++){ for (int j = i+1; j < ntask; j++){ model.add(Proc[i] != Proc[j]); } } • Output: Number of fails : 44496 Number of choice points : 44505 ... Running time since creation : 1.5 Vincoli globali

  28. Modello con alldifferent • Alldifferent in ILOG IloAllDiff(IloEnv, IloIntVarArray) IloAllDiffCt IloDistributeCt IloSequenceCt IloAllMinDistanceCt IloPartitionCt IloAllNullIntersectCt IloEqUnionCt IloNotOverlapCt IloBoxCt IlcFilterLevelConstraint • Nel nostro caso: IloIntVarArray diff(env); for(int j = ntask-nproc; j < ntask; j++) diff.add(Proc[j]); model.add(IloAllDiff(env, diff)); IloExtendedLevel IloMediumLevel IloBasicLevel IloLowLevel IlcFilterLevel • ATTENZIONE! Dopo aver estratto il modello: solver.setDefaultFilterLevel(IloAllDiffCt, IloExtendedLevel); Vincoli globali

  29. Output Number of fails : 8 Number of choice points : 16 ... Running time since creation : 0 problem solved Proc[0]:0 Proc[1]:0 Proc[2]:0 Proc[3]:1 Proc[4]:0 Proc[5]:1 Proc[6]:2 Proc[7]:3 Proc[8]:4 Proc[9]:5 IMPORTANTE: ILOG Solver permette anche di definire nuovi vincoli, ma per il momento non ci interessa... Vincoli globali

  30. Esercizio 2 (base2.cpp) • Nuovo vincolo: non più di tre task per processore • SUGGERIMENTO: il vincolo gcc in ILOG è: IloDistribute(IloEnv, IloIntVarArray cards,IloIntArrayvals, IloIntVarArrayvars) • Ricordate che dopo l’estrazione va modificato l’algoritmo di filtering... solver.setDefaultFilterLevel(???, ???); Vincoli globali

  31. Strategie di ricerca Modificare la strategia di ricerca

  32. Search strategy CP permette l’impiego di diverse strategie di ricerca • Per esempio si può scegliere il criterio con cui scegliere la variabile su cui fare branching IloGenerate(IloEnv, IloIntVarArray, IloChooseIntIndex) IloChooseFirstUnboundIntIloChooseMaxMaxIntIloChooseMaxMinIntIloChooseMaxRegretMaxIloChooseMaxRegretMinIloChooseMaxSizeIntIloChooseMinMaxIntIloChooseMinMinIntIloChooseMinRegretMaxIloChooseMinRegretMinIloChooseMinSizeInt E’ un IloGoal, va passato come argomento di solver.solve(...) First Fail Principle Strategie di ricerca

  33. Output solver.solve(IloGenerate(env, Proc, IloChooseMinSizeInt)) Number of fails : 71 Number of choice points : 77 ... Running time since creation : 0.01 IMPORTANTE: ILOG Solver permette anche di definire nuove strategie o di intervenire sulla ricerca in modo ancora più complesso, ma per il momento non ci interessa... Search stratgies

  34. Esercizio 3 (base.cpp, base2.cpp) • Cosa succede con altre strategie di ricerca? • Cosa succede utilizzando il first fail principle (IloChooseMinSizeInt) nel primo modello? Perché? Search stratgies

  35. Simmetrie Eliminazione delle simmetrie

  36. Simmetrie I processori sono risorse simmetriche; per esempio le due allocazioni: Proc[0]:0 Proc[1]:0 Proc[2]:0 Proc[3]:0 Proc[4]:1 Proc[5]:2 Proc[6]:3 Proc[7]:1 Proc[8]:2 Proc[9]:3 Proc[0]:1 Proc[1]:1 Proc[2]:1 Proc[3]:1 Proc[4]:0 Proc[5]:2 Proc[6]:3 Proc[7]:0 Proc[8]:2 Proc[9]:3 e Sono del tutto equivalenti! Simmetrie

  37. Simmetrie Una soluzione è quella di forzare un ordine di preferenza tra i processori: se p0 è libero non utilizzare uno dei processori seguenti • Si possono aggiungere dei vincoli per vietare le allocazioni che non rispetterebbero il criterio • Per ogni processore teniamo traccia del task di indice più basso allocato su di esso (dopo vedremo come) IloIntVarArrayminItem(env, nproc, 0, ntask-1); • Il task di indice più basso su p0 deve essere minore di quello su p1, e così via for(inti = 0; i < nproc-1; i++){ model.add(minItem[i] < minItem[i+1]); } Simmetrie

  38. Simmetrie Come ottenere minItem? model.add(minItem(Proc[0]) == 0); for(inti = 1; i < ntask; i++){ IloConstraintxpr = Proc[i] != Proc[i-1]; for(int j = i-2; j >= 0; j--){ xpr = xpr && (Proc[i] != Proc[j]); } model.add(IloIfThen(env, xpr, minItem(Proc[i]) == i)); } Element constraint in ILOG METAVINCOLI: i vincoli possono essere combinati in espressioni logiche! Simmetrie

  39. Output Number of fails : 84 Number of choice points : 92 ... Running time since creation : 0.01 Proc[0]:0 Proc[1]:0 Proc[2]:0 Proc[3]:0 Proc[4]:1 Proc[5]:2 Proc[6]:3 Proc[7]:1 Proc[8]:2 Proc[9]:3 Simmetrie

  40. Scheduling con ILOG Introduzione ad ILOG Scheduler

  41. ILOG Scheduler • Un’altra libreria in C++ • Fornisce strumenti per modellare e risolvere problemi di scheduling • Si appoggia al Solver per la soluzione del problema • La classe IlcScheduler permette di accedere alla soluzione Alcuni concetti chiave: • Attività • Vincoli temporali • Risorse • ... Scheduling con ILOG

  42. Attività Definite con: IloActivity(env, IloInt duration); IloActivity(env, IloNumVar duration); Una attività introduce tre variabili: START, END, DUR • END = START + DUR IloArray<IloActivity> acts(env, ntask); for(inti = 0; i < ntask; i++){ acts[i] = IloActivity(env, durations[i]); } Scheduling con ILOG

  43. Vincoli temporali IloActivity::startsAfterEnd(IloActivity); IloActivity::startsAfterStart(IloActivity); ... ...Restituiscono vincoli che forzano relazioni di precedenza IloActivity::startsBefore(...); IloActivity::startsAfter(...); ... ...Restituiscono vincoli temporali rispetto ad istanti fissati (o a variabili intere) for(inti = 0; i < nprec; i++){ model.add(acts[precTo[i]].startsAfterEnd(acts[precFrom[i]])); } Scheduling con ILOG

  44. Risorse Per ora consideriamo solo risorse unarie: IloUnaryResource(IloEnv) • Il metodo IloActivity::requires(...) restituisce un vincolo che va aggiunto al modello IloArray<IloUnaryResource> pres(env, nproc); for(inti = 0; i < nproc; i++) pres[i] = IloUnaryResource(env); for(inti = 0; i < nproc; i++){ for(int j = 0; j < ntask; j++){ model.add(IloIfThen(env, Proc[j] == i, acts[j].requires(pres[i]))); } } Scheduling con ILOG

  45. Input & Output intnprec = 5; intprecFrom[] = {0, 0, 4, 6, 3}; intprecTo[] = {1, 2, 5, 5, 8}; Goal: IloGenerate(env, Proc, ...) && IloSetTimesForward(env) Proc[0]:0 task[0]: [0 -- 3 --> 3] Proc[1]:0 task[1]: [3 -- 4 --> 7] Proc[2]:1 task[2]: [9 -- 7 --> 16] Proc[3]:2 task[3]: [2 -- 2 --> 4] Proc[4]:2 task[4]: [0 -- 2 --> 2] Proc[5]:0 task[5]: [7 -- 8 --> 15] Proc[6]:3 task[6]: [0 -- 7 --> 7] Proc[7]:2 task[7]: [4 -- 10 --> 14] Proc[8]:3 task[8]: [7 -- 8 --> 15] Proc[9]:1 task[9]: [0 -- 9 --> 9] Scheduling con ILOG

  46. Esercizio 4 (sched.cpp) • Cosa succede modificando il livello di propagazione? IloSchedulerEnvschedEnv(env); schedEnv.getResourceParam().setCapacityEnforcement(...); Notate cheIloExtendedabilita edge finder • Nuovo vincolo: i task 0, 3, 6, 9 devono accedere ad una memoria a due vie Risorsa a capacitàmaggioredi 1: IloDiscreteResource Scheduling con ILOG

  47. Minimizzare il tempo di esecuzione Introduciamounanuovavariabile (makespan): IloIntVarmakespan(env); Tutte le attivitàdevonoterminare prima del tempo diesecuzione: for(inti = 0; i < ntask; i++) model.add(acts[i].endsBefore(makespan)); Nuovoobiettivo: model.add(IloMinimize(env, makespan)); Goal ottimizzato: IloGenerate(env, Proc, ...) && IloSetTimesForward(env, makespan) Scheduling con ILOG

  48. Output Proc[0]:0 task[0]: [0 -- 3 --> 3] Proc[1]:0 task[1]: [10 -- 4 --> 14] Proc[2]:0 task[2]: [3 -- 7 --> 10] Proc[3]:1 task[3]: [2 -- 2 --> 4] Proc[4]:1 task[4]: [0 -- 2 --> 2] Proc[5]:1 task[5]: [7 -- 8 --> 15] Proc[6]:2 task[6]: [0 -- 7 --> 7] Proc[7]:3 task[7]: [0 -- 10 --> 10] Proc[8]:2 task[8]: [7 -- 8 --> 15] Proc[9]:4 task[9]: [0 -- 9 --> 9] Scheduling con ILOG

  49. Esercizio 5 (schedMK.cpp) • Cosa succede usando il goal IloSetTimesFOrward non ottimizzato? • Cosa succede eliminando le relazioni di precedenza? Scheduling con ILOG

  50. Basta teoria ;-) Adesso mettiamo le mani in pasta

More Related