-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(appunti): Computational Intelligence Baionetta (#22)
Aggiunti appunti per l'esame di Computational Intelligence 🤓
- Loading branch information
Showing
146 changed files
with
5,003 additions
and
0 deletions.
There are no files selected for viewing
3,671 changes: 3,671 additions & 0 deletions
3,671
magistrale/Anno 1/Computational Intelligence/README.md
Large diffs are not rendered by default.
Oops, something went wrong.
69 changes: 69 additions & 0 deletions
69
magistrale/Anno 1/Computational Intelligence/algorithms_implementation/TSP/TSP.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import numpy as np | ||
|
||
class Problem_tsp: | ||
def __init__(self, nc, mat): | ||
self.ncities = nc | ||
self.dmat = mat # Matrice che contiene le distanze | ||
|
||
def create_random_instance(nc): | ||
# Crea due vettori x e y che contengono le coordinate di ciascuna città nel range [-50,50] | ||
x = 100 * np.random.random(nc) - 50 | ||
y = 100 * np.random.random(nc) - 50 | ||
m = np.zeros((nc, nc)) | ||
for i in range(nc): | ||
for j in range(nc): | ||
m[i,j] = np.sqrt((x[i]-x[j])**2+(y[i]-y[j])**2) | ||
return Problem_tsp(nc,m) | ||
|
||
# l è l'elenco dei nodi visitati, includendo il primo e l'ultimo (che sono uguali) | ||
def objective_function(self, l): | ||
s = 0 | ||
for i in range(self.ncities): | ||
c1 = l[i] | ||
c2 = l[i+1] | ||
d = self.dmat[c1,c2] | ||
s = s+d | ||
return s | ||
|
||
def do_2_opt(l, i, j): | ||
l1 = l[:i+1] | ||
l2 = l[i+1:j] | ||
l3 = l[j:] | ||
return l1+l2[::-1]+l3 | ||
|
||
# Compute the difference on the objective function if the 2-opt operation is performed | ||
def delta_2_opt(self, l, i, j): | ||
return -self.dmat[l[i], l[i+1]] - self.dmat[l[j-1], l[j]] + self.dmat[l[i], l[j-1]] + self.dmat[l[i+1], l[j]] | ||
|
||
def local_search(self, init_sol=None, verbose=False): | ||
n = self.ncities | ||
if init_sol is None: | ||
# Creazione di una soluzione casuale | ||
x = list(range(1, n)) | ||
np.random.shuffle(x) | ||
x = [0]+x+[0] | ||
else: | ||
x = init_sol.copy() | ||
improved = True | ||
fx = self.objective_function(x) | ||
if verbose: | ||
print("Initial value {}".format(fx)) | ||
while improved: | ||
best_delta = 1e300 # Numero grande per i confronti seguenti | ||
# Il delta sarebbe quanto aumenta la funzione obiettivo se io faccio la 2-opt (l'obiettivo è averlo più basso possibile) | ||
for i in range(1, n-1): # Controllo cosa succede se applico 2-opt senza effettivamente modificare x (lo cambio solo dopo aver trovato la migliore configurazione possibile) | ||
for j in range(i+3, n): | ||
delta = self.delta_2_opt(x, i, j) | ||
if delta < best_delta: | ||
i_best = i | ||
j_best = j | ||
best_delta = delta | ||
if best_delta < 0: | ||
fx = fx + best_delta | ||
x = Problem_tsp.do_2_opt(x, i_best, j_best) | ||
improved = True | ||
if verbose: | ||
print("New value {}".format(fx)) | ||
else: | ||
improved = False | ||
return x, fx |
20 changes: 20 additions & 0 deletions
20
magistrale/Anno 1/Computational Intelligence/algorithms_implementation/TSP/test.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
from TSP import * | ||
p = Problem_tsp.create_random_instance(50) | ||
print(p.ncities) | ||
print(p.dmat) | ||
|
||
l = list(range(0, 50)) | ||
l.append(0) | ||
print(len(l)) | ||
|
||
print(p.objective_function(l)) | ||
|
||
l1 = Problem_tsp.do_2_opt(l, 22, 44) | ||
print(p.objective_function(l1)) | ||
|
||
delta = p.delta_2_opt(l, 22, 44) | ||
print(delta) | ||
print(p.objective_function(l)+delta) | ||
|
||
p = Problem_tsp.create_random_instance(20) | ||
print(p.local_search(verbose=True)) |
30 changes: 30 additions & 0 deletions
30
...Computational Intelligence/algorithms_implementation/bayesian_network/bayesian_newtork.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import pgmpy | ||
from pgmpy.models import BayesianNetwork | ||
from pgmpy.factors.discrete import TabularCPD | ||
from pgmpy.inference import VariableElimination | ||
from pgmpy.inference import ApproxInference | ||
|
||
net = BayesianNetwork([('a', 'c'), ('b', 'c')]) | ||
|
||
print(net.nodes) | ||
print(net.edges) | ||
|
||
pa = TabularCPD('a', 2, [[0.2], [0.8]]) | ||
pb = TabularCPD('b', 2, [[0.4], [0.6]]) | ||
pc = TabularCPD('c', 2, [[0.2, 0.3, 0.1, 0.15], [0.8, 0.7, 0.9, 0.85]], ['a', 'b'], [2, 2]) | ||
net.add_cpds(pa, pb, pc) | ||
|
||
inference = VariableElimination(net) | ||
|
||
rl = inference.query(variables = ['c'], evidence = {'a':0, 'b':0}) | ||
print(rl.values) | ||
|
||
rl2 = inference.query(variables = ['c'], evidence = {'a':0}) | ||
print(rl2.values) | ||
|
||
rl3 = inference.query(variables = ['c']) | ||
print(rl3.values) | ||
|
||
inference2 = ApproxInference(net) | ||
rl_2 = inference2.query(variables=['c']) | ||
print(rl_2.values) |
Binary file added
BIN
+3.43 KB
...ence/algorithms_implementation/differential_evolution/__pycache__/diffevol.cpython-39.pyc
Binary file not shown.
89 changes: 89 additions & 0 deletions
89
...1/Computational Intelligence/algorithms_implementation/differential_evolution/diffevol.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# Una semplice implementazione dell'algoritmo Differential Evolution | ||
import numpy as np | ||
|
||
class Objective_Function: | ||
def __init__(self, fun, dim, domains): | ||
''' | ||
- fun è la definzione della funzione | ||
- dim è il numero di parametri | ||
- domains è la lista degli intervalli [x_i_min, x_i_max] per ogni variabile x_i | ||
''' | ||
self.fun = fun | ||
self.dim = dim | ||
self.domains = domains | ||
|
||
def __call__(self, x): | ||
return self.fun(x) | ||
|
||
|
||
class Differential_Evolution: | ||
def __init__(self, objf, np, f, cr, max_gen): | ||
self.objf = objf | ||
self.np = np | ||
self.f = f | ||
self.cr = cr | ||
self.max_gen = max_gen | ||
|
||
def initialize(self): # Serve ad inizializzare l'algoritmo (Ad esempio è necessario creare i vettori della popolazione) | ||
d = self.objf.dim | ||
self.population = [] | ||
self.values = [] | ||
for i in range(self.np): | ||
r = np.random.random(d) | ||
for j in range(d): | ||
l, u = self.objf.domains[j] # intervallo della j-esima variabile della funzione | ||
r[j] = l + (u - l) * r[j] | ||
self.population.append(r) | ||
self.values.append(self.objf(r)) | ||
self.best_f = 1e300 | ||
self.find_best() | ||
|
||
def find_best(self):# trovo il miglior elemento della popolazione | ||
self.i_best = 0 | ||
for i in range(1, self.np): | ||
if self.values[i] < self.values[self.i_best]: | ||
self.i_best = i | ||
if self.values[self.i_best] < self.best_f: | ||
self.best_f = self.values[self.i_best] | ||
self.best = self.population[self.i_best] | ||
print("found new best with f = {}".format(self.best_f)) | ||
|
||
def evolution(self): | ||
self.initialize() | ||
for g in range(1, self.max_gen+1): | ||
mutants = self.differential_mutation() | ||
trials = self.crossover(mutants) # gli elementi prodotti dal crossover nel differential evolution si chiamano trials | ||
self.selection(trials) | ||
self.find_best() | ||
return self.best_f, self.best | ||
|
||
def differential_mutation(self): | ||
mutants = [] | ||
for i in range(self.np): | ||
# RAND/1 implementations | ||
l = [j for j in range(self.np) if j != i] | ||
r1, r2, r3 = np.random.choice(l, 3, replace=False) | ||
m = self.population[r1] + self.f * (self.population[r2] - self.population[r3]) | ||
mutants.append(m) | ||
return mutants | ||
|
||
def crossover(self, mutants): | ||
trials = [] | ||
d = self.objf.dim | ||
for i in range(self.np): | ||
j_rand = np.random.randint(0, d) | ||
tr = np.zeros(d) | ||
for j in range(d): | ||
if np.random.random() < self.cr or j == j_rand: | ||
tr[j] = mutants[i][j] | ||
else: | ||
tr[j] = self.population[i][j] | ||
trials.append(tr) | ||
return trials | ||
|
||
def selection(self, trials): | ||
for i in range(self.np): | ||
fx = self.objf(trials[i]) | ||
if fx < self.values[i]: | ||
self.population[i] = trials[i] | ||
self.values[i] = fx |
19 changes: 19 additions & 0 deletions
19
...nno 1/Computational Intelligence/algorithms_implementation/differential_evolution/test.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
from diffevol import * | ||
|
||
''' | ||
objf = Objective_Function(lambda x: np.sqrt(x[0]**2+x[1]**2), 2, [[-1,1], [-1,1]]) | ||
print(objf(np.array([1,1]))) | ||
a = Differential_Evolution(objf, 20, 0.9, 1, 100) | ||
a.evolution() | ||
''' | ||
|
||
# Provando ad allargare il dominio tra -10 e 10 | ||
objf = Objective_Function(lambda x: np.sqrt(x[0]**2+x[1]**2), 2, [[-10,10], [-10,10]]) | ||
objf(np.array([1,1])) | ||
a = Differential_Evolution(objf, 20, 0.9, 1, 100) | ||
a.evolution() | ||
|
||
# è possibile giocare con i parametri in vari modi | ||
objf = Objective_Function(lambda x: np.sqrt(np.dot(x,x)), 10, [[-10,10] for i in range(10)]) | ||
a = Differential_Evolution(objf, 50, 0.9, 0.5, 1000) | ||
a.evolution() |
102 changes: 102 additions & 0 deletions
102
...elligence/algorithms_implementation/genetic_algorithm/MAX_CUT/binary_genetic_algorithm.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
# A simple genetic algorithm for unconstrained binary maximization problems | ||
import numpy as np | ||
|
||
class Binary_genetic_algorithm: | ||
|
||
def __init__(self, problem, num_elem=None, num_gen=100, pcross=0.9, pmut=0.01): | ||
self.problem=problem | ||
self.num_bits=problem.get_dim() | ||
if num_elem is None: | ||
self.num_elem=self.num_bits | ||
else: | ||
self.num_elem=num_elem | ||
self.pcross=pcross | ||
self.pmut=pmut | ||
self.num_gen=num_gen | ||
|
||
def run(self): | ||
self.init_population() | ||
for gen in range(0,self.num_gen): | ||
mating_pool=self.select_mating_pool() | ||
children=self.do_crossover(mating_pool) | ||
self.do_mutation(children) | ||
self.select_new_population(children) | ||
return self.best, self.best_f | ||
|
||
def init_population(self): | ||
self.population=[] | ||
self.f_obj=np.zeros(self.num_elem) | ||
self.best=None | ||
self.best_f=-1 | ||
for i in range(0,self.num_elem): | ||
ind=np.random.randint(0,1+1,self.num_bits) | ||
self.population.append(ind) | ||
self.f_obj[i]=self.problem.objective_function(ind) | ||
self.update_best(ind,self.f_obj[i]) | ||
|
||
def update_best(self, x, fx): | ||
if fx>self.best_f: | ||
self.best_f=fx | ||
self.best=x | ||
print("new best ",fx) | ||
|
||
def select_mating_pool(self): | ||
mating_pool=[] | ||
for i in range(0,self.num_elem//2): | ||
p1=self.roulette_wheel() | ||
p2=self.roulette_wheel() | ||
mating_pool.append((p1,p2)) | ||
return mating_pool | ||
|
||
def roulette_wheel(self): | ||
s=np.sum(self.f_obj) | ||
r=np.random.random()*s | ||
i=0 | ||
while r>s: | ||
r=r-self.f_obj[i] | ||
i=i+1 | ||
return self.population[i] | ||
|
||
def do_crossover(self, mating_pool): | ||
children=[] | ||
for p1, p2 in mating_pool: | ||
if np.random.random()<self.pcross: | ||
c1, c2 = self.crossover_operator(p1,p2) | ||
else: | ||
c1=p1.copy() | ||
c2=p2.copy() | ||
children.append(c1) | ||
children.append(c2) | ||
return children | ||
|
||
def crossover_operator(self, p1, p2): | ||
# one point crossover | ||
l1=list(p1) | ||
l2=list(p2) | ||
j=np.random.randint(1,self.num_bits) | ||
c1=np.array(l1[:j]+l2[j:]) | ||
c2=np.array(l2[:j]+l1[j:]) | ||
return c1,c2 | ||
|
||
def do_mutation(self,children): | ||
for c in children: | ||
for i in range(0, self.num_bits): | ||
if np.random.random()<self.pmut: | ||
c[i]=1-c[i] | ||
|
||
def select_new_population(self,children): | ||
# Find the best among the children and the parents | ||
f_child=np.array([self.problem.objective_function(c) for c in children]) | ||
ib1=np.argmax(self.f_obj) | ||
ib2=np.argmax(f_child) | ||
# First case: the best child is better than the the best parent | ||
if f_child[ib2]>self.f_obj[ib1]: | ||
self.population=children | ||
self.f_obj=f_child | ||
self.update_best(children[ib2],f_child[ib2]) | ||
else: | ||
iw=np.argmin(f_child) | ||
children[iw]=self.population[ib1] | ||
f_child[iw]=self.f_obj[ib1] | ||
self.population=children | ||
self.f_obj=f_child |
30 changes: 30 additions & 0 deletions
30
.../Computational Intelligence/algorithms_implementation/genetic_algorithm/MAX_CUT/maxcut.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Un'istanza è data dal numero dei nodi numerati da 0 al numero di nodi -1 (0, . . ., num_nodes-1) -> se ho 6 nodi sono numerati da 0 a 5 | ||
# È data anche dalla lista degli archi (una coppia di nodi) | ||
|
||
import numpy as np | ||
|
||
class Maxcut_problem: | ||
|
||
def __init__(self, num_nodes, edges): | ||
self.num_nodes = num_nodes | ||
self.edges = edges | ||
|
||
def create_random_instance(num_nodes, edge_prob): | ||
edges=[] | ||
for i in range(0,num_nodes): | ||
for j in range(i+1,num_nodes): | ||
if np.random.random()<edge_prob: | ||
edges.append((i,j)) | ||
return Maxcut_problem(num_nodes,edges) | ||
|
||
def objective_function(self,c): | ||
# c è un vettore di n-bit | ||
# c is a num_nodes binary string | ||
num_cuts = 0 | ||
for x,y in self.edges: | ||
if c[x]!=c[y]: | ||
num_cuts +=1 | ||
return num_cuts | ||
|
||
def get_dim(self): | ||
return self.num_nodes |
13 changes: 13 additions & 0 deletions
13
... 1/Computational Intelligence/algorithms_implementation/genetic_algorithm/MAX_CUT/test.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from binary_genetic_algorithm import * | ||
from maxcut import * | ||
|
||
p = Maxcut_problem.create_random_instance(20, 0.1) | ||
g = Binary_genetic_algorithm(p, num_elem=20) | ||
g.run() | ||
print(len(p.edges)) | ||
|
||
|
||
p2 = Maxcut_problem.create_random_instance(40, 0.2) | ||
print(len(p2.edges)) | ||
g = Binary_genetic_algorithm(p2, num_elem=20) | ||
g.run() |
Oops, something went wrong.