{"id":2136,"date":"-0001-11-30T00:00:00","date_gmt":"-0001-11-29T23:10:04","guid":{"rendered":""},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T22:00:00","slug":"2136","status":"publish","type":"post","link":"https:\/\/www.vialattea.net\/content\/2136\/","title":{"rendered":"A scrivere siamo degli studenti di un corso di Fondamenti di Informatica II e gradiremmo alcuni chiarimenti circa la teoria della complessit\u00e0 computazionale, che ha sollevato in noi parecchi dubbi e fraintendimenti:\r\n\r\n1) Per &#8220;complessit\u00e0 computazionale&#8221; si deve intendere\r\nuna &#8220;stima del numero di operazioni&#8221; che compongono un\r\nalgoritmo e\/o una &#8220;scienza che studia i criteri&#8221; di\r\nefficienza degli algoritmi?\r\n\r\n2) Se per &#8220;complessit\u00e0 computazionale&#8221; si accetta la\r\nseconda accezione, \u00e8 possibile parlare di &#8220;complessit\u00e0\r\ncomputazionale temporale&#8221; e &#8220;complessit\u00e0\r\ncomputazionale spaziale&#8221; come finalizzate\r\nall\u2019ottimizzazione di risorse rispettivamente\r\ntemporali e spaziali, oppure \u00e8 esatto parlare di\r\ncomplessit\u00e0 computazionale se riferita alla\r\nvalutazione del tempo e complessit\u00e0 spaziale quando\r\nriferita alla memoria ?\r\n\r\n3) Sono convinto di non aver ben capito a fondo quali\r\nsono le regole pratiche per il calcolo della\r\ncomplessit\u00e0 di un algoritmo e perch\u00e9 sono tali.\r\nAd esempio, un ciclo &#8220;for (int i=1; i<c, i++) {...}\"\r\nha una complessit\u00e0 che non dipende dal numero di\r\nreiterazioni del ciclo perch\u00e9 tale numero \u00e8 una\r\ncostante al variare della dimensione dell\u2019ingresso \u2018n\u2019\r\ne dunque dipende da altri fattori (ad esempio\r\ndall\u2019hardware).\r\n\r\n4) Se si determina una relazione tra la dimensione dei\r\ndati in ingresso ed il tempo impiegato\r\ndall\u2019elaborazione, tale stima sar\u00e0 del tutto inutile\r\nai fini della valutazione del tempo effettivo\r\nimpiegato da un elaboratore E operante in un ambiente\r\nX per completare l\u2019algortimo?"},"content":{"rendered":"<p><font face=\"Book Antiqua,Calisto MT\">La<br \/>\n        complessit\u00e0 computazionale di un algoritmo \u00e8 definita come l&#8217;ordine di<br \/>\n        grandezza della funzione che determina il numero di passi elementari da<br \/>\n        svolgere per eseguirlo, al crescere della dimensione dei dati di ingresso.<\/font><\/p>\n<p><font face=\"Book Antiqua,Calisto MT\">La <i>complessit\u00e0 computazionale<\/i>,<br \/>\n        in questo senso, \u00e8 quindi una misura di tempo astratta che ha,<br \/>\n        al pi\u00f9, una relazione di proporzionalit\u00e0 con il <i>tempo<br \/>\n        effettivo di esecuzione<\/i>.<\/font><\/p>\n<p><font face=\"Book Antiqua,Calisto MT\">Si parla anche di complessit\u00e0<br \/>\n        computazionale spaziale, intesa come dimensione della struttura dati necessaria<br \/>\n        a supportare l\u2019esecuzione di un algoritmo. Tuttavia, non si dovrebbe associare<br \/>\n        la complessit\u00e0 (computazionale) spaziale alla memoria e computazionale<br \/>\n        al tempo, poich\u00e9 in entrambi i casi si sta valutando <i>l\u2019ordine<br \/>\n        di grandezza<\/i> delle quantit\u00e0 associate (tempo e memoria).<\/font><\/p>\n<p><font face=\"Book Antiqua,Calisto MT\">L\u2019analisi della complessit\u00e0<br \/>\n        temporale di un algoritmo consente di determinare l\u2019ordine di grandezza<br \/>\n        del tempo necessario per eseguirlo senza nemmeno iniziare la computazione.<br \/>\n        Questo approccio ha dei vantaggi considerevoli, infatti \u00e8 possibile<br \/>\n        scrivere algoritmi che terminano in un numero considerevole di anni.<\/font><\/p>\n<p><font face=\"Book Antiqua,Calisto MT\">Si supponga di scrivere il seguente<br \/>\n        algoritmo ricorsivo per il calcolo del fattoriale:<\/font><\/p>\n<p><font face=\"Book Antiqua,Calisto MT\"><b>Algoritmo F1<\/b>:<\/font><\/p>\n<p><i><font face=\"Book Antiqua,Calisto MT\">if n = 0 then <\/font><\/i><\/p>\n<blockquote>\n<p><i><font face=\"Book Antiqua,Calisto MT\"> f = 1;<\/font><\/i><\/p>\n<\/blockquote>\n<p><i><font face=\"Book Antiqua,Calisto MT\">else<\/font><\/i><\/p>\n<blockquote>\n<p><i><font face=\"Book Antiqua,Calisto MT\">\tf = n*F1(n-1);<\/font><\/i><\/p>\n<\/blockquote>\n<p><font face=\"Book Antiqua,Calisto MT\">e si supponga di voler calcolare<br \/>\n        <i>F1(1000)<\/i> con un calcolatore in grado di fare un miliardo di iterazioni<br \/>\n        elementari (o <i>passi<\/i>) al secondo: occorrerebbero 2551 anni.<\/font><\/p>\n<p><font face=\"Book Antiqua,Calisto MT\">L\u2019analisi della complessit\u00e0<br \/>\n        dell\u2019algoritmo F1 consente, quindi, di non dover attendere il risultato<br \/>\n        fino al capodanno del 4550.<\/font><\/p>\n<p><font face=\"Book Antiqua,Calisto MT\">Le regole di valutazione della complessit\u00e0<br \/>\n        computazionale sono le seguenti:<\/font><\/p>\n<ul>\n<li><font face=\"Book Antiqua,Calisto MT\">Le istruzioni di assegnamento<br \/>\n          hanno complessit\u00e0 unitaria. <\/font><\/li>\n<li><font face=\"Book Antiqua,Calisto MT\">Le iterazioni di tipo <i>for<br \/>\n          i = 1 to n do c<\/i> hanno complessit\u00e0 <i>n<\/i> volte la complessit\u00e0<br \/>\n          del corpo dell\u2019iterazione <i>c<\/i>. <\/font><\/li>\n<li><font face=\"Book Antiqua,Calisto MT\">Se un algoritmo contiene istruzioni<br \/>\n          condizionali di tipo <i>if \u2026 then \u2026 else<\/i>, allora ha complessit\u00e0<br \/>\n          <i>minima, media <\/i>e <i>massima<\/i> pari al numero di passi <i>minimo<\/i>,<br \/>\n          <i>medio<\/i> e <i>massimo<\/i> necessari allo svolgimento delle istruzioni<br \/>\n          condizionali che lo compongono.<\/font><\/li>\n<\/ul>\n<p><font face=\"Book Antiqua,Calisto MT\">Con queste regole siamo in grado<br \/>\n        di valutare la complessit\u00e0 computazionale di un algoritmo al crescere<br \/>\n        della dimensione dei dati di ingresso.<\/font><\/p>\n<p><font face=\"Book Antiqua,Calisto MT\">Si consideri ora l\u2019algoritmo per<br \/>\n        il calcolo del fattoriale che segue:<\/font><\/p>\n<p><font face=\"Book Antiqua,Calisto MT\"><b>Algoritmo F2<\/b>:<\/font><\/p>\n<p><i><font face=\"Book Antiqua,Calisto MT\">f = 1;<\/font><\/i><\/p>\n<p><i><font face=\"Book Antiqua,Calisto MT\">if n &gt; 1 then<\/font><\/i><\/p>\n<blockquote>\n<p><i><font face=\"Book Antiqua,Calisto MT\">for i = 1 to n do f = f * i;<\/font><\/i><\/p>\n<\/blockquote>\n<p><font face=\"Book Antiqua,Calisto MT\">Ora, applicando le regole di calcolo<br \/>\n        della complessit\u00e0 computazionale esposte, si valuti la complessit\u00e0<br \/>\n        degli algoritmi F1 ed F2. <\/font><\/p>\n<p><font face=\"Book Antiqua,Calisto MT\">Si scopre che F1 ed F2 impiegano<br \/>\n        rispettivamente <i>n!<\/i> e <i>n+1 <\/i>passi. Il calcolatore di cui sopra<br \/>\n        eseguirebbe, quindi, <i>F2(1000)<\/i> in un milionesimo di secondo circa.<br \/>\n        L\u2019analisi della complessit\u00e0 rivela che l\u2019algoritmo F2 \u00e8<br \/>\n        nettamente pi\u00f9 efficiente di F1.<\/font><\/p>\n<p><font face=\"Book Antiqua,Calisto MT\">Ma, ai fini della valutazione dell\u2019efficienza,<br \/>\n        ci\u00f2 che interessa \u00e8 l\u2019ordine di grandezza delle funzioni<br \/>\n        che determinano il numero di passi al crescere di <i>n<\/i> o, in termini<br \/>\n        formali, <i>l\u2019ordine di infinito<\/i> di queste funzioni.<\/font><\/p>\n<p><font face=\"Book Antiqua,Calisto MT\">Ricordiamo che una funzione ha lo<br \/>\n        stesso ordine di infinito x<i><sup>n<\/sup><\/i> se e solo se <img loading=\"lazy\" decoding=\"async\" width=\"93\" height=\"41\" align=\"absmiddle\" src=\"..\/..\/esperti\/inform\/complessita\/Image33.gif\" alt=\"\"\/>,<br \/>\n        per <i>c &gt; 0<\/i> constante. Questa propriet\u00e0 si indica affermando<br \/>\n        che <i>&#8220;f(x) <\/i>\u00e8 <i>O(x<sup>n<\/sup>)<\/i>&#8220;<\/font><\/p>\n<p><font face=\"Book Antiqua,Calisto MT\">Valutando l\u2019ordine di infinito delle<br \/>\n        funzioni che determinano il numero di passi necessari a svolgere un algoritmo<br \/>\n        siamo in grado di determinare due cose:<\/font><\/p>\n<ol>\n<li><font face=\"Book Antiqua,Calisto MT\">un criterio di efficienza degli<br \/>\n          algoritmi<\/font><\/li>\n<li><font face=\"Book Antiqua,Calisto MT\">delle classi di computabilit\u00e0<br \/>\n          di algoritmi<\/font><\/li>\n<\/ol>\n<p><font face=\"Book Antiqua,Calisto MT\">Siano <i>f1(n) <\/i>ed <i>f2(n)<\/i><br \/>\n        due funzioni di valutazione di complessit\u00e0 computazionale relativi<br \/>\n        agli algoritmi <i>A<\/i> e <i>B<\/i> rispettivamente. <\/font><\/p>\n<ol>\n<li><font face=\"Book Antiqua,Calisto MT\"><i>A <\/i>e <i>B <\/i>hanno la<br \/>\n          stessa efficienza: <img loading=\"lazy\" decoding=\"async\" width=\"101\" height=\"44\" align=\"absmiddle\" src=\"..\/..\/esperti\/inform\/complessita\/Image34.gif\" alt=\"\"\/>,<br \/>\n          con <i>c &gt; 0 <\/i>constante.<\/font><\/li>\n<li><font face=\"Book Antiqua,Calisto MT\"><i>A <\/i>\u00e8 pi\u00f9<br \/>\n          efficiente di <i>B<\/i>: <img loading=\"lazy\" decoding=\"async\" width=\"102\" height=\"44\" align=\"absmiddle\" src=\"..\/..\/esperti\/inform\/complessita\/Image35.gif\" alt=\"\"\/><\/font><\/li>\n<li><font face=\"Book Antiqua,Calisto MT\"><i>B <\/i>\u00e8 pi\u00f9<br \/>\n          efficiente di <i>A<\/i>: <img loading=\"lazy\" decoding=\"async\" width=\"105\" height=\"44\" align=\"absmiddle\" src=\"..\/..\/esperti\/inform\/complessita\/Image36.gif\" alt=\"\"\/><\/font><\/li>\n<\/ol>\n<p><font face=\"Book Antiqua,Calisto MT\">Le classi di computabilit\u00e0<br \/>\n        degli algoritmi vengono invece definite sulla gerarchia di ordini di infinito<br \/>\n        delle funzioni di valutazione della complessit\u00e0 computazionale:<\/font><\/p>\n<ul>\n<li><font face=\"Book Antiqua,Calisto MT\">Complessit\u00e0 polinomiale:<br \/>\n          algoritmi <i>O(n<sup>i<\/sup>) <\/i>per qualche <i>i <\/i><\/font><\/li>\n<li><font face=\"Book Antiqua,Calisto MT\">Complessit\u00e0 esponenziale:<br \/>\n          algoritmi <i>O(a<sup>n<\/sup>) <\/i>per qualche <i>a <\/i><\/font><\/li>\n<li><font face=\"Book Antiqua,Calisto MT\">Complessit\u00e0 non-polinomiale:<br \/>\n          tutti gli altri algoritmi<\/font><\/li>\n<\/ul>\n<p><font face=\"Book Antiqua,Calisto MT\">L\u2019algoritmo F1 \u00e8 quindi <i>O(n!)<br \/>\n        <\/i>(non-polinomiale), ment<\/font><\/p>\n","protected":false},"excerpt":{"rendered":"<p>[&#8230;]<\/p>\n","protected":false},"author":180,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[62],"tags":[],"class_list":["post-2136","post","type-post","status-publish","format-standard","hentry","category-software"],"_links":{"self":[{"href":"https:\/\/www.vialattea.net\/content\/wp-json\/wp\/v2\/posts\/2136","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.vialattea.net\/content\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.vialattea.net\/content\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.vialattea.net\/content\/wp-json\/wp\/v2\/users\/180"}],"replies":[{"embeddable":true,"href":"https:\/\/www.vialattea.net\/content\/wp-json\/wp\/v2\/comments?post=2136"}],"version-history":[{"count":0,"href":"https:\/\/www.vialattea.net\/content\/wp-json\/wp\/v2\/posts\/2136\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.vialattea.net\/content\/wp-json\/wp\/v2\/media?parent=2136"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.vialattea.net\/content\/wp-json\/wp\/v2\/categories?post=2136"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.vialattea.net\/content\/wp-json\/wp\/v2\/tags?post=2136"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}