-
Hugo Roussel authoredHugo Roussel authored
LocalModelMillerRegression.java 13.23 KiB
package agents.context.localModel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import agents.context.Context;
import agents.context.Experiment;
import agents.percept.Percept;
import utils.Pair;
import utils.TRACE_LEVEL;
// TODO: Auto-generated Javadoc
/**
* The Class LocalModelMillerRegression.
*/
public class LocalModelMillerRegression implements LocalModel{
private Context context;
/** The n parameters. */
private int nParameters;
/** The regression. */
transient private Regression regression;
/** The coef. */
private Double[] coefs;
private ArrayList<Experiment> firstExperiments;
/**
* Instantiates a new local model miller regression.
*
* @param world the world
*/
public LocalModelMillerRegression(Context associatedContext) {
context = associatedContext;
ArrayList<Percept> var = associatedContext.getAmas().getPercepts();
this.nParameters = var.size();
regression = new Regression(nParameters,true);
firstExperiments = new ArrayList<Experiment>();
}
public LocalModelMillerRegression(Context associatedContext, Double[] coefsCopy, List<Experiment> fstExperiments) {
context = associatedContext;
ArrayList<Percept> var = associatedContext.getAmas().getPercepts();
this.nParameters = var.size();
regression = new Regression(nParameters,true);
coefs = coefsCopy;
firstExperiments = new ArrayList<Experiment>(fstExperiments);
}
@Override
public void setContext(Context context) {
this.context = context;
}
@Override
public Context getContext() {
return context;
}
/**
* Sets the coef.
*
* @param coef the new coef
*/
@Override
public void setCoef(Double[] coef) {
this.coefs = coef.clone();
}
/**
* Gets the coef.
*
* @return the coef
*/
@Override
public Double[] getCoef() {
return coefs;
}
@Override
public double getProposition() {
ArrayList<Percept> percepts = context.getAmas().getPercepts();
double result = coefs[0];
if (coefs[0] == Double.NaN) System.exit(0);
for (int i = 1 ; i < coefs.length ; i++) {
if (Double.isNaN(coefs[i])) coefs[i] = 0.0;
result += coefs[i] * percepts.get(i-1).getValue();
}
return result;
}
private double getProposition(Context context, double[] situation) {
double result = coefs[0];
if (coefs[0] == Double.NaN) System.exit(0);
for (int i = 1 ; i < coefs.length ; i++) {
if (Double.isNaN(coefs[i])) coefs[i] = 0.0;
result += coefs[i] * situation[i-1];
}
return result;
}
@Override
public double getMaxProposition() {
ArrayList<Percept> percepts = context.getAmas().getPercepts();
double result = coefs[0];
if (coefs[0] == Double.NaN)
throw new ArithmeticException("First coeficient of model cannot be NaN");
for (int i = 1 ; i < coefs.length ; i++) {
if (Double.isNaN(coefs[i])) coefs[i] = 0.0;
if(coefs[i]>0) {
result += coefs[i] * context.getRanges().get(percepts.get(i-1)).getEnd();
}
else {
result += coefs[i] * context.getRanges().get(percepts.get(i-1)).getStart();
}
}
return result;
}
@Override
public HashMap<String, Double> getMaxWithConstraint(HashMap<String, Double> fixedPercepts){
ArrayList<Percept> percepts = context.getAmas().getPercepts();
HashMap<String, Double> result = new HashMap<String, Double>();
result.put("oracle", coefs[0]);
if (coefs[0] == Double.NaN)
throw new ArithmeticException("First coeficient of model cannot be NaN");
for (int i = 1 ; i < coefs.length ; i++) {
if (Double.isNaN(coefs[i])) coefs[i] = 0.0;
double pos;
Percept p = percepts.get(i-1);
if(fixedPercepts.containsKey(p.getName())) {
pos = fixedPercepts.get(p.getName());
} else {
if(coefs[i]>0) {
pos = context.getRanges().get(p).getEnd();
}
else {
pos = context.getRanges().get(p).getStart();
}
}
double value = coefs[i] * pos;
result.put("oracle", result.get("oracle") + value);
result.put(p.getName(), pos);
}
return result;
}
@Override
public double getMinProposition() {
ArrayList<Percept> percepts = context.getAmas().getPercepts();
double result = coefs[0];
if (coefs[0] == Double.NaN) System.exit(0);
for (int i = 1 ; i < coefs.length ; i++) {
if (Double.isNaN(coefs[i])) coefs[i] = 0.0;
if(coefs[i]<0) {
result += coefs[i] * context.getRanges().get(percepts.get(i-1)).getEnd();
}
else {
result += coefs[i] * context.getRanges().get(percepts.get(i-1)).getStart();
}
}
return result;
}
public double getProposition(Experiment experiment) {
if (coefs[0] == Double.NaN) System.exit(0);
double result = coefs[0];
for (int i = 1 ; i < coefs.length ; i++) {
if (Double.isNaN(coefs[i])) coefs[i] = 0.0;
result += coefs[i] * experiment.getValuesAsArray()[i-1];
}
return result;
}
@Override
public String getCoefsFormula() {
String result = "" +coefs[0];
// //System.out.println("Result 0" + " : " + result);
if (coefs[0] == Double.NaN) System.exit(0);
for (int i = 1 ; i < coefs.length ; i++) {
if (Double.isNaN(coefs[i])) coefs[i] = 0.0;
result += "\t" + coefs[i] + " (" + context.getAmas().getPercepts().get(i-1) +")";
}
return result;
}
@Override
public void updateModel(Experiment newExperiment, double weight) {
context.getAmas().getEnvironment().trace(TRACE_LEVEL.INFORM, new ArrayList<String>(Arrays.asList(context.getName(),"NEW POINT REGRESSION", "FIRST POINTS :", ""+firstExperiments.size(), "OLD MODEL :", coefsToString())));
if(firstExperiments.size()< (nParameters + 2)) {
firstExperiments.add(newExperiment);
updateModel();
}else {
updateModelWithExperimentAndWeight(newExperiment, weight, context.getAmas().data.numberOfPointsForRegression);
}
context.getAmas().addSpatiallyAlteredContextForUnityUI(context);
context.getAmas().getEnvironment().trace(TRACE_LEVEL.INFORM,new ArrayList<String>(Arrays.asList(context.getName(),"NEW POINT REGRESSION", "FIRST POINTS :", ""+firstExperiments.size(), "MODEL :", coefsToString())));
}
public void updateModel() {
regression = new Regression(nParameters,true);
for (Experiment exp : firstExperiments) {
regression.addObservation(exp.getValuesAsArray(), exp.getOracleProposition());
}
int i = 0;
while (regression.getN() < nParameters + 2) {
regression.addObservation(firstExperiments.get(i%firstExperiments.size()).getValuesAsArray(), firstExperiments.get(i%firstExperiments.size()).getOracleProposition());
i++;
}
double[] coef = regression.regress().getParameterEstimates();
coefs = new Double[coef.length];
for(int j = 0; j < coef.length; j++) {
coefs[j] = coef[j];
}
}
public void updateModelWithExperimentAndWeight(Experiment newExperiment, double weight, int numberOfPoints) {
regression = new Regression(nParameters,true);
int numberOfPointsForRegression = numberOfPoints;
if(numberOfPointsForRegression < (nParameters+2)) {
numberOfPointsForRegression += numberOfPointsForRegression*((int)((nParameters+2)/numberOfPointsForRegression));
}
Pair<double[][], double[]> artificialSituations = getRandomlyDistributedArtificialExperiments((int)(numberOfPointsForRegression - (numberOfPointsForRegression*weight)));
//Pair<double[][], double[]> artificialSituations = getEquallyDistributedArtificialExperiments((int)(numberOfPointsForRegression - (numberOfPointsForRegression*weight)));
int numberOfArtificialPoints = artificialSituations.getB().length;
for (int i =0;i<numberOfArtificialPoints;i++) {
regression.addObservation(artificialSituations.getA()[i], artificialSituations.getB()[i]);
}
int numberOfXPPoints;
if(numberOfArtificialPoints != (int)(numberOfPointsForRegression - (numberOfPointsForRegression*weight))) {
numberOfXPPoints = (int)(weight*numberOfArtificialPoints/(1-weight));
}
else {
numberOfXPPoints = (int)(numberOfPointsForRegression*weight);
}
for (int i =0;i<numberOfXPPoints;i++) {
regression.addObservation(newExperiment.getValuesAsArray(), newExperiment.getOracleProposition());
}
while (regression.getN() < newExperiment.getValuesAsLinkedHashMap().size() + 2) {
regression.addObservation(newExperiment.getValuesAsArray(), newExperiment.getOracleProposition());
System.out.println("ADING Observations " + regression.getN());
}
double[] coef = regression.regress().getParameterEstimates();
coefs = new Double[coef.length];
for(int i = 0; i < coef.length; i++) {
coefs[i] = coef[i];
}
context.getAmas().getEnvironment().regressionPoints = numberOfXPPoints + numberOfArtificialPoints;
}
private Pair<double[][], double[]> getEquallyDistributedArtificialExperiments(int amount){
int nbPercept = context.getAmas().getPercepts().size();
int[] nbPointsByPercept = new int[nbPercept];
ArrayList<Double> pointsByPercept[] = new ArrayList[nbPercept];
int totalNumberOfPoints = 1;
for(int i = 0 ; i < nbPercept ; i++) {
double startRange = this.context.getRanges().get(context.getAmas().getPercepts().get(i)).getStart();
double endRange = this.context.getRanges().get(context.getAmas().getPercepts().get(i)).getEnd();
nbPointsByPercept[i] = (int)(amount*this.context.rangeLengthRatio(context.getAmas().getPercepts().get(i)));
pointsByPercept[i] = new ArrayList<Double>();
totalNumberOfPoints *= nbPointsByPercept[i];
for(int j=0;j<=nbPointsByPercept[i]-1;j++) {
pointsByPercept[i].add(startRange + ((endRange-startRange)/(nbPointsByPercept[i]-1))*j );
}
}
nbPercept = context.getAmas().getPercepts().size();
int[] perceptIndices = new int[nbPercept];
for(int i = 0 ; i < nbPercept ; i++) {
perceptIndices[i] = 0;
}
int i = 0;
boolean test = true;
double[][] artificalExperiments = new double[totalNumberOfPoints][nParameters];
double[] artificalResults = new double[totalNumberOfPoints];
while(test) {
for(int j = 0;j<nParameters;j++) {
artificalExperiments[i][j] = pointsByPercept[j].get(perceptIndices[j]);
}
artificalResults[i] = this.getProposition(context, artificalExperiments[i]);
test = nextMultiDimCounter(perceptIndices, nbPointsByPercept);
i++;
}
return new Pair<double[][], double[]>(artificalExperiments, artificalResults);
}
private boolean nextMultiDimCounter(int[] indices, int[] bounds){
for(int i = 0; i<indices.length;i++) {
if(indices[i]==bounds[i]-1) {
if(i==indices.length-1) {
indices[i]=0;
return false;
}
else {
indices[i]=0;
}
}
else {
indices[i] += 1;
return true;
}
}
return false;
}
private Pair<double[][], double[]> getRandomlyDistributedArtificialExperiments(int amount){
double[][] artificalExperiments = new double[amount][nParameters];
double[] artificalResults = new double[amount];
for (int i = 0; i < amount;i ++) {
for(int j = 0;j<nParameters;j++) {
double startRange = this.context.getRanges().get(context.getAmas().getPercepts().get(j)).getStart();
double endRange = this.context.getRanges().get(context.getAmas().getPercepts().get(j)).getEnd();
artificalExperiments[i][j] = startRange + (Math.random()*(endRange - startRange));
}
artificalResults[i] = this.getProposition(context, artificalExperiments[i]);
}
return new Pair<double[][], double[]>(artificalExperiments, artificalResults);
}
@Override
public double distance(Experiment experiment) {
if (coefs[0] == Double.NaN) System.exit(0);
double distanceToTheModel = -coefs[0];
double normOfOthogonalVectorToThePlane = 0.0;
for (int i = 1 ; i < coefs.length ; i++) {
if (Double.isNaN(coefs[i])) coefs[i] = 0.0;
distanceToTheModel += -coefs[i] * experiment.getValuesAsArray()[i-1];
normOfOthogonalVectorToThePlane += coefs[i]*coefs[i];
}
distanceToTheModel += experiment.getOracleProposition();
normOfOthogonalVectorToThePlane += 1;
distanceToTheModel = Math.abs(distanceToTheModel);
normOfOthogonalVectorToThePlane = Math.sqrt(normOfOthogonalVectorToThePlane);
distanceToTheModel /= normOfOthogonalVectorToThePlane;
return distanceToTheModel;
}
@Override
public ArrayList<Experiment> getFirstExperiments() {
return firstExperiments;
}
@Override
public void setFirstExperiments( ArrayList<Experiment> frstExp) {
firstExperiments = frstExp;
}
@Override
public String coefsToString() {
String coefsString = "";
if(coefs != null) {
for(int i=0; i<coefs.length; i ++) {
coefsString += coefs[i] + "\t";
}
}
return coefsString;
}
@Override
public boolean finishedFirstExperiments() {
return firstExperiments.size()>= (nParameters + 2);
}
@Override
public TypeLocalModel getType() {
return TypeLocalModel.MILLER_REGRESSION;
}
}