%prop=geneticGoogle(v, p, nv, F, varF, pp, generations,pop_size,prob,sigma,mut,eps,indices_list)

%This function uses a genetic algorithm to figure out the propensity values that lead to a desired distribution. 
%It uses an approximation of the google steady state distribution in order to evaluate the fitness of the propensities

%parameters-
%indices_list: the states we are trying to modify
%v: the corresponding values we are trying to reach in the those states
%p, nv, F, varF: corresponding to network we are looking at
%pp: the amount of noise we will use when finding the google distribution
%generations: number of times genetic algorithm iterates
%pop_size: number of members of each generation
%sigma: the size of distribution mutations are picked from-larger sigma means larger variations
%mut: the chance that each gene gets mutated
%eps: used in stopping criteria

%uses: fitnessGoogle.m, crossover.m
%Author: Jacob Miller, May 28th, 2016

function prop=geneticGoogle(v, p, nv, F, varF, pp, generations,pop_size,sigma,mut,eps,indices_list)

n=length(nv);%number of genes

propensities=cell(2*n,pop_size);

%Generate the entire first population
for i=1:pop_size

  c=rand(2,n); %Random Propensity
  propensities(:,i)=num2cell(reshape(c,1,2*n)); 
  
end

%Calculate fitnesses and probabilites for entire generation
[probabilities,m_index]=fitnessGoogle(propensities,indices_list,v,F,varF,nv,p,pp);

%Go throught the remaining generations
for k=1:generations

new_propensities=cell(2*n,pop_size); %Propensities of children 
new_propensities(:,1)=propensities(:,m_index);

%Create a whole new population for each generation
for i=1:pop_size-1

  p1=find(probabilities>rand(1,1),1);%Choose 2 parent sets of propensities
  p2=find(probabilities>rand(1,1),1);
  parent1=cell2mat(propensities(:,p1));
  parent2=cell2mat(propensities(:,p2));
  
  %crossover parent1 and parent2 with a mut chance of mutation and a distribution with sd of sigma
  child=crossover(parent1,parent2,mut,sigma);
%   new_c=reshape(child,2,n);
  new_propensities(:,i+1)=num2cell(child);
  
end

%Calculate fitnesses and propensities for entire generation
[probabilities,min_index]=fitnessGoogle(new_propensities,indices_list,v,F,varF,nv,p,pp);
propensities=new_propensities;

end
prop=reshape(cell2mat(propensities(:,min_index)),2,n); %Return most fit set of propensities
end