/*
* JABM - Java Agent-Based Modeling Toolkit
* Copyright (C) 2013 Steve Phelps
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package net.sourceforge.jabm.init;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import net.sourceforge.jabm.Population;
import net.sourceforge.jabm.agent.Agent;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Required;
public class ProportionalCombiAgentInitialiser implements AgentInitialiser,
Serializable, InitializingBean {
protected float[] proportions;
protected List<AgentInitialiser> initialisers;
public ProportionalCombiAgentInitialiser(float[] proportions,
List<AgentInitialiser> initialisers) {
this();
this.proportions = proportions;
this.initialisers = initialisers;
}
public ProportionalCombiAgentInitialiser() {
super();
}
public void initialise(Population population) {
Collection<Agent> agents = population.getAgents();
int total = agents.size();
Iterator<Agent> agentIterator = agents.iterator();
for (int p = 0; p < proportions.length; p++) {
float proportion = proportions[p];
AgentInitialiser subInitialiser = initialisers.get(p);
int n = Math.round(proportion * total);
Population subPopulation = new Population();
for (int i = 0; i < n; i++) {
Agent agent = agentIterator.next();
subPopulation.add(agent);
subInitialiser.initialise(subPopulation);
}
}
}
public float[] getProportions() {
return proportions;
}
@Required
public void setProportions(float[] proportions) {
this.proportions = proportions;
}
public List<AgentInitialiser> getInitialisers() {
return initialisers;
}
@Required
public void setInitialisers(List<AgentInitialiser> initialisers) {
this.initialisers = initialisers;
}
@Override
public void afterPropertiesSet() throws Exception {
if (initialisers.size() == proportions.length+1 ) {
inferMissingProportion();
}
if (! (initialisers.size() == proportions.length)) {
throw new RuntimeException("Proportion/initialisers size mismatch");
}
checkSumToOne();
}
public void inferMissingProportion() {
float[] shortProportions = this.proportions;
int n = shortProportions.length;
this.proportions = Arrays.copyOf(shortProportions, n + 1);
float sigma = 0;
for(int i=0; i<n; i++) {
sigma += shortProportions[i];
}
this.proportions[n] = 1 - sigma;
}
public void checkSumToOne() {
float sigma = 0.0f;
for(int i=0; i<proportions.length; i++) {
sigma += proportions[i];
}
if ( (sigma > 1.00001f) || (sigma < 0) ) {
throw new RuntimeException("Proportions do not sum to 1");
}
}
}