6.6. Solutions: Lecture 6#
6.6.1. Exercise 6.1#
es_6.1.py
#!/usr/bin/python
'''
Si determini con il metodo della bisezione lo zero della funzione g(x) = cos(x) nell’intervallo (0, 4).
Quali controlli sono stati omessi, nell’implementazione dell’algoritmo descritta nel testo della lezione,
che potrebbero accelerare il risultato?
'''
from bisezione import bisezione, bisezione_ricorsiva
import sys
from math import cos
def func (x) :
'''
Funzione di cui trovare lo zero
'''
return cos (x)
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def main () :
'''
Funzione che implementa il programma principale
'''
args = len (sys.argv) - 1
print ('The name of this script is ' + sys.argv[0])
print ('Zero della funzione = ', bisezione (func, 0., 4.))
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
if __name__ == "__main__":
main ()
bisezione.py
#!/usr/bin/python
def bisezione (
g, # funzione di cui trovare lo zero
xMin, # minimo dell'intervallo
xMax, # massimo dell'intervallo
prec = 0.0001): # precisione della funzione
'''
Funzione che calcola zeri
con il metodo della bisezione
'''
xAve = xMin
while ((xMax - xMin) > prec) :
xAve = 0.5 * (xMax + xMin)
if (g (xAve) * g (xMin) > 0.): xMin = xAve
else : xMax = xAve
return xAve
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def bisezione_ricorsiva (
g, # funzione di cui trovare lo zero
xMin, # minimo dell'intervallo
xMax, # massimo dell'intervallo
prec = 0.0001): # precisione della funzione
'''
Funzione che calcola zeri
con il metodo della bisezione ricorsivo
'''
xAve = 0.5 * (xMax + xMin)
if ((xMax - xMin) < prec): return xAve ;
if (g (xAve) * g (xMin) > 0.): return bisezione_ricorsiva (g, xAve, xMax, prec) ;
else : return bisezione_ricorsiva (g, xMin, xAve, prec) ;
6.6.2. Exercise 6.2#
es_6.2.py
#!/usr/bin/python
'''
Si svolga l’esercizio precedente utilizzando una funzione ricorsiva.
Quale delle due implementazioni è più rapida?
'''
from bisezione import bisezione, bisezione_ricorsiva
import sys
from math import cos
def func (x) :
'''
Funzione di cui trovare lo zero
'''
return cos (x)
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def main () :
'''
Funzione che implementa il programma principale
'''
args = len(sys.argv) - 1
print ('The name of this script is ' + sys.argv[0])
print ('Zero della funzione = ', bisezione_ricorsiva (func, 0., 4.))
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
if __name__ == "__main__":
main ()
6.6.3. Exercise 6.3#
es_6.3.py
#!/usr/bin/python
'''
Si implementi una funzione che calcola il fattoriale di un numero utilizzando una funzione ricorsiva.
'''
import sys
def fattoriale (n):
'''
Funzione che calcola il fattoriale
'''
if (n == 0): return 1;
return (n * fattoriale (n-1))
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def main () :
'''
Funzione che implementa il programma principale
'''
args = len(sys.argv) - 1
num = 6
if (num < 0) :
print ('Numero negativo, il fattoriale non è definito')
exit ()
print (num, '! = ', fattoriale (num))
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
if __name__ == "__main__":
main ()
6.6.4. Exercise 6.4#
es_6.4.py
#!/usr/bin/python
'''
Si determini con il metodo della sezione aurea il minimo
della funzione g(x) = x2 + 7.3x + 4 nell’intervallo (-10, 10).
'''
import sys
from sez_aurea import sezioneAureaMin
def funz (x) :
'''
Funzione di cui trovare l'estremante
'''
return x*x + 7.3*x + 4
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def main () :
'''
Funzione che implementa il programma principale
'''
x_min = - 10.
x_max = 10.
risoluzione = 0.0001
print ('Minimo della funzione: ', sezioneAureaMin (funz, x_min, x_max, risoluzione))
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
if __name__ == "__main__":
main ()
sez_aurea.py
#!/usr/bin/python
def sezioneAureaMin (
g, # funzione di cui trovare lo zero
x0, # estremo dell'intervallo
x1, # altro estremo dell'intervallo
prec = 0.0001): # precisione della funzione
'''
Funzione che calcola estremanti
con il metodo della sezione aurea
'''
r = 0.618
x2 = 0.
x3 = 0.
larghezza = abs (x1 - x0)
while (larghezza > prec):
x2 = x0 + r * (x1 - x0)
x3 = x0 + (1. - r) * (x1 - x0)
# si restringe l'intervallo tenendo fisso uno dei due estremi e spostando l'altro
if (g (x3) > g (x2)):
x0 = x3
# x1 = x1 this extreme does not change
else :
x1 = x2
# x0 = x0 this extreme does not change
larghezza = abs (x1-x0)
return (x0 + x1) / 2.
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def sezioneAureaMin_ricorsiva (
g, # funzione di cui trovare lo zero
x0, # estremo dell'intervallo
x1, # altro estremo dell'intervallo
prec = 0.0001): # precisione della funzione
'''
Funzione che calcola estremanti
con il metodo della sezione aurea
implementata ricorsivamente
'''
r = 0.618
x2 = x0 + r * (x1 - x0)
x3 = x0 + (1. - r) * (x1 - x0)
larghezza = abs (x1 - x0)
if (larghezza < prec) : return ( x0 + x1) / 2.
elif (g (x3) > g (x2)) : return sezioneAureaMin_ricorsiva (g, x3, x1, prec)
else : return sezioneAureaMin_ricorsiva (g, x0, x2, prec)
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def sezioneAureaEffMin (
g, # funzione di cui trovare lo zero
x0, # estremo dell'intervallo
x1, # altro estremo dell'intervallo
prec = 0.0001): # precisione della funzione
'''
Funzione che calcola estremanti
con il metodo della sezione aurea,
riutilizzando nel ciclo uno dei punti calcolati
nell'iterazione precedente
'''
r = 0.618
x2 = x0 + r * (x1 - x0)
g_x2 = g (x2)
x3 = 0.
larghezza = abs (x1 - x0)
while (larghezza > prec):
x3 = x0 + (1. - r) * (x1 - x0)
g_x3 = g (x3)
# si restringe l'intervallo tenendo fisso uno dei due estremi e spostando l'altro
if (g_x3 < g_x2):
# x0 = x0 this extreme does not change
x1 = x2
x2 = x3
g_x2 = g_x3
else :
x0 = x1
x1 = x3
# x2 = x2 this point does not change
larghezza = abs (x1-x0)
return (x0 + x1) / 2.
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def sezioneAureaEffMin_ricorsiva (
g, # funzione di cui trovare lo zero
x0, # estremo dell'intervallo
x1, # altro estremo dell'intervallo
x2, # punto intermedio dell'intervallo
g_x2, # valore della funzione g in x2
prec = 0.0001): # precisione della funzione
'''
Funzione che calcola estremanti
con il metodo della sezione aurea
implementata ricorsivamente,
riutilizzando nel ciclo uno dei punti calcolati
nell'iterazione precedente.
'''
r = 0.618
x3 = x0 + (1. - r) * (x1 - x0)
g_x3 = g (x3)
larghezza = abs (x1 - x0)
if (larghezza < prec) : return (x0 + x1) / 2.
elif g_x3 < g_x2 : return sezioneAureaEffMin_ricorsiva (g, x0, x2, x3, g_x3, prec)
else : return sezioneAureaEffMin_ricorsiva (g, x1, x3, x2, g_x2, prec)
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def sezioneAureaMax (
g, # funzione di cui trovare lo zero
x0, # estremo dell'intervallo
x1, # altro estremo dell'intervallo
prec = 0.0001): # precisione della funzione
'''
Funzione che calcola estremanti
con il metodo della sezione aurea
'''
r = 0.618
x2 = 0.
x3 = 0.
larghezza = abs (x1 - x0)
while (larghezza > prec):
x2 = x0 + r * (x1 - x0)
x3 = x0 + (1. - r) * (x1 - x0)
# si restringe l'intervallo tenendo fisso uno dei due estremi e spostando l'altro
if (g (x3) < g (x2)):
x0 = x3
# x1 = x1 this extreme does not change
else :
x1 = x2
# x0 = x0 this extreme does not change
larghezza = abs (x1-x0)
return (x0 + x1) / 2.
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def sezioneAureaMax_ricorsiva (
g, # funzione di cui trovare lo zero
x0, # estremo dell'intervallo
x1, # altro estremo dell'intervallo
prec = 0.0001): # precisione della funzione
'''
Funzione che calcola estremanti
con il metodo della sezione aurea
implementata ricorsivamente
'''
r = 0.618
x2 = x0 + r * (x1 - x0)
x3 = x0 + (1. - r) * (x1 - x0)
larghezza = abs (x1 - x0)
if (larghezza < prec) : return ( x0 + x1) / 2.
elif (g (x3) < g (x2)) : return sezioneAureaMax_ricorsiva (g, x3, x1, prec)
else : return sezioneAureaMax_ricorsiva (g, x0, x2, prec)
6.6.5. Exercise 6.5#
es_6.5.py
#!/usr/bin/python
'''
Si svolga l’esercizio precedente utilizzando una funzione ricorsiva.
Quale delle due implementazioni è più rapida?
'''
import sys
from sez_aurea import sezioneAureaMin, sezioneAureaEffMin, sezioneAureaMin_ricorsiva, sezioneAureaEffMin_ricorsiva
def funz (x) :
'''
Funzione di cui trovare l'estremante
'''
return x*x + 7.3*x + 4
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def main () :
'''
Funzione che implementa il programma principale
'''
x_min = - 10.
x_max = 10.
risoluzione = 0.0001
print ('Minimo della funzione: ', sezioneAureaMin (funz, x_min, x_max, risoluzione))
print ('Minimo della funzione: ', sezioneAureaEffMin (funz, x_min, x_max, risoluzione))
print ('Minimo della funzione: ', sezioneAureaMin_ricorsiva (funz, x_min, x_max, risoluzione))
x2 = x_min + 0.618 * (x_max - x_min)
print ('Minimo della funzione: ', sezioneAureaEffMin_ricorsiva (funz, x_min, x_max, x2, risoluzione))
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
if __name__ == "__main__":
main ()
6.6.6. Exercise 6.6#
es_6.6.py
#!/usr/bin/python
'''
Si svolgano i due esercizi precedenti cercando il massimo di una funzione a scelta.
'''
import sys
from math import pi, sin
from sez_aurea import sezioneAureaMax, sezioneAureaMax_ricorsiva
def funz (x) :
'''
Funzione di cui trovare l'estremante
'''
return sin (0.5 * x)
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def main () :
'''
Funzione che implementa il programma principale
'''
x_min = 0.
x_max = 2. * pi
risoluzione = 0.0001
print ('Massimo della funzione: ', sezioneAureaMax (funz, x_min, x_max, risoluzione))
print ('Massimo della funzione: ', sezioneAureaMax_ricorsiva (funz, x_min, x_max, risoluzione))
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
if __name__ == "__main__":
main ()
6.6.7. Exercise 6.7#
es_6.7.py
#!/usr/bin/python
'''
Modificando i programmi sviluppati precedentemente,
si disegnino le funzioni studiate ed i punti trovati con i metodi della bisezione e della sezione aurea.
'''
import sys
from math import cos
import matplotlib.pyplot as plt
import numpy as np
def bisezione_mod (
g, # funzione di cui trovare lo zero
xMin, # minimo dell'intervallo
xMax, # massimo dell'intervallo
prec = 0.0001): # precisione della funzione
'''
Funzione che calcola zeri
con il metodo della bisezione,
ritornando anche la collezione di intervalli considerati
'''
extremes = []
xAve = xMin
while ((xMax - xMin) > prec) :
extremes.append ([xMin, xMax])
xAve = 0.5 * (xMax + xMin)
if (g (xAve) * g (xMin) > 0.): xMin = xAve
else : xMax = xAve
return xAve , extremes
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def func (x) :
'''
Funzione di cui trovare lo zero
'''
return np.cos (x)
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def main () :
'''
Funzione che implementa il programma principale
'''
args = len (sys.argv) - 1
print ('The name of this script is ' + sys.argv[0])
xMin = 0.
xMax = 4.
zero, extremes = bisezione_mod (func, xMin, xMax)
print ('Zero della funzione = ', zero)
# creazione dei punti per il disegno della funzione
x = np.linspace(-5, 5, 1000)
y = np.cos (x)
# disegno della funzione
fig, ax = plt.subplots ()
ax.plot (x, y, label='f(x)= cos (x)')
ax.set_title ('il metodo della bisezione', size=14)
ax.set_xlim (0., 4)
yMin = -1.5
yMax = 1.5
ax.set_ylim (yMin, yMax)
# disegno di un singolo punto
# l'opzione "zorder" porta il punto in primo piano
plt.scatter([zero], [0], color='red', zorder = 5)
steps = len (extremes)
yMin_local = yMin
yMax_local = yMax
for i in range (len (extremes)):
ax.add_patch(plt.Rectangle (
(extremes[i][0], yMin_local), # bottom - left vertex coordinates
extremes[i][1] - extremes[i][0], # width
yMax_local - yMin_local, # height
edgecolor = 'silver',
fill = False,
))
yMin_local = 0.5 * yMin_local
yMax_local = 0.5 * yMax_local
plt.savefig ('es_5.7.png')
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
if __name__ == "__main__":
main ()