Scaricare la presentazione
La presentazione è in caricamento. Aspetta per favore
1
Constraint Programming con ILOG Solver
Modellare e risolvere problemi con CP Michele Lombardi
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 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
Vediamo che strumenti abbiamo a disposizione
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 Concert Solver Scheduler Dispatcher 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 IloConstraint vincolo ... 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
Formulato il modello su carta, possiamo “costruirlo” usando Concert
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 Modellare un problema int ntask = 10; int nproc = 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 Stili di modellazione 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
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 p task devono essere assegnati a processori diversi Vincoli globali
27
Modello con vincoli binari
Modellando con vincoli “!=“: for (int i = 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
solver.setDefaultFilterLevel(???, ???);
Esercizio 2 (base2.cpp) Nuovo vincolo: non più di tre task per processore SUGGERIMENTO: il vincolo gcc in ILOG è: IloDistribute(IloEnv, IloIntVarArray cards, IloIntArray vals, IloIntVarArray vars) Ricordate che dopo l’estrazione va modificato l’algoritmo di filtering... solver.setDefaultFilterLevel(???, ???); Vincoli globali
31
Modificare la strategia di ricerca
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) IloChooseFirstUnboundInt IloChooseMaxMaxInt IloChooseMaxMinInt IloChooseMaxRegretMax IloChooseMaxRegretMin IloChooseMaxSizeInt IloChooseMinMaxInt IloChooseMinMinInt IloChooseMinRegretMax IloChooseMinRegretMin IloChooseMinSizeInt 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
Eliminazione delle simmetrie
36
Sono del tutto equivalenti!
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) IloIntVarArray minItem(env, nproc, 0, ntask-1); Il task di indice più basso su p0 deve essere minore di quello su p1, e così via for(int i = 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(int i = 1; i < ntask; i++){ IloConstraint xpr = 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 Simmetrie 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
Introduzione ad ILOG Scheduler
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(int i = 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(int i = 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(int i = 0; i < nproc; i++) pres[i] = IloUnaryResource(env); for(int i = 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 int nprec = 5; int precFrom[] = {0, 0, 4, 6, 3}; int precTo[] = {1, 2, 5, 5, 8}; Goal: IloGenerate(env, Proc, ...) && IloSetTimesForward(env) Proc[0]:0 task[0]: [ > 3] Proc[1]:0 task[1]: [ > 7] Proc[2]:1 task[2]: [ > 16] Proc[3]:2 task[3]: [ > 4] Proc[4]:2 task[4]: [ > 2] Proc[5]:0 task[5]: [ > 15] Proc[6]:3 task[6]: [ > 7] Proc[7]:2 task[7]: [ > 14] Proc[8]:3 task[8]: [ > 15] Proc[9]:1 task[9]: [ > 9] Scheduling con ILOG
46
Esercizio 4 (sched.cpp) Cosa succede modificando il livello di propagazione? IloSchedulerEnv schedEnv(env); schedEnv.getResourceParam().setCapacityEnforcement(...); Notate che IloExtended abilita edge finder Nuovo vincolo: i task 0, 3, 6, 9 devono accedere ad una memoria a due vie Risorsa a capacità maggiore di 1: IloDiscreteResource Scheduling con ILOG
47
Minimizzare il tempo di esecuzione
Introduciamo una nuova variabile (makespan): IloIntVar makespan(env); Tutte le attività devono terminare prima del tempo di esecuzione: for(int i = 0; i < ntask; i++) model.add(acts[i].endsBefore(makespan)); Nuovo obiettivo: model.add(IloMinimize(env, makespan)); Goal ottimizzato: IloGenerate(env, Proc, ...) && IloSetTimesForward(env, makespan) Scheduling con ILOG
48
Output Scheduling con ILOG Proc[0]:0 task[0]: [0 -- 3 --> 3]
49
Esercizio 5 (schedMK.cpp)
Cosa succede usando il goal IloSetTimesFOrward non ottimizzato? Cosa succede eliminando le relazioni di precedenza? Scheduling con ILOG
50
Adesso mettiamo le mani in pasta
Basta teoria ;-) Adesso mettiamo le mani in pasta
51
Istruzioni BUON LAVORO! Fate login su windows
Dal sito del corso scaricate il template di progetto Aprite il file “template.sln” con visual studio 2005 Nel pacchetto con il template ci sono anche alcuni file sorgente, che contengono il codice di partenza: in ogni esercizio è specificato da quali sorgenti dovete partire per risolverlo Per lanciare gli eseguibili aprite un prompt dei comandi usando il file batch “START.bat”, sempre nel pacchetto con il template: serve per accedere alla licenza per l’uso di ILOG BUON LAVORO!
Presentazioni simili
© 2024 SlidePlayer.it Inc.
All rights reserved.