caricato da Utente1624

Ricerca Operativa (appunti)

annuncio pubblicitario
Lezione 1 – 06/03/2019
Abbiamo un sacco di numeri interi e possiamo confrontarli. Possiamo immaginare di avere una bilancia, che
pesa due numeri, e possiamo chiedere quale dei due pesa di più. Chiaramente stiamo pensando a un insieme
totalmente ordinato, come posso trovare il MASSIMO?
Per spezzare il problema e renderlo più piccolo, ho pensato che ho n pesi, allora posso pensare di prendere
dei valori precisi per n e testare:
-
Se n = 3, ho tre pesi A, B, C, con una bilancia a bracci uguali prendo A e B e li confronto, uno dei due
sarà più pesante, e quello lo confronto con C. n = 3 mi dà un numero di pesate pari a 2.
Se n = 2, basta una sola pesata.
Se n = 1, trovare il più pesante è inutile, quindi non faccio pesate.
Quindi ci conviene aumentare n. Per n generico cerco di fare un confronto a coppie e “butto via” quello che
perde. Quante pesate finisco a fare in questo modo, facendo delle coppie disgiunte?
Numero oggetti
1
2
3
Pesate
0
1
2
Arriviamo all’INDUZIONE MATEMATICA, ovvero quando sono nel caso n = 3, io confronto prima una coppia
e quindi faccio 1 pesata, e poi mi riconduco al caso precedente n = 2, da cui avrò 1+1 = 2 e corrisponde a
quando visto per il caso n = 3.
Legge di Church-Turing: tutto ciò che è computabile è ricorsivo.
Ora facciamo delle CONGETTURE. Voglio convincermi che il processo termina, come termina e le quantità in
gioco. Ora n1 = 7, facendo 3 coppie abbiamo n2 = 4. Il processo consuma oggetti, dato che parto con un
numero finito di oggetti, c’è una monovariante, perché ogni volta il numero di oggetti cala, quindi ho un certo
controllo. Quindi questo mi dice che il mio processo termina. Riusciamo a stabilire quante sono le pesate che
faccio? La congettura è che siano n-1, e mi piace perché sembra vicino al vero. Quindi l’algoritmo termina,
l’abbiamo analizzato non solo dal punto di vista che termina, ma anche dal punto di vista delle risorse che
impiega.
Come posso dimostrarlo in generale? Ho n oggetti, se n>1 posso trasformare l’istanza e darla alla Fatina
Ricorsina, e l’unico modo che ho per modificare questa istanza è l’uso della bilancia. Quindi di questi oggetti
ne prendo 2, e l’Oracolo mi dice quale pesa di più. Quello che pesa meno è fuori dai giochi, quindi per qualsiasi
schema di pesature per risolvere il problema, non metterà più sulla bilancia l’oggetto che pesa meno.
No anzi adesso la prende un po’ più lunga e introduce i grafi, e li usa come modelli per rappresentare dei
problemi, per semplificare la situazione. Supponiamo di avere 4 oggetti e li vedo come nodi di un grafo e
quando faccio una pesata ci metto l’arco.
1
2
3
4
Posso codificare di più in questo grafo? Sì, anche l’esito. Perché se oggetto 2 > oggetto 1, posso mettere una
freccia che va da 2 a 1. Voglio sapere quale può essere il numero di archi, perché corrisponde al numero di
pesate che io faccio. Cerchiamo di chiederci com’è fatto questo grafo, che quando termina mi dice qual è il
massimo.
1
2
3
4
Un grafo fatto come quello sopra può essere uno di quelli che mi trova il massimo? Non contiene cicli grap,
sarà un DIGRAFO ACICLICO. A un certo punto le mie pesate mi devono bastare per capire quale sia la biglia
più pesante. Se ho un grafo aciclio tutto in avanti, mi direbbe che la biglia più grande è quella su cui arrivano
tante frecce, ce la faccio anche con pochi archi, solo con tre ce la faccio a convincermi che c’è un massimo.
Passiamo da calcolare la soluzione al problema a certificarla, ovvero a dire che ci posso arrivare. La teoria
della complessità ci ha restituito l’importanza dei certificati.
1
2
3
4
Per trovare il “certificato” che il mio grafo mi porta al massimo ma con il numero più basso possibile di archi,
considerando la figura sopra, è cambiarlo nel modo seguente:
1
2
3
4
Cioè vale a dire che faccio confronto 1-2 e 3-4 e poi confronto i vincitori. Questo digrafo basta a convincermi
che trovo il massimo. È necessario avere 3 archi o c’è un digrafo con meno archi che mi può convincere?
Abbiamo un DAG e qui noi vogliamo che ci sia un unico pozzo, e ci deve essere un arco che esce, cioè che ha
perso con qualcuno, che può a sua volta aver perso con qualcuno. Finché non arrivi all’unico pozzo, che è
l’unico elemento massimo. Se invece il pozzo non è unico, ci son tipo due che non hanno mai perso, non
posso applicare la proprietà transitiva. Il minimo numero di archi perché abbia un unico pozzo è quello che
devo trovare, è vero che ne devo usare n-1, da ogni nodo ne deve uscire uno. È vero che ogni arco ha due
estremi, ma ogni arco esce da al più un nodo. Tutti gli n-1 nodi non pozzi possono avere ciascuno un arco che
esce, quindi ne servono davvero almeno n-1.
Il digrafo mi rappresenta una generica relazione, cioè è un sottoinsieme delle coppie di un prodotto
cartesiano. Una generica relazione è un grafo diretto bipartito, le relazioni sono l’oggetto base. I grafi ci danno
modo di lavorare in modo grafico e di visualizzare relazioni.
Torniamo al problema di prima (ultimo disegno sopra). Questo DAG non è il primo che mi viene in mente per
dire che 4 è il massimo, perché 1  2  3  4, sarebbe più naturale, e troverei sia il più grande sia il più
piccolo, questo ordinamento mi permette di trovare anche l’i-esimo. Da qui posso ottenere un argomento
più semplice? L’ordinamento in questo modo degli oggetti non ce la si fa con le pesate, un tale algoritmo può
non essere così semplice. Per trovare il massimo un metodo un po’ più strutturato è che gli oggetti siano in
fila (non necessariamente di peso), confronto i primi due e quello che perde esce di scena. Confronto il next
con il vincitore e tengo il vincitore tra i due, e ripeto questo procedimento fino alla fine, questo mi trova il
max con n-1 confronti. Io voglio un algoritmo che trovi il massimo su n numeri: ne prendo 2, li confronto,
quello che perde lo butto via e chiedo alla fatina ricorsina di trovarmi il massimo di questi altri. La fatina
ricorsina usa n-2 confronti più quello che ho fatto io mi torna n-1.
Codice python per la ricerca del massimo:
def find_max(lista):
presunto_max = lista[0]
for val in lista[1:]
if val > presunto_max
presunto_max = val
return presunto_max
Come faccio a prevedere se e come termina l’algoritmo? Non posso prevederlo perché l’unico modo che una
macchina ha per prevedere l’andamento è simularlo. Con questo algoritmo la lista si consuma quindi
sicuramente termina, ma quello che io devo dire è che termina e ritorna il massimo. Se l’if non scatta, il
presunto_max sta nella lista, se scatta il presunto_max cambia e poi sta nella lista. Se l’if non scatta
mai, l’unico modo perché quello che mi ritorna sia nella lista e di impostare come valore iniziale di
presunto_max il primo elemento della lista. L’invariante di ciclo in questo algoritmo è data da
presunto_max, perché è quello che mi aiuta a chiudere il mio ciclo, cioè ad ogni giro del ciclo trovo il
migliore è quello che mi dice se devo continuare a fare confronti.
Scarica