% This program illustrates a simple implementation of a genetic algorithm.
%
% The GA optimizes a Hamiltonian that simulates the occupation 
% of particles on a 1D lattice where each site is coupled (with
% a random strength) to every other site. An "on-site" term is also 
% present for each lattice site. The objective is to find the number
% and location of particles on the lattice to minimize the energy
%
% MCC Summer School 2005
% Gus Hart Northern Arizona Univesity
% mail: gus.hart "at" nau.edu

clc   % clear the command window
clear % clear all variables
close all % close windows

load Precomputed_EandH

% Plot distributions of energies
hist(energies,40)
xlabel('Energy')
ylabel('Number of energies')


BFmin = min(energies);  % Save the minimum from the brute-force search
N=length(H(1,:));       % Number of sites in the model
Nperms = 2^N;           % Number of possible permutations of occupation variables

% Parameters for the GA
Npop = 20;         % Number of individuals in the population
max_its = 500;     % Maximum number of iterations (generations)
r_mut = .05;       % Average rate of mutations/gene 

[en_hist, its] = ga_minimize(H, Npop, r_mut, max_its, BFmin);

% Calculate the average energy at each generation (iteration)
ave_en = zeros(1,its);
for i = 1:its
    ave_en(i) = sum(en_hist(i,:))/Npop;
end

% Output the results and make a plot
if BFmin == min(en_hist(its,:))
    fprintf('GA converged to correct minimum\n');
else
    fprintf('GA failed to converge\n');    
end
fprintf('Brute force min: %6.3f   GA min: %6.3f\n', BFmin, min(en_hist(its,:))) 
fprintf('Fraction of search space explored: %8.6f\n', Npop*its/Nperms) 
fprintf('Number of iterations %6d', its) 
figure
plot([1:its],en_hist(1:its,:),'r.',[1:its],ave_en(1:its),'b.-')
xlabel('Generation')
ylabel('Energy')