def callback_gen(ga_instance):print("Generation: ", ga_instance.generations_completed)print("Fitness of the best solution: ", ga_instance.best_solution()[1])print(ga_instance.population)
# Configuração dos Parâmetros do AGfitness_function = fitness_func# Definição da população e dos indivíduosnum_generations =25num_parents_mating =2num_pop =25num_genes =3init_range_low =0.1init_range_high =10# Elitismoparent_selection_type ="sss"keep_parents =1# Cruzamentocrossover_type ="two_points"# Mutaçãomutation_type ="random"mutation_percent_genes =0.01mutation_num_genes =1
/usr/local/lib/python3.8/dist-packages/pygad/pygad.py:764: UserWarning: Starting from PyGAD 2.6.0, the callback_generation parameter is deprecated and will be removed in a later release of PyGAD. Please use the on_generation parameter instead.
if not self.suppress_warnings: warnings.warn("Starting from PyGAD 2.6.0, the callback_generation parameter is deprecated and will be removed in a later release of PyGAD. Please use the on_generation parameter instead.")
/usr/local/lib/python3.8/dist-packages/pygad/pygad.py:820: UserWarning: Use the 'save_best_solutions' parameter with caution as it may cause memory overflow when either the number of generations or number of genes is large.
if not self.suppress_warnings: warnings.warn("Use the 'save_best_solutions' parameter with caution as it may cause memory overflow when either the number of generations or number of genes is large.")
/usr/local/lib/python3.8/dist-packages/pygad/pygad.py:828: UserWarning: Use the 'save_solutions' parameter with caution as it may cause memory overflow when either the number of generations, number of genes, or number of solutions in population is large.
if not self.suppress_warnings: warnings.warn("Use the 'save_solutions' parameter with caution as it may cause memory overflow when either the number of generations, number of genes, or number of solutions in population is large.")
ga_instance.run()
/usr/local/lib/python3.8/dist-packages/control/timeresp.py:935: UserWarning: return_x specified for a transfer function system. Internal conversion to state space used; results may meaningless.
warnings.warn(
ga_instance.plot_fitness()ga_instance.pop_fitness=Truesolution, solution_fitness, solution_idx = ga_instance.best_solution(ga_instance.last_generation_fitness)print(f"Melhor Solução: {np.round(solution,2)}")print(f"Fitness: {np.round(-solution_fitness,2)}")print("Index of the best solution : {solution_idx}".format(solution_idx=solution_idx))if ga_instance.best_solution_generation !=-1:print("Best fitness value reached after {best_solution_generation} generations.".format( best_solution_generation=ga_instance.best_solution_generation))
Melhor Solução: [ 0.46 14.17 0.03]
Fitness: 2.26
Index of the best solution : 6
Best fitness value reached after 25 generations.
J,t,y,u,K = PID(solution)fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10,5))ax1.plot(t, y, label='y(t)')ax2.plot(t, u, label='u_out(t)')ax1.grid()ax2.grid()ax1.legend()ax2.legend() ax1.set_xlabel('t')ax2.set_xlabel('t')ax1.set_title('Step response')ax2.set_title('Control signal')
/usr/local/lib/python3.8/dist-packages/control/timeresp.py:935: UserWarning: return_x specified for a transfer function system. Internal conversion to state space used; results may meaningless.
warnings.warn(
from mpl_toolkits.mplot3d import axes3dplt.figure()k = ga_instance.initial_populationh = ga_instance.populationax = plt.axes(projection ="3d")colors = ('y', 'g', 'c', 'b', 'k')c_list = []for c in colors: c_list.extend([c] *5)# Creating plotsct = ax.scatter(k[:,0], k[:,1], k[:,2], c=c_list)scct = ax.scatter(h[:,0], h[:,1], h[:,2], c=c_list)ax.set_xlabel('P', fontweight ='bold')ax.set_ylabel('I', fontweight ='bold')ax.set_zlabel('D', fontweight ='bold')plt.show()# Rotate the axes and update# for angle in range(0, 360*4 + 1):# # Normalize the angle to the range [-180, 180] for display# angle_norm = (angle + 180) % 360 - 180# # Cycle through a full rotation of elevation, then azimuth, roll, and all# elev = azim = roll = 0# if angle <= 360:# elev = angle_norm# elif angle <= 360*2:# azim = angle_norm# elif angle <= 360*3:# roll = angle_norm# else:# elev = azim = roll = angle_norm# # Update the axis view and title# ax.view_init(elev, azim)# plt.title("Primeira e última Geração")# plt.draw()
#Controlador baseado em otimização Controle ótimo: operação de um sistema dinâmico a um custo mínimo. O problema LQR: Dinâmica do sistema descrita por um conjunto de equações diferênciais lineares com o Custo descrito por uma função quadrática. >A solução é fornecida pelo regulador linear-quadrático (LQR), um controlador realimentado.
O LQR é uma parte importante da solução para o problema LQG (linear-quadrártico gaussiano).
Sistemas MIMO: difícil especificar um overshoot. Os pólos são, do ponto de vista da engenharia, o resultado da raiz do determinante de uma matriz, e possuem uma relação obscura com a resposta temporal. (Usar LQR para sistemas MIMO).
Muitos problemas de controle podem ser expressos como a minimização do “desvio” das variáveis controladas, y, de seus set-points, r.
O significado do desvio pode ser formalizado como, por exemplo, \((y-r)^2\). Desta forma, elevando ao quadrado, penaliza-se tanto os desvios poditivos quanto os negativos.
\(e^2 = (y-r)^2\)
Inicialmente \(r = 0\) será assumido, pois denota qualquer ponto de equilíbrio constante em um modelo linearizado.
\(e^2 = y^2 = (Cx)^2\)
A função custo é uma função que queremos minimizar, o objetivo é encontrar um compensador que minimize a função J, ou seja, obtenha o menor valor possível.
Para o caso do erro \(e^2\), queremos minimizar a função:
\(J_c = \int_{0}^{\infty} e^2 \,dt\)
\(J_d=\sum_{k=0}^{\infty} e(k)^2 \,dt\)
Quando falamos em matrizes a função custo assume a forma:
\(Q=QT≥0,R=RT>0\), com $ (A, Q^{1/2}) $ observavel.
from scipy.signal import tf2ssimport scipy.signal as signal
A, B, C, D = tf2ss(num, den)# A = matrix([[0,0,1], [0,-2,-1], [0,0,0]])# B = matrix([[0,0,1]]).reshape(3,1)# C = matrix([[0,0,1]])# D = 0*eye(1)system = ct.ss(A,B,C,D)sys = ct.tf(system)print('system: ',sys)print('A:\n', A)print('B:\n', B)print('C:\n', C)print('D:\n', D)
# Entrada ao degraudef Step(sys): plt.figure() yout, T = ct.step_response(sys) plt.plot(yout, T)Step(system)
def LQR(indiv):global A, B, C, D, dt T0 =0 N =600 t = np.arange(T0,N*dt, dt) Q = matrix([[indiv[0],0,0], [0,indiv[1],0], [0,0,indiv[2]]]) R = indiv[3] K, S, E = ct.lqr(A, B, Q, R) Ac = (A-B@K) sys = ct.ss(Ac,B@K@matrix([[1],[0],[0]]),C,D) y,t,xout = lsim(sys,dt,t) J = dt*sum(np.dot(np.dot(y.T,y),Q)+np.dot(np.dot(Ac.T,Ac),R))# plt.plot(t,y)# plt.grid()# plt.show()return J, K, y, t, xout
def f_func(solution, solution_idx): J, K, y, t, xout = LQR(solution)return-J
def callback_gen(ga_instance):print("Generation: ", ga_instance.generations_completed)print("Fitness of the best solution: ", ga_instance.best_solution()[1])print(ga_instance.population)
# Configuração dos Parâmetros do AGfitness_function = f_func# Definição da população e dos indivíduosnum_generations =10num_parents_mating =2num_pop =5num_genes =4init_range_low =0.1init_range_high =10# Elitismoparent_selection_type ="sss"keep_parents =1# Cruzamentocrossover_type ="two_points"# Mutaçãomutation_type ="random"mutation_percent_genes =0.01mutation_num_genes =1
Generation: 1
Fitness of the best solution: -13.315317431015036
[[7.91717774 1.65970891 7.52509274 0.23326649]
[8.32234891 5.10504725 2.61945967 0.23326649]
[7.91717774 1.65970891 2.61945967 9.72650587]
[8.35795827 1.65970891 2.61945967 9.726719 ]
[1.96303611 5.10504725 7.52509274 0.23326649]]
Generation: 2
Fitness of the best solution: -10.674806333045062
[[1.96303611 5.10504725 7.52509274 0.23326649]
[1.96303611 1.30520908 7.52509274 0.23326649]
[8.06018692 5.10504725 7.52509274 0.23326649]
[1.96303611 2.21987709 7.52509274 0.23326649]
[7.91717774 5.10504725 7.99991901 0.23326649]]
---------------------------------------------------------------------------LinAlgError Traceback (most recent call last)
<ipython-input-51-e87ae048484f> in <module>----> 1ga_instance.run()/usr/local/lib/python3.8/dist-packages/pygad/pygad.py in run(self) 1407 self.previous_generation_fitness = self.last_generation_fitness.copy() 1408# Measuring the fitness of each chromosome in the population. Save the fitness in the last_generation_fitness attribute.-> 1409self.last_generation_fitness = self.cal_pop_fitness() 1410 1411 best_solution, best_solution_fitness, best_match_idx = self.best_solution(pop_fitness=self.last_generation_fitness)/usr/local/lib/python3.8/dist-packages/pygad/pygad.py in cal_pop_fitness(self) 1233 fitness = self.previous_generation_fitness[parent_idx] 1234else:-> 1235fitness = self.fitness_func(sol, sol_idx) 1236if type(fitness)in GA.supported_int_float_types: 1237pass<ipython-input-43-081b4e95514f> in f_func(solution, solution_idx) 1def f_func(solution, solution_idx):----> 2J, K, y, t, xout = LQR(solution) 3return-J
<ipython-input-42-7dc11440f013> in LQR(indiv) 13 R = indiv[3] 14---> 15K, S, E = ct.lqr(A, B, Q, R) 16 17 Ac =(A-B@K)/usr/local/lib/python3.8/dist-packages/control/statefbk.py in lqr(*args, **kwargs) 451 452# Compute the result (dimension and symmetry checking done in care())--> 453X, L, G = care(A, B, Q, R, N,None, method=method, S_s="N") 454return G, X, L
455/usr/local/lib/python3.8/dist-packages/control/mateqn.py in care(A, B, Q, R, S, E, stabilizing, method, A_s, B_s, Q_s, R_s, S_s, E_s) 433 "method='scipy' not valid when stabilizing is not True")
434--> 435X = sp.linalg.solve_continuous_are(A, B, Q, R) 436 K = np.linalg.solve(R, B.T @ X) 437 E, _ = np.linalg.eig(A - B @ K)/usr/local/lib/python3.8/dist-packages/scipy/linalg/_solvers.py in solve_continuous_are(a, b, q, r, e, s, balanced) 521 522if norm(u_sym,1)> sym_threshold:--> 523 raise LinAlgError('The associated Hamiltonian pencil has eigenvalues '
524 'too close to the imaginary axis')
525LinAlgError: The associated Hamiltonian pencil has eigenvalues too close to the imaginary axis
ga_instance.plot_fitness()ga_instance.pop_fitness=Truesolution, solution_fitness, solution_idx = ga_instance.best_solution()print(f"Melhor Solução: {np.round(solution,2)}")print(f"Fitness: {np.round(-solution_fitness,2)}")print("Index of the best solution : {solution_idx}".format(solution_idx=solution_idx))if ga_instance.best_solution_generation !=-1:print("Best fitness value reached after {best_solution_generation} generations.".format( best_solution_generation=ga_instance.best_solution_generation))
Melhor Solução: [ 1.85 -0.63 5.86 -0.21]
Fitness: -14.68
Index of the best solution : 0
Best fitness value reached after 9 generations.
J, K, y, t, xout = LQR(solution)fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10,5))ax1.plot(t, y, label='y(t)')ax2.plot(t, u, label='xout(t)')ax1.grid()ax2.grid()ax1.legend()ax2.legend() ax1.set_xlabel('t')ax2.set_xlabel('t')ax1.set_title('Step response')ax2.set_title('Control signal')