bdi4jade
Changes
bdi-jade-extensions/.classpath 21(+11 -10)
bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/InfluenceFactor.java 21(+21 -0)
bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningAlgorithm.java 10(+10 -0)
bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/learningalgorithm/LinearRegressionAlgorithm.java 92(+92 -0)
bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedCapability.java 24(+24 -0)
bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedPlanBody.java 35(+35 -0)
bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedPlanSelectionStrategy.java 63(+63 -0)
bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/OptimizationFunction.java 5(+5 -0)
Details
bdi-jade-extensions/.classpath 21(+11 -10)
diff --git a/bdi-jade-extensions/.classpath b/bdi-jade-extensions/.classpath
index e0b1538..4b3c509 100644
--- a/bdi-jade-extensions/.classpath
+++ b/bdi-jade-extensions/.classpath
@@ -1,10 +1,11 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry combineaccessrules="false" kind="src" path="/bdi-jade"/>
- <classpathentry kind="lib" path="/bdi-jade/lib/commons-logging-1.1.3.jar"/>
- <classpathentry kind="lib" path="/bdi-jade/lib/jade-4.3.2.jar"/>
- <classpathentry kind="lib" path="/bdi-jade/lib/log4j-1.2.17.jar"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/bdi-jade"/>
+ <classpathentry kind="lib" path="/bdi-jade/lib/commons-logging-1.1.3.jar"/>
+ <classpathentry kind="lib" path="/bdi-jade/lib/jade-4.3.2.jar"/>
+ <classpathentry kind="lib" path="/bdi-jade/lib/log4j-1.2.17.jar"/>
+ <classpathentry kind="lib" path="src/bdi4jade/extension/planselection/learningbased/lib/weka.jar"/>
+ <classpathentry kind="output" path="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
new file mode 100644
index 0000000..e2a98e4
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/InfluenceFactor.java
@@ -0,0 +1,21 @@
+package bdi4jade.extension.planselection.learningbased;
+
+import bdi4jade.belief.Belief;
+
+public class InfluenceFactor {
+
+ private Belief<?, ?> belief;
+
+ public InfluenceFactor(Belief<?, ?> belief) {
+ this.belief = belief;
+ }
+
+ public String getBeliefName() {
+ return (String) this.belief.getName();
+ }
+
+ public Object getBeliefValue() {
+ return this.belief.getValue();
+ }
+
+}
\ No newline at end of file
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningAlgorithm.java b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningAlgorithm.java
new file mode 100644
index 0000000..f7ad425
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningAlgorithm.java
@@ -0,0 +1,10 @@
+package bdi4jade.extension.planselection.learningbased;
+
+import bdi4jade.goal.Softgoal;
+import bdi4jade.plan.Plan;
+
+public interface LearningAlgorithm {
+
+ public double predictExpectedContribution(Plan plan, Softgoal softgoal);
+
+}
\ 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
new file mode 100644
index 0000000..107cbd5
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/learningalgorithm/LinearRegressionAlgorithm.java
@@ -0,0 +1,92 @@
+package bdi4jade.extension.planselection.learningbased.learningalgorithm;
+
+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.classifiers.functions.LinearRegression;
+import weka.core.DenseInstance;
+import weka.core.Instance;
+import weka.core.Instances;
+import bdi4jade.extension.planselection.learningbased.LearningAlgorithm;
+import bdi4jade.extension.planselection.learningbased.PlanMetadata;
+import bdi4jade.extension.planselection.learningbased.util.Utils;
+import bdi4jade.goal.Softgoal;
+import bdi4jade.plan.Plan;
+
+public class LinearRegressionAlgorithm implements LearningAlgorithm {
+
+ private Instances trainingInstances;
+ private LinearRegression model;
+
+ @Override
+ @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.MIN_PLAN_EXECUTIONS) {
+ String filePath = "instances/"
+ + plan.getClass().getSimpleName().toLowerCase() + "_"
+ + softgoal + ".arff";
+ if (!new File(filePath).exists()) {
+ try {
+ Utils.writeToFile(filePath,
+ planMetadata.getArffFileHeader());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ planMetadata.increasePlanExecutionsCounter();
+ } else {
+ 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 = model.classifyInstance(instance);
+ // System.out.println("Current Instance (" + instance + "): " +
+ // prediction);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ return prediction;
+ }
+
+ private void learnFromTrainingSet(Plan plan, Softgoal softgoal) {
+ try {
+ trainingInstances = new Instances(new BufferedReader(
+ new FileReader("instances/"
+ + plan.getClass().getSimpleName().toLowerCase()
+ + "_" + softgoal + ".arff")));
+
+ trainingInstances
+ .setClassIndex(trainingInstances.numAttributes() - 1);
+
+ model = new LinearRegression();
+ model.buildClassifier(trainingInstances);
+
+ } 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/LearningBasedCapability.java b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedCapability.java
new file mode 100644
index 0000000..991fedc
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedCapability.java
@@ -0,0 +1,24 @@
+package bdi4jade.extension.planselection.learningbased;
+
+import bdi4jade.annotation.Belief;
+import bdi4jade.core.Capability;
+import bdi4jade.extension.planselection.utilitybased.SoftgoalPreferences;
+
+public class LearningBasedCapability extends Capability {
+
+ private static final long serialVersionUID = -1044132085270106726L;
+
+ @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.
+ */
+ public LearningBasedCapability(LearningAlgorithm learningAlgorithm) {
+ setPlanSelectionStrategy(new LearningBasedPlanSelectionStrategy(
+ learningAlgorithm));
+ }
+
+}
\ 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
new file mode 100644
index 0000000..3bba0f1
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedPlanBody.java
@@ -0,0 +1,35 @@
+package bdi4jade.extension.planselection.learningbased;
+
+import java.util.Collection;
+import java.util.Map;
+
+import bdi4jade.goal.Softgoal;
+import bdi4jade.plan.planbody.AbstractPlanBody;
+
+public abstract class LearningBasedPlanBody extends AbstractPlanBody {
+
+ private static final long serialVersionUID = -5064965263121492233L;
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void onStart() {
+ Collection<PlanMetadata> planMetadata = ((Map<Softgoal, PlanMetadata>) this
+ .getPlan().getMetadata(PlanMetadata.METADATA_NAME)).values();
+
+ for (PlanMetadata metadata : planMetadata) {
+ metadata.getNotifiedAtStartedPlanExecution();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public int onEnd() {
+ Collection<PlanMetadata> planMetadata = ((Map<Softgoal, PlanMetadata>) this
+ .getPlan().getMetadata(PlanMetadata.METADATA_NAME)).values();
+
+ for (PlanMetadata metadata : planMetadata) {
+ metadata.getNotifiedAtEndedPlanExecution();
+ }
+ 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
new file mode 100644
index 0000000..dc83e44
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/LearningBasedPlanSelectionStrategy.java
@@ -0,0 +1,63 @@
+package bdi4jade.extension.planselection.learningbased;
+
+import java.util.Set;
+
+import bdi4jade.extension.planselection.utilitybased.SoftgoalPreferences;
+import bdi4jade.goal.Goal;
+import bdi4jade.goal.Softgoal;
+import bdi4jade.plan.Plan;
+import bdi4jade.reasoning.AbstractReasoningStrategy;
+import bdi4jade.reasoning.PlanSelectionStrategy;
+
+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.
+ */
+ public LearningBasedPlanSelectionStrategy(
+ LearningAlgorithm learningAlgorithm) {
+ this.learningAlgorithm = learningAlgorithm;
+ }
+
+ @Override
+ public Plan selectPlan(Goal goal, Set<Plan> candidatePlans) {
+ Plan selectedPlan = null;
+ Double maxContribution = null;
+
+ for (Plan plan : candidatePlans) {
+ double contribution = 0;
+
+ SoftgoalPreferences preferences = (SoftgoalPreferences) plan
+ .getPlanLibrary().getCapability().getBeliefBase()
+ .getBelief(SoftgoalPreferences.NAME);
+
+ for (Softgoal softgoal : capability.getMyAgent().getSoftgoals()) {
+ Double preference = preferences
+ .getPreferenceForSoftgoal(softgoal);
+
+ if (preference != null) {
+ double expectedContribution = learningAlgorithm
+ .predictExpectedContribution(plan, softgoal);
+ contribution += preference * expectedContribution;
+ }
+ }
+
+ if (selectedPlan == null || maxContribution < contribution) {
+ selectedPlan = plan;
+ maxContribution = contribution;
+ }
+
+ }
+ return selectedPlan;
+ }
+
+}
\ No newline at end of file
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/lib/weka.jar b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/lib/weka.jar
new file mode 100644
index 0000000..e5bc6c0
Binary files /dev/null and b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/lib/weka.jar differ
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/OptimizationFunction.java b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/OptimizationFunction.java
new file mode 100644
index 0000000..ca87a99
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/OptimizationFunction.java
@@ -0,0 +1,5 @@
+package bdi4jade.extension.planselection.learningbased;
+
+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
new file mode 100644
index 0000000..30e7cd0
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/Outcome.java
@@ -0,0 +1,26 @@
+package bdi4jade.extension.planselection.learningbased;
+
+public abstract class Outcome {
+
+ private String name;
+
+ public Outcome(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ /*
+ * 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.
+ */
+ public abstract double getMeasurement();
+
+ public void startMeasurement() {}
+
+ public void endMeasurement() {}
+
+}
\ 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
new file mode 100644
index 0000000..68156c7
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/PlanMetadata.java
@@ -0,0 +1,129 @@
+package bdi4jade.extension.planselection.learningbased;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import bdi4jade.extension.planselection.learningbased.util.Utils;
+import bdi4jade.goal.Softgoal;
+import bdi4jade.plan.Plan;
+
+public class PlanMetadata {
+
+ public static final String METADATA_NAME = PlanMetadata.class
+ .getSimpleName();
+
+ public static final int MIN_PLAN_EXECUTIONS = 50;
+
+ private Plan plan;
+ private Softgoal softgoal;
+ private Outcome outcome;
+ private OptimizationFunction optFunction;
+ private ArrayList<InfluenceFactor> influenceFactors;
+ private String currentInstance;
+ private int planExecutionsCounter;
+
+ public PlanMetadata(Plan plan, Softgoal softgoal, Outcome outcome,
+ OptimizationFunction optFunction) {
+ this.plan = plan;
+ this.softgoal = softgoal;
+ this.outcome = outcome;
+ this.optFunction = optFunction;
+ this.influenceFactors = new ArrayList<>();
+ this.currentInstance = new String();
+ this.planExecutionsCounter = 0;
+ }
+
+ public PlanMetadata(Plan plan, Softgoal softgoal, Outcome outcome,
+ OptimizationFunction optFunction,
+ ArrayList<InfluenceFactor> influenceFactors) {
+ this.plan = plan;
+ this.softgoal = softgoal;
+ this.outcome = outcome;
+ this.optFunction = optFunction;
+ this.influenceFactors = influenceFactors;
+ this.currentInstance = new String();
+ this.planExecutionsCounter = 0;
+ }
+
+ public void addInfluenceFactor(InfluenceFactor influenceFactor) {
+ this.influenceFactors.add(influenceFactor);
+ }
+
+ public Outcome getOutcome() {
+ return this.outcome;
+ }
+
+ public OptimizationFunction getOptimizationFunction() {
+ return this.optFunction;
+ }
+
+ public ArrayList<InfluenceFactor> getInfluenceFactors() {
+ return this.influenceFactors;
+ }
+
+ public int getPlanExecutionsCounter() {
+ return this.planExecutionsCounter;
+ }
+
+ public void increasePlanExecutionsCounter() {
+ this.planExecutionsCounter++;
+ }
+
+ public void getNotifiedAtStartedPlanExecution() {
+ updateCurrentInstance();
+ this.outcome.startMeasurement();
+ }
+
+ public void getNotifiedAtEndedPlanExecution() {
+ this.outcome.endMeasurement();
+ this.currentInstance = currentInstance + this.outcome.getMeasurement();
+ saveInstance();
+ }
+
+ private void updateCurrentInstance() {
+ for (InfluenceFactor influenceFactor : influenceFactors) {
+ this.currentInstance = this.currentInstance
+ + influenceFactor.getBeliefValue() + ",";
+ }
+ }
+
+ private void saveInstance() {
+ String filePath = "instances/"
+ + this.plan.getClass().getSimpleName().toLowerCase() + "_"
+ + this.softgoal + ".arff";
+ try {
+ Utils.writeToFile(filePath, this.currentInstance);
+ } catch (IOException e) {
+ 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
+ */
+ public String getArffFileHeader() {
+ String lineSeparator = System.getProperty("line.separator");
+ String relation = "@relation " + this.plan.getClass().getSimpleName()
+ + "-" + this.softgoal + lineSeparator;
+
+ StringBuilder header = new StringBuilder();
+ header.append(relation);
+
+ for (InfluenceFactor influenceFactor : influenceFactors) {
+ header.append("@attribute ");
+ header.append(influenceFactor.getBeliefName());
+ header.append(" numeric");
+ header.append(lineSeparator);
+ }
+
+ header.append("@data");
+ header.append(lineSeparator);
+ return header.toString();
+ }
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..c1fdc73
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/planselection/learningbased/util/Utils.java
@@ -0,0 +1,22 @@
+package bdi4jade.extension.planselection.learningbased.util;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+public class Utils {
+
+ public Utils() {
+ }
+
+ 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