/*
* 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.examples.elfarolbar;
import java.util.List;
import net.sourceforge.jabm.agent.Agent;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Required;
import cern.jet.random.Uniform;
import cern.jet.random.engine.RandomEngine;
/**
* A prediction strategy which adaptively chooses amongst a set of other
* prediction strategies by choosing the one with the minimum
* forecasting error at any given time.
*
* @author Steve Phelps
*/
public class AdaptivePredictionStrategy extends AbstractPredictionStrategy
implements InitializingBean {
protected AbstractPredictionStrategy[] rules;
protected int numRules;
protected ObjectFactory<AbstractPredictionStrategy> ruleFactory;
protected AbstractPredictionStrategy currentBestPredictor;
/**
* The pseudo-random number generator used to tie-break rules with
* the same forecast error.
*/
protected RandomEngine prng;
public AdaptivePredictionStrategy(int numRules,
ObjectFactory<AbstractPredictionStrategy> ruleFactory) {
this.numRules = numRules;
this.ruleFactory = ruleFactory;
afterPropertiesSet();
}
public AdaptivePredictionStrategy() {
super();
}
public int getNumRules() {
return numRules;
}
public void setNumRules(int numRules) {
this.numRules = numRules;
}
public ObjectFactory<AbstractPredictionStrategy> getRuleFactory() {
return ruleFactory;
}
public void setRuleFactory(ObjectFactory<AbstractPredictionStrategy> ruleFactory) {
this.ruleFactory = ruleFactory;
}
public void execute(List<Agent> otherAgents) {
super.execute(otherAgents);
if (logger.isDebugEnabled()) {
logger.debug("currentPrediction = " + currentPrediction);
logger.debug("Executing best predictor: " + currentBestPredictor);
}
currentBestPredictor.execute(otherAgents);
}
public void makePrediction() {
findBestPredictor();
currentPrediction = currentBestPredictor.getCurrentPrediction();
}
public AbstractPredictionStrategy findBestPredictor() {
Uniform dist = new Uniform(0, rules.length-1, prng);
currentBestPredictor = rules[dist.nextInt()];
for(int i=0; i<rules.length; i++) {
if (rules[i].getForecastError()
< currentBestPredictor.getForecastError()) {
currentBestPredictor = rules[i];
}
}
if (logger.isDebugEnabled()) {
logger.debug("currentBestPredictor = " + currentBestPredictor);
}
return currentBestPredictor;
}
@Override
public void setAgent(Agent agent) {
super.setAgent(agent);
for(int i=0; i < rules.length; i++) {
rules[i].setAgent(agent);
}
}
public RandomEngine getPrng() {
return prng;
}
@Required
public void setPrng(RandomEngine prng) {
this.prng = prng;
}
// @Override
// public void eventOccurred(SimEvent event) {
// super.eventOccurred(event);
// for(int i=0; i < rules.length; i++) {
// rules[i].eventOccurred(event);
// }
// }
@Override
public void afterPropertiesSet() {
rules = new AbstractPredictionStrategy[numRules];
for (int i = 0; i < numRules; i++) {
rules[i] = ruleFactory.getObject();
}
}
public AbstractPredictionStrategy[] getRules() {
return rules;
}
public void setRules(AbstractPredictionStrategy[] rules) {
this.rules = rules;
}
public AbstractPredictionStrategy getCurrentBestPredictor() {
return currentBestPredictor;
}
}