bdi4jade
Changes
bdi-jade-extensions/.gitignore 1(+1 -0)
bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/InfluenceFactor.java 24(+23 -1)
bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningAlgorithm.java 128(+126 -2)
bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/learningalgorithm/LinearRegressionAlgorithm.java 62(+44 -18)
bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedCapability.java 18(+11 -7)
bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedPlanBody.java 16(+16 -0)
bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedPlanSelectionStrategy.java 23(+12 -11)
bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/NominalInfluenceFactor.java 60(+60 -0)
bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/NumericInfluenceFactor.java 23(+23 -0)
bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/OptimizationFunction.java 6(+6 -0)
Details
bdi-jade-extensions/.gitignore 1(+1 -0)
diff --git a/bdi-jade-extensions/.gitignore b/bdi-jade-extensions/.gitignore
index 5e56e04..a56cb9b 100644
--- a/bdi-jade-extensions/.gitignore
+++ b/bdi-jade-extensions/.gitignore
@@ -1 +1,2 @@
/bin
+.classpath
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/InfluenceFactor.java b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/InfluenceFactor.java
index e2a98e4..87591a2 100644
--- a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/InfluenceFactor.java
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/InfluenceFactor.java
@@ -2,18 +2,40 @@ package bdi4jade.extension.planselection.learningbased;
import bdi4jade.belief.Belief;
-public class InfluenceFactor {
+/**
+ * An abstraction of an influence factor which is context variable and maps to a
+ * belief. An influence factor affects plan outcomes.
+ *
+ * @author João Faccin
+ */
+public abstract class InfluenceFactor {
private Belief<?, ?> belief;
+ /**
+ * Creates a new influence factor and maps it to a belief.
+ *
+ * @param belief
+ * A belief to be mapped.
+ */
public InfluenceFactor(Belief<?, ?> belief) {
this.belief = belief;
}
+ /**
+ * Returns the name of the mapped belief.
+ *
+ * @return Belief's name
+ */
public String getBeliefName() {
return (String) this.belief.getName();
}
+ /**
+ * Returns the value of mapped belief.
+ *
+ * @return Belief's value.
+ */
public Object getBeliefValue() {
return this.belief.getValue();
}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningAlgorithm.java b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningAlgorithm.java
index f7ad425..9d21c0f 100644
--- a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningAlgorithm.java
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningAlgorithm.java
@@ -1,10 +1,134 @@
package bdi4jade.extension.planselection.learningbased;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Map;
+
+import weka.core.DenseInstance;
+import weka.core.Instance;
+import weka.core.Instances;
+import bdi4jade.extension.planselection.learningbased.util.Utils;
import bdi4jade.goal.Softgoal;
import bdi4jade.plan.Plan;
-public interface LearningAlgorithm {
+/**
+ * It represents the algorithm used by the {@link}
+ * LearningBasedPlanSelectionStrategy. It uses an algorithm, specified in
+ * {@link} PlanMetadata, to predict an expected contribution of a plan's
+ * outcome.
+ *
+ * @author João Faccin
+ */
+public class LearningAlgorithm {
+
+ private Instances trainingInstances;
+
+ public LearningAlgorithm() {
+ }
+
+ /**
+ * Predicts an expected plan's contribution for a given softgoal based on
+ * plan metadata and current context conditions.
+ *
+ * @param plan
+ * A plan which expected contribution we want to predict.
+ * @param softgoal
+ * A softgoal which plan's contribution is related.
+ * @return An expected plan contribution value.
+ */
+ @SuppressWarnings("unchecked")
+ public double predictExpectedContribution(Plan plan, Softgoal softgoal) {
+
+ double prediction = 1;
+ PlanMetadata planMetadata = ((Map<Softgoal, PlanMetadata>) plan
+ .getMetadata(PlanMetadata.METADATA_NAME)).get(softgoal);
+
+ if (planMetadata.getPlanExecutionsCounter() < planMetadata
+ .getMinPlanExecutions()) {
+ String filePath = planMetadata.getFilePath()
+ + (plan.getId() + "_" + plan.getClass().getSimpleName()
+ + "_" + softgoal).toLowerCase() + ".arff";
+ if (!new File(filePath).exists()) {
+ try {
+ Utils.writeToFile(filePath,
+ planMetadata.getArffFileHeader());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ } else {
+
+ if (planMetadata.getPlanExecutionsCounter() == planMetadata
+ .getMinPlanExecutions()
+ || planMetadata.getPlanExecutionsCounter()
+ % planMetadata.getLearningGap() == 0) {
+ learnFromTrainingSet(plan, softgoal);
+ }
+
+ int numOfFactors = planMetadata.getInfluenceFactors().size();
+
+ Instance instance = new DenseInstance(numOfFactors);
+
+ for (int i = 0; i < numOfFactors; i++) {
+ instance.setValue(trainingInstances.attribute(i),
+ (Double) planMetadata.getInfluenceFactors().get(i)
+ .getBeliefValue());
+ }
+
+ try {
+ prediction = planMetadata.getModel().classifyInstance(instance);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ switch (planMetadata.getOptimizationFunction()) {
+ case MINIMIZE:
+ return 1 - prediction;
+ default:
+ return prediction;
+ }
+ }
+
+ /**
+ * Generates a prediction model from a training set of a given plan and
+ * softgoal.
+ *
+ * @param plan
+ * A plan which prediction model we want to generate.
+ * @param softgoal
+ * A softgoal that the generated prediction model will relate.
+ */
+ @SuppressWarnings("unchecked")
+ private void learnFromTrainingSet(Plan plan, Softgoal softgoal) {
+
+ PlanMetadata planMetadata = ((Map<Softgoal, PlanMetadata>) plan
+ .getMetadata(PlanMetadata.METADATA_NAME)).get(softgoal);
+
+ try {
+ trainingInstances = new Instances(new BufferedReader(
+ new FileReader(
+ planMetadata.getFilePath()
+ + (plan.getId() + "_"
+ + plan.getClass().getSimpleName()
+ + "_" + softgoal).toLowerCase()
+ + ".arff")));
+
+ trainingInstances
+ .setClassIndex(trainingInstances.numAttributes() - 1);
+
+ planMetadata.getModel().buildClassifier(trainingInstances);
- public double predictExpectedContribution(Plan plan, Softgoal softgoal);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
}
\ No newline at end of file
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/learningalgorithm/LinearRegressionAlgorithm.java b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/learningalgorithm/LinearRegressionAlgorithm.java
index 107cbd5..88b9b1d 100644
--- a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/learningalgorithm/LinearRegressionAlgorithm.java
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/learningalgorithm/LinearRegressionAlgorithm.java
@@ -7,7 +7,6 @@ import java.io.FileReader;
import java.io.IOException;
import java.util.Map;
-import weka.classifiers.functions.LinearRegression;
import weka.core.DenseInstance;
import weka.core.Instance;
import weka.core.Instances;
@@ -20,7 +19,9 @@ import bdi4jade.plan.Plan;
public class LinearRegressionAlgorithm implements LearningAlgorithm {
private Instances trainingInstances;
- private LinearRegression model;
+
+ //Ver PlanMetadata
+ //private LinearRegression model;
@Override
@SuppressWarnings("unchecked")
@@ -31,9 +32,9 @@ public class LinearRegressionAlgorithm implements LearningAlgorithm {
.getMetadata(PlanMetadata.METADATA_NAME)).get(softgoal);
if (planMetadata.getPlanExecutionsCounter() < PlanMetadata.MIN_PLAN_EXECUTIONS) {
- String filePath = "instances/"
- + plan.getClass().getSimpleName().toLowerCase() + "_"
- + softgoal + ".arff";
+ String filePath = "/home/jgfaccin/git/bdi4jade/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/instances/"
+ + (plan.getId() + "_" + plan.getClass().getSimpleName()
+ + "_" + softgoal).toLowerCase() + ".arff";
if (!new File(filePath).exists()) {
try {
Utils.writeToFile(filePath,
@@ -42,45 +43,70 @@ public class LinearRegressionAlgorithm implements LearningAlgorithm {
e.printStackTrace();
}
}
- planMetadata.increasePlanExecutionsCounter();
} else {
- learnFromTrainingSet(plan, softgoal);
+
+ if (planMetadata.getPlanExecutionsCounter() == PlanMetadata.MIN_PLAN_EXECUTIONS
+ || planMetadata.getPlanExecutionsCounter()
+ % PlanMetadata.LEARNING_GAP == 0) {
+ learnFromTrainingSet(plan, softgoal);
+ }
+ //learnFromTrainingSet(plan, softgoal);
int numOfFactors = planMetadata.getInfluenceFactors().size();
Instance instance = new DenseInstance(numOfFactors);
for (int i = 0; i < numOfFactors; i++) {
+ // it was Double.valueOf((Integer)
+ // planMetadata.getInfluenceFactors...
instance.setValue(trainingInstances.attribute(i),
- (double) planMetadata.getInfluenceFactors().get(i)
+ (Double) planMetadata.getInfluenceFactors().get(i)
.getBeliefValue());
}
try {
- prediction = model.classifyInstance(instance);
- // System.out.println("Current Instance (" + instance + "): " +
- // prediction);
+ //prediction = model.classifyInstance(instance);
+ prediction = planMetadata.getModel().classifyInstance(instance);
} catch (Exception e) {
e.printStackTrace();
}
}
- return prediction;
+ switch (planMetadata.getOptimizationFunction()) {
+ case MINIMIZE:
+ return 1 - prediction;
+ default:
+ return prediction;
+ }
}
+ @SuppressWarnings("unchecked")
private void learnFromTrainingSet(Plan plan, Softgoal softgoal) {
+
+
+ PlanMetadata planMetadata = ((Map<Softgoal, PlanMetadata>) plan
+ .getMetadata(PlanMetadata.METADATA_NAME)).get(softgoal);
+
try {
- trainingInstances = new Instances(new BufferedReader(
- new FileReader("instances/"
- + plan.getClass().getSimpleName().toLowerCase()
- + "_" + softgoal + ".arff")));
+ trainingInstances = new Instances(
+ new BufferedReader(
+ new FileReader(
+ "/home/jgfaccin/git/bdi4jade/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/instances/"
+ + (plan.getId()
+ + "_"
+ + plan.getClass()
+ .getSimpleName()
+ + "_" + softgoal)
+ .toLowerCase() + ".arff")));
trainingInstances
.setClassIndex(trainingInstances.numAttributes() - 1);
- model = new LinearRegression();
- model.buildClassifier(trainingInstances);
+ //model = new LinearRegression();
+ //model.buildClassifier(trainingInstances);
+ planMetadata.getModel().buildClassifier(trainingInstances);
+
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedCapability.java b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedCapability.java
index 991fedc..c544013 100644
--- a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedCapability.java
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedCapability.java
@@ -4,6 +4,12 @@ import bdi4jade.annotation.Belief;
import bdi4jade.core.Capability;
import bdi4jade.extension.planselection.utilitybased.SoftgoalPreferences;
+/**
+ * Represents a capability that implements the {@link}
+ * LearningBasedPlanSelectionStrategy.
+ *
+ * @author João Faccin
+ */
public class LearningBasedCapability extends Capability {
private static final long serialVersionUID = -1044132085270106726L;
@@ -11,14 +17,12 @@ public class LearningBasedCapability extends Capability {
@Belief
protected SoftgoalPreferences softgoalPreferences = new SoftgoalPreferences();
- /*
- * Passando o LearningAlgorithm como parâmetro aqui ele será instanciado no
- * agente. Assim será possível definir diferentes algoritmos de aprendizado
- * para diferentes agentes.
+ /**
+ * Default constructor that sets the {@link}
+ * LearningBasedPlanSelectionStrategy as the plan selection strategy.
*/
- public LearningBasedCapability(LearningAlgorithm learningAlgorithm) {
- setPlanSelectionStrategy(new LearningBasedPlanSelectionStrategy(
- learningAlgorithm));
+ public LearningBasedCapability() {
+ setPlanSelectionStrategy(new LearningBasedPlanSelectionStrategy());
}
}
\ No newline at end of file
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedPlanBody.java b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedPlanBody.java
index 3bba0f1..204b20e 100644
--- a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedPlanBody.java
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedPlanBody.java
@@ -6,10 +6,20 @@ import java.util.Map;
import bdi4jade.goal.Softgoal;
import bdi4jade.plan.planbody.AbstractPlanBody;
+/**
+ * Represents the learning-based plan body abstraction, being an extension of
+ * the {@link} AbstractPlanBody.
+ *
+ * @author João Faccin
+ */
public abstract class LearningBasedPlanBody extends AbstractPlanBody {
private static final long serialVersionUID = -5064965263121492233L;
+ /**
+ * Notifies some elements of a plan metadata (e.g. {@link} Outcome instance)
+ * that a plan execution will start.
+ */
@SuppressWarnings("unchecked")
@Override
public void onStart() {
@@ -21,6 +31,10 @@ public abstract class LearningBasedPlanBody extends AbstractPlanBody {
}
}
+ /**
+ * Notifies some elements of a plan metadata (e.g. {@link} Outcome instance)
+ * that a plan execution ended.
+ */
@SuppressWarnings("unchecked")
@Override
public int onEnd() {
@@ -29,7 +43,9 @@ public abstract class LearningBasedPlanBody extends AbstractPlanBody {
for (PlanMetadata metadata : planMetadata) {
metadata.getNotifiedAtEndedPlanExecution();
+ metadata.increasePlanExecutionsCounter();
}
+
return super.onEnd();
}
}
\ No newline at end of file
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedPlanSelectionStrategy.java b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedPlanSelectionStrategy.java
index dc83e44..0aca05b 100644
--- a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedPlanSelectionStrategy.java
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedPlanSelectionStrategy.java
@@ -9,23 +9,24 @@ import bdi4jade.plan.Plan;
import bdi4jade.reasoning.AbstractReasoningStrategy;
import bdi4jade.reasoning.PlanSelectionStrategy;
+/**
+ * A learning-based implementation of the {@link} PlanSelectionStrategy. It
+ * selects the plan that has the best expected contribution based on a predicted
+ * outcome value and agent preferences.
+ *
+ * @author João Faccin
+ */
public class LearningBasedPlanSelectionStrategy extends
AbstractReasoningStrategy implements PlanSelectionStrategy {
private LearningAlgorithm learningAlgorithm;
- /*
- * Instanciarei um algoritmo de aprendizagem aqui, e.g. public
- * UtilityBasedPlanSelectionStrategy(LearningAlgorithm la){}.
- * LearningAlgorithm será uma interface que obrigará a criação de uma função
- * getValue() ou algo do tipo. Criarei uma série de classes (nesse momento
- * apenas duas) que implementam essa interface, e.g.
- * LinearRegressionAlgorithm e SVMAlgorithm, que serão criadas no pacote
- * implementation.
+ /**
+ * Default constructor that initializes the {@link} LearningAlgorithm used
+ * in the plan selection process.
*/
- public LearningBasedPlanSelectionStrategy(
- LearningAlgorithm learningAlgorithm) {
- this.learningAlgorithm = learningAlgorithm;
+ public LearningBasedPlanSelectionStrategy() {
+ this.learningAlgorithm = new LearningAlgorithm();
}
@Override
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/NominalInfluenceFactor.java b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/NominalInfluenceFactor.java
new file mode 100644
index 0000000..917468f
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/NominalInfluenceFactor.java
@@ -0,0 +1,60 @@
+package bdi4jade.extension.planselection.learningbased;
+
+import java.util.ArrayList;
+
+import bdi4jade.belief.Belief;
+
+/**
+ * An implementation of the abstract class {@link} InfluenceFactor to allow the
+ * use of discrete values as influence factor.
+ *
+ * @author João Faccin
+ */
+public class NominalInfluenceFactor extends InfluenceFactor {
+
+ private ArrayList<String> possibleValues;
+
+ public NominalInfluenceFactor(Belief<?, ?> belief) {
+ super(belief);
+ this.possibleValues = new ArrayList<String>();
+ }
+
+ /**
+ * Creates a new influence factor and maps it to a belief. Also, define a
+ * set of possible values that this influence factor can have.
+ *
+ * @param belief
+ * A belief to be mapped.
+ * @param possibleValues
+ * A set of values that the influence factor can have.
+ */
+ public NominalInfluenceFactor(Belief<?, ?> belief,
+ ArrayList<String> possibleValues) {
+ super(belief);
+ this.possibleValues = possibleValues;
+ }
+
+ /**
+ * Adds a new value to the set of possible values that the influence factor
+ * can have.
+ *
+ * @param possibleValue
+ * A new possible value.
+ */
+ public void addPossibleValue(String possibleValue) {
+ possibleValues.add(possibleValue);
+ }
+
+ @Override
+ public String toString() {
+ String influenceFactor = "@attribute " + getBeliefName() + " {"
+ + possibleValues.get(0);
+ for (int i = 1; i < possibleValues.size(); i++) {
+ influenceFactor += "," + possibleValues.get(i);
+ }
+ influenceFactor += "}";
+
+ return influenceFactor;
+ }
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/NumericInfluenceFactor.java b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/NumericInfluenceFactor.java
new file mode 100644
index 0000000..2da3609
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/NumericInfluenceFactor.java
@@ -0,0 +1,23 @@
+package bdi4jade.extension.planselection.learningbased;
+
+import bdi4jade.belief.Belief;
+
+/**
+ * An implementation of the abstract class {@link} InfluenceFactor to allow the
+ * use of continuous values as influence factor.
+ *
+ * @author João Faccin
+ */
+public class NumericInfluenceFactor extends InfluenceFactor {
+
+ public NumericInfluenceFactor(Belief<?, ?> belief) {
+ super(belief);
+ }
+
+ @Override
+ public String toString() {
+ String influenceFactor = "@attribute " + getBeliefName() + " numeric";
+ return influenceFactor;
+ }
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/OptimizationFunction.java b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/OptimizationFunction.java
index ca87a99..9c1a9e5 100644
--- a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/OptimizationFunction.java
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/OptimizationFunction.java
@@ -1,5 +1,11 @@
package bdi4jade.extension.planselection.learningbased;
+/**
+ * An optimization function that indicates how an outcome value influences on
+ * preference satisfaction.
+ *
+ * @author João Faccin
+ */
public enum OptimizationFunction {
MINIMIZE, MAXIMIZE;
}
\ No newline at end of file
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/Outcome.java b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/Outcome.java
index 30e7cd0..bc0cdb2 100644
--- a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/Outcome.java
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/Outcome.java
@@ -1,26 +1,38 @@
package bdi4jade.extension.planselection.learningbased;
+/**
+ * An abstraction of an outcome. It represents a measurement that can be taken
+ * during and/or after a plan execution.
+ *
+ * @author João Faccin
+ */
public abstract class Outcome {
- private String name;
-
- public Outcome(String name) {
- this.name = name;
- }
+ /**
+ * Gets the final measurement of an outcome value.
+ *
+ * @return An outcome measurement.
+ */
+ public abstract double getMeasurement();
- public String getName() {
- return this.name;
+ /**
+ * Used in cases that a measurement is an interval between two values, e.g.
+ * difference between final and initial time.
+ */
+ public void startMeasurement() {
}
- /*
- * It may be a function that return the measurement of the outcome. If it's
- * time measurement, it can be done through calculation of the difference
- * between final and initial time execution.
+ /**
+ * Used in cases that a measurement is an interval between two values, e.g.
+ * difference between final and initial time.
*/
- public abstract double getMeasurement();
-
- public void startMeasurement() {}
-
- public void endMeasurement() {}
+ public void endMeasurement() {
+ };
+ @Override
+ public String toString() {
+ String outcome = "@attribute " + this.getClass().getSimpleName() + " numeric";
+ return outcome;
+ }
+
}
\ No newline at end of file
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/PlanMetadata.java b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/PlanMetadata.java
index 68156c7..2c886ff 100644
--- a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/PlanMetadata.java
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/PlanMetadata.java
@@ -1,19 +1,30 @@
package bdi4jade.extension.planselection.learningbased;
import java.io.IOException;
+import java.nio.file.FileSystems;
import java.util.ArrayList;
+import weka.classifiers.Classifier;
import bdi4jade.extension.planselection.learningbased.util.Utils;
import bdi4jade.goal.Softgoal;
import bdi4jade.plan.Plan;
+/**
+ * Represents the metadata associated to a plan. It relates a set of influence
+ * factors to an outcome and to a specific softgoal. This information is
+ * subsequent used by the {@link} LearningAlgorithm class in the plan selection
+ * process.
+ *
+ * @author João Faccin
+ */
public class PlanMetadata {
public static final String METADATA_NAME = PlanMetadata.class
.getSimpleName();
-
- public static final int MIN_PLAN_EXECUTIONS = 50;
-
+
+ private final int MIN_PLAN_EXECUTIONS;
+ private final int LEARNING_GAP;
+
private Plan plan;
private Softgoal softgoal;
private Outcome outcome;
@@ -21,9 +32,35 @@ public class PlanMetadata {
private ArrayList<InfluenceFactor> influenceFactors;
private String currentInstance;
private int planExecutionsCounter;
+ private Classifier model;
+ private String filePath;
+ /**
+ * Creates a new instance of plan metadata relating a plan to a specific
+ * softgoal.
+ *
+ * @param plan
+ * A plan which this metadata is related.
+ * @param softgoal
+ * A softgoal which this metadata refers to.
+ * @param outcome
+ * An outcome to be monitored in each plan execution.
+ * @param optFunction
+ * An optimization function.
+ * @param modelClass
+ * The learning algorithm which will be used in the learning
+ * process.
+ * @param minPlanExecutions
+ * An integer indicating the minimum number of plan's executions
+ * to be performed before the first learning process.
+ * @param learningGap
+ * An integer indicating the interval of plan's executions
+ * between two learning processes.
+ */
public PlanMetadata(Plan plan, Softgoal softgoal, Outcome outcome,
- OptimizationFunction optFunction) {
+ OptimizationFunction optFunction,
+ Class<? extends Classifier> modelClass, int minPlanExecutions,
+ int learningGap) {
this.plan = plan;
this.softgoal = softgoal;
this.outcome = outcome;
@@ -31,11 +68,47 @@ public class PlanMetadata {
this.influenceFactors = new ArrayList<>();
this.currentInstance = new String();
this.planExecutionsCounter = 0;
+ this.filePath = FileSystems.getDefault().getPath("").toString();
+ this.MIN_PLAN_EXECUTIONS = minPlanExecutions;
+ this.LEARNING_GAP = learningGap;
+ try {
+ model = modelClass.newInstance();
+ } catch (InstantiationException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
}
+ /**
+ * Creates a new instance of plan metadata relating a plan to a specific
+ * softgoal.
+ *
+ * @param plan
+ * A plan which this metadata is related.
+ * @param softgoal
+ * A softgoal which this metadata refers to.
+ * @param outcome
+ * An outcome to be monitored in each plan execution.
+ * @param optFunction
+ * An optimization function.
+ * @param influenceFactors
+ * A set of influence factors related to an outcome.
+ * @param modelClass
+ * The learning algorithm which will be used in the learning
+ * process.
+ * @param minPlanExecutions
+ * An integer indicating the minimum number of plan's executions
+ * to be performed before the first learning process.
+ * @param learningGap
+ * An integer indicating the interval of plan's executions
+ * between two learning processes.
+ */
public PlanMetadata(Plan plan, Softgoal softgoal, Outcome outcome,
OptimizationFunction optFunction,
- ArrayList<InfluenceFactor> influenceFactors) {
+ ArrayList<InfluenceFactor> influenceFactors,
+ Class<? extends Classifier> modelClass, int minPlanExecutions,
+ int learningGap) {
this.plan = plan;
this.softgoal = softgoal;
this.outcome = outcome;
@@ -43,12 +116,45 @@ public class PlanMetadata {
this.influenceFactors = influenceFactors;
this.currentInstance = new String();
this.planExecutionsCounter = 0;
+ this.filePath = FileSystems.getDefault().getPath("").toString();
+ this.MIN_PLAN_EXECUTIONS = minPlanExecutions;
+ this.LEARNING_GAP = learningGap;
+ try {
+ model = modelClass.newInstance();
+ } catch (InstantiationException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
}
+ /**
+ * Returns the prediction model built using the learning algorithm specified
+ * in the {@link} PlanMetadata constructor.
+ *
+ * @return The prediction model.
+ */
+ public Classifier getModel() {
+ return model;
+ }
+
+ /**
+ * Adds an influence factor to the existing set of influence factors.
+ *
+ * @param influenceFactor
+ */
public void addInfluenceFactor(InfluenceFactor influenceFactor) {
this.influenceFactors.add(influenceFactor);
}
+ public int getLearningGap() {
+ return this.LEARNING_GAP;
+ }
+
+ public int getMinPlanExecutions() {
+ return this.MIN_PLAN_EXECUTIONS;
+ }
+
public Outcome getOutcome() {
return this.outcome;
}
@@ -60,26 +166,47 @@ public class PlanMetadata {
public ArrayList<InfluenceFactor> getInfluenceFactors() {
return this.influenceFactors;
}
-
+
public int getPlanExecutionsCounter() {
return this.planExecutionsCounter;
}
-
+
+ /**
+ * Increases the plan executions counter.
+ */
public void increasePlanExecutionsCounter() {
this.planExecutionsCounter++;
}
+ /**
+ * Represents the notification of a started plan execution.
+ */
public void getNotifiedAtStartedPlanExecution() {
updateCurrentInstance();
this.outcome.startMeasurement();
}
+ /**
+ * Represents the notification of an already ended plan execution.
+ */
public void getNotifiedAtEndedPlanExecution() {
this.outcome.endMeasurement();
+
this.currentInstance = currentInstance + this.outcome.getMeasurement();
saveInstance();
}
+ public void setFilePath(String filePath) {
+ this.filePath = filePath;
+ }
+
+ public String getFilePath() {
+ return this.filePath;
+ }
+
+ /**
+ * Stores an instance with the current values of influence factors.
+ */
private void updateCurrentInstance() {
for (InfluenceFactor influenceFactor : influenceFactors) {
this.currentInstance = this.currentInstance
@@ -87,25 +214,29 @@ public class PlanMetadata {
}
}
+ /**
+ * Writes the current instance in a specific file.
+ */
private void saveInstance() {
- String filePath = "instances/"
- + this.plan.getClass().getSimpleName().toLowerCase() + "_"
- + this.softgoal + ".arff";
+ String filePath = this.filePath
+ + (this.plan.getId() + "_"
+ + this.plan.getClass().getSimpleName() + "_" + this.softgoal)
+ .toLowerCase() + ".arff";
try {
Utils.writeToFile(filePath, this.currentInstance);
} catch (IOException e) {
- System.out.println("A problem occurred when trying to save a context instance!");
+ System.out
+ .println("A problem occurred when trying to save a context instance!");
e.printStackTrace();
}
this.currentInstance = "";
}
- /*
- * This method returns a string in the format:
- * @relation relation
- * @attribute attr1 numeric
- * @attribute attr2 numeric
- * @data
+ /**
+ * Returns a string with the specific format of a header of the .arff file
+ * used in the learning process.
+ *
+ * @return An .arff file header.
*/
public String getArffFileHeader() {
String lineSeparator = System.getProperty("line.separator");
@@ -116,12 +247,13 @@ public class PlanMetadata {
header.append(relation);
for (InfluenceFactor influenceFactor : influenceFactors) {
- header.append("@attribute ");
- header.append(influenceFactor.getBeliefName());
- header.append(" numeric");
+ header.append(influenceFactor);
header.append(lineSeparator);
}
+ header.append(outcome);
+ header.append(lineSeparator);
+
header.append("@data");
header.append(lineSeparator);
return header.toString();
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/util/Utils.java b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/util/Utils.java
index c1fdc73..3c7a8ea 100644
--- a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/util/Utils.java
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/util/Utils.java
@@ -4,19 +4,31 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
+/**
+ * Implements useful methods to be used in general applications.
+ *
+ * @author João Faccin
+ */
public class Utils {
public Utils() {
}
- public static void writeToFile(String filePath, String text) throws IOException {
+ /**
+ * Writes a given text into a file specified in parameters.
+ *
+ * @param filePath
+ * Specifies a path to a file which a text will be write.
+ * @param text
+ * A string to be write in filePath.
+ * @throws IOException
+ */
+ public static void writeToFile(String filePath, String text)
+ throws IOException {
FileWriter writer = new FileWriter(filePath, true);
-
PrintWriter lineWriter = new PrintWriter(writer);
lineWriter.printf("%s" + "%n", text);
-
lineWriter.close();
-
}
}
\ No newline at end of file