bdi4jade

Changes

bdi-jade/.classpath 24(+12 -12)

Details

bdi-jade/.classpath 24(+12 -12)

diff --git a/bdi-jade/.classpath b/bdi-jade/.classpath
index c21aed9..cbac2e1 100644
--- a/bdi-jade/.classpath
+++ b/bdi-jade/.classpath
@@ -1,12 +1,12 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="src" path="extensions-src"/>
-	<classpathentry kind="src" path="examples-src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
-	<classpathentry kind="lib" path="lib/jade-4.3.2.jar"/>
-	<classpathentry kind="lib" path="lib/commons-logging-1.1.3.jar"/>
-	<classpathentry kind="lib" path="lib/log4j-1.2.17.jar"/>
-	<classpathentry kind="lib" path="/bdi-jade-extensions/lib/weka.jar"/>
-	<classpathentry kind="output" path="bin"/>
-</classpath>
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="extensions-src"/>
+	<classpathentry kind="src" path="examples-src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="lib" path="lib/jade-4.3.2.jar"/>
+	<classpathentry kind="lib" path="lib/commons-logging-1.1.3.jar"/>
+	<classpathentry kind="lib" path="lib/log4j-1.2.17.jar"/>
+	<classpathentry kind="lib" path="/bdi-jade-extensions/lib/weka.jar"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bdi-jade/.project b/bdi-jade/.project
index 4125a50..d900c35 100644
--- a/bdi-jade/.project
+++ b/bdi-jade/.project
@@ -18,12 +18,12 @@
 		<link>
 			<name>examples-src</name>
 			<type>2</type>
-			<location>D:/ingrid/Workspaces/mas-research/bdi4jade/bdi-jade-test/src</location>
+			<location>/Users/ingridnunes/Documents/workspaces/aamas-2107/bdi4jade/bdi-jade-test/src</location>
 		</link>
 		<link>
 			<name>extensions-src</name>
 			<type>2</type>
-			<location>D:/ingrid/Workspaces/mas-research/bdi4jade/bdi-jade-extensions/src</location>
+			<location>/Users/ingridnunes/Documents/workspaces/aamas-2107/bdi4jade/bdi-jade-extensions/src</location>
 		</link>
 	</linkedResources>
 </projectDescription>
diff --git a/bdi-jade/src/bdi4jade/belief/DerivedPredicate.java b/bdi-jade/src/bdi4jade/belief/DerivedPredicate.java
index a7491f0..0293ee9 100644
--- a/bdi-jade/src/bdi4jade/belief/DerivedPredicate.java
+++ b/bdi-jade/src/bdi4jade/belief/DerivedPredicate.java
@@ -29,8 +29,7 @@ package bdi4jade.belief;
  * 
  * @author Ingrid Nunes
  */
-public abstract class DerivedPredicate<K> extends DerivedBelief<K, Boolean>
-		implements Predicate<K> {
+public abstract class DerivedPredicate<K> extends DerivedBelief<K, Boolean> implements PredicateBelief<K> {
 
 	private static final long serialVersionUID = -1551397656846999182L;
 
@@ -53,4 +52,17 @@ public abstract class DerivedPredicate<K> extends DerivedBelief<K, Boolean>
 		super(name);
 	}
 
+	@Override
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+		Boolean value = getValue();
+		if (value == null) {
+			sb.append("not ");
+		} else if (!value) {
+			sb.append("~");
+		}
+		sb.append(getName());
+		return sb.toString();
+	}
+
 }
diff --git a/bdi-jade/src/bdi4jade/belief/TransientPredicate.java b/bdi-jade/src/bdi4jade/belief/TransientPredicate.java
index fe39162..b16fbb6 100644
--- a/bdi-jade/src/bdi4jade/belief/TransientPredicate.java
+++ b/bdi-jade/src/bdi4jade/belief/TransientPredicate.java
@@ -28,8 +28,7 @@ package bdi4jade.belief;
  * 
  * @author Ingrid Nunes
  */
-public class TransientPredicate<K> extends TransientBelief<K, Boolean>
-		implements Predicate<K> {
+public class TransientPredicate<K> extends TransientBelief<K, Boolean> implements PredicateBelief<K> {
 
 	private static final long serialVersionUID = -2315938302480821432L;
 
@@ -64,4 +63,16 @@ public class TransientPredicate<K> extends TransientBelief<K, Boolean>
 		super(name, value);
 	}
 
+	@Override
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+		if (getValue() == null) {
+			sb.append("not ");
+		} else if (!value) {
+			sb.append("~");
+		}
+		sb.append(getName());
+		return sb.toString();
+	}
+
 }
diff --git a/bdi-jade/src/bdi4jade/core/AbstractBDIAgent.java b/bdi-jade/src/bdi4jade/core/AbstractBDIAgent.java
index 401ee41..67f68b6 100644
--- a/bdi-jade/src/bdi4jade/core/AbstractBDIAgent.java
+++ b/bdi-jade/src/bdi4jade/core/AbstractBDIAgent.java
@@ -22,11 +22,6 @@
 
 package bdi4jade.core;
 
-import jade.core.Agent;
-import jade.core.behaviours.CyclicBehaviour;
-import jade.lang.acl.ACLMessage;
-import jade.proto.states.MsgReceiver;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -57,6 +52,10 @@ import bdi4jade.reasoning.DefaultAgentDeliberationFunction;
 import bdi4jade.reasoning.DefaultAgentOptionGenerationFunction;
 import bdi4jade.reasoning.DefaultAgentPlanSelectionStrategy;
 import bdi4jade.util.ReflectionUtils;
+import jade.core.Agent;
+import jade.core.behaviours.CyclicBehaviour;
+import jade.lang.acl.ACLMessage;
+import jade.proto.states.MsgReceiver;
 
 /**
  * This class is an abstract implementation of the {@link BDIAgent} interface.
@@ -119,36 +118,27 @@ public abstract class AbstractBDIAgent extends Agent implements BDIAgent {
 				GoalUpdateSet agentGoalUpdateSet = processIntentions(agentIntentions);
 				Map<Capability, GoalUpdateSet> capabilityGoalUpdateSets = new HashMap<>();
 				for (Capability capability : capabilities) {
-					GoalUpdateSet capabilityGoalUpdateSet = processIntentions(capability
-							.getIntentions());
-					capabilityGoalUpdateSets.put(capability,
-							capabilityGoalUpdateSet);
+					GoalUpdateSet capabilityGoalUpdateSet = processIntentions(capability.getIntentions());
+					capabilityGoalUpdateSets.put(capability, capabilityGoalUpdateSet);
 				}
 
 				// Generating new goals and choosing goals to drop
-				optionGenerationFunction.generateGoals(agentGoalUpdateSet,
-						capabilityGoalUpdateSets);
+				optionGenerationFunction.generateGoals(agentGoalUpdateSet, capabilityGoalUpdateSets);
 
 				// Adding generated goals
-				for (GoalDescription goal : agentGoalUpdateSet
-						.getGeneratedGoals()) {
+				for (GoalDescription goal : agentGoalUpdateSet.getGeneratedGoals()) {
 					try {
-						Intention intention = addIntention(
-								goal.getDispatcher(), goal.getGoal(),
-								goal.getListener());
+						Intention intention = addIntention(goal.getDispatcher(), goal.getGoal(), goal.getListener());
 						if (intention != null)
 							agentGoalUpdateSet.addIntention(intention);
 					} catch (IllegalAccessException exc) {
 						log.error(exc);
 					}
 				}
-				for (GoalUpdateSet goalUpdateSet : capabilityGoalUpdateSets
-						.values()) {
-					for (GoalDescription goal : goalUpdateSet
-							.getGeneratedGoals()) {
+				for (GoalUpdateSet goalUpdateSet : capabilityGoalUpdateSets.values()) {
+					for (GoalDescription goal : goalUpdateSet.getGeneratedGoals()) {
 						try {
-							Intention intention = addIntention(
-									goal.getDispatcher(), goal.getGoal(),
+							Intention intention = addIntention(goal.getDispatcher(), goal.getGoal(),
 									goal.getListener());
 							if (intention != null)
 								goalUpdateSet.addIntention(intention);
@@ -159,21 +149,18 @@ public abstract class AbstractBDIAgent extends Agent implements BDIAgent {
 				}
 
 				// Removing dropped goals
-				for (GoalDescription goal : agentGoalUpdateSet
-						.getDroppedGoals()) {
+				for (GoalDescription goal : agentGoalUpdateSet.getDroppedGoals()) {
 					goal.getIntention().noLongerDesire();
 					fireGoalEvent(goal.getIntention());
 					agentIntentions.remove(goal.getIntention());
 					allIntentions.remove(goal.getGoal());
 					agentGoalUpdateSet.removeIntention(goal);
 				}
-				for (GoalUpdateSet goalUpdateSet : capabilityGoalUpdateSets
-						.values()) {
+				for (GoalUpdateSet goalUpdateSet : capabilityGoalUpdateSets.values()) {
 					for (GoalDescription goal : goalUpdateSet.getDroppedGoals()) {
 						goal.getIntention().noLongerDesire();
 						fireGoalEvent(goal.getIntention());
-						goal.getDispatcher().removeIntention(
-								goal.getIntention());
+						goal.getDispatcher().removeIntention(goal.getIntention());
 						allIntentions.remove(goal.getGoal());
 						goalUpdateSet.removeIntention(goal);
 					}
@@ -182,14 +169,12 @@ public abstract class AbstractBDIAgent extends Agent implements BDIAgent {
 				// Filtering options
 				Map<Capability, Set<GoalDescription>> capabilityGoals = new HashMap<>();
 				for (Capability capability : capabilityGoalUpdateSets.keySet()) {
-					capabilityGoals.put(capability, capabilityGoalUpdateSets
-							.get(capability).getCurrentGoals());
+					capabilityGoals.put(capability, capabilityGoalUpdateSets.get(capability).getCurrentGoals());
 				}
-				Set<Goal> selectedGoals = deliberationFunction.filter(
-						agentGoalUpdateSet.getCurrentGoals(), capabilityGoals);
+				Set<Goal> selectedGoals = deliberationFunction.filter(agentGoalUpdateSet.getCurrentGoals(),
+						capabilityGoals);
 
-				log.trace("Selected goals to be intentions: "
-						+ selectedGoals.size());
+				log.trace("Selected goals to be intentions: " + selectedGoals.size());
 				for (Intention intention : allIntentions.values()) {
 					if (selectedGoals.contains(intention.getGoal())) {
 						intention.tryToAchive();
@@ -310,8 +295,7 @@ public abstract class AbstractBDIAgent extends Agent implements BDIAgent {
 	 *      bdi4jade.goal.Goal, bdi4jade.event.GoalListener)
 	 */
 	@Override
-	public final boolean addGoal(Capability dispatcher, Goal goal,
-			GoalListener goalListener) {
+	public final boolean addGoal(Capability dispatcher, Goal goal, GoalListener goalListener) {
 		try {
 			addIntention(dispatcher, goal, goalListener);
 			return true;
@@ -351,6 +335,22 @@ public abstract class AbstractBDIAgent extends Agent implements BDIAgent {
 	}
 
 	/**
+	 * @see bdi4jade.core.BDIAgent#addGoalListener(bdi4jade.goal.Goal,
+	 *      bdi4jade.event.GoalListener)
+	 */
+	@Override
+	public boolean addGoalListener(Goal goal, GoalListener goalListener) {
+		synchronized (allIntentions) {
+			Intention intention = this.allIntentions.get(goal);
+			if (intention != null) {
+				intention.addGoalListener(goalListener);
+				return true;
+			}
+			return false;
+		}
+	}
+
+	/**
 	 * @see bdi4jade.core.BDIAgent#addGoalListener(bdi4jade.event.GoalListener)
 	 */
 	@Override
@@ -371,8 +371,8 @@ public abstract class AbstractBDIAgent extends Agent implements BDIAgent {
 	 * @param goalListener
 	 *            the listener to be notified.
 	 */
-	private final Intention addIntention(Capability dispatcher, Goal goal,
-			GoalListener goalListener) throws IllegalAccessException {
+	private final Intention addIntention(Capability dispatcher, Goal goal, GoalListener goalListener)
+			throws IllegalAccessException {
 		Intention intention = null;
 		synchronized (allIntentions) {
 			intention = allIntentions.get(goal);
@@ -479,8 +479,7 @@ public abstract class AbstractBDIAgent extends Agent implements BDIAgent {
 	private final void fireGoalEvent(Intention intention) {
 		Goal goal = intention.getGoal();
 		GoalStatus status = intention.getStatus();
-		log.debug("Goal: " + goal.getClass().getSimpleName() + " (" + status
-				+ ") - " + goal);
+		log.debug("Goal: " + goal.getClass().getSimpleName() + " (" + status + ") - " + goal);
 
 		GoalEvent goalEvent = new GoalEvent(goal, status);
 		synchronized (goalListeners) {
@@ -565,15 +564,12 @@ public abstract class AbstractBDIAgent extends Agent implements BDIAgent {
 	 * @return the capability instances related to this capability that owns the
 	 *         goal, or an empty set if the agent cannot add this goal.
 	 */
-	protected final Set<Capability> getGoalOwner(
-			Class<? extends Capability> owner, boolean internal) {
+	protected final Set<Capability> getGoalOwner(Class<? extends Capability> owner, boolean internal) {
 		if (internal) {
 			return new HashSet<Capability>();
 		} else {
-			Set<Capability> restrictedAccessOwners = restrictedAccessOwnersMap
-					.get(owner);
-			return restrictedAccessOwners == null ? new HashSet<Capability>()
-					: restrictedAccessOwners;
+			Set<Capability> restrictedAccessOwners = restrictedAccessOwnersMap.get(owner);
+			return restrictedAccessOwners == null ? new HashSet<Capability>() : restrictedAccessOwners;
 		}
 	}
 
@@ -696,8 +692,7 @@ public abstract class AbstractBDIAgent extends Agent implements BDIAgent {
 			for (Capability capability : addedCapabilities) {
 				if (capability.getMyAgent() != null) {
 					throw new IllegalArgumentException(
-							"Capability already binded to another agent: "
-									+ capability.getFullId());
+							"Capability already binded to another agent: " + capability.getFullId());
 				}
 				capability.setMyAgent(this);
 			}
@@ -718,8 +713,7 @@ public abstract class AbstractBDIAgent extends Agent implements BDIAgent {
 	 * @param beliefRevisionStrategy
 	 *            the beliefRevisionStrategy to set.
 	 */
-	public final void setBeliefRevisionStrategy(
-			AgentBeliefRevisionStrategy beliefRevisionStrategy) {
+	public final void setBeliefRevisionStrategy(AgentBeliefRevisionStrategy beliefRevisionStrategy) {
 		if (beliefRevisionStrategy == null) {
 			this.beliefRevisionStrategy = new DefaultAgentBeliefRevisionStrategy();
 		} else {
@@ -735,8 +729,7 @@ public abstract class AbstractBDIAgent extends Agent implements BDIAgent {
 	 * @param deliberationFunction
 	 *            the deliberationFunction to set.
 	 */
-	public final void setDeliberationFunction(
-			AgentDeliberationFunction deliberationFunction) {
+	public final void setDeliberationFunction(AgentDeliberationFunction deliberationFunction) {
 		if (deliberationFunction == null) {
 			this.deliberationFunction = new DefaultAgentDeliberationFunction();
 		} else {
@@ -752,8 +745,7 @@ public abstract class AbstractBDIAgent extends Agent implements BDIAgent {
 	 * @param optionGenerationFunction
 	 *            the optionGenerationFunction to set.
 	 */
-	public final void setOptionGenerationFunction(
-			AgentOptionGenerationFunction optionGenerationFunction) {
+	public final void setOptionGenerationFunction(AgentOptionGenerationFunction optionGenerationFunction) {
 		if (optionGenerationFunction == null) {
 			this.optionGenerationFunction = new DefaultAgentOptionGenerationFunction();
 		} else {
@@ -769,8 +761,7 @@ public abstract class AbstractBDIAgent extends Agent implements BDIAgent {
 	 * @param planSelectionStrategy
 	 *            the planSelectionStrategy to set.
 	 */
-	public final void setPlanSelectionStrategy(
-			AgentPlanSelectionStrategy planSelectionStrategy) {
+	public final void setPlanSelectionStrategy(AgentPlanSelectionStrategy planSelectionStrategy) {
 		if (planSelectionStrategy == null) {
 			this.planSelectionStrategy = new DefaultAgentPlanSelectionStrategy();
 		} else {
diff --git a/bdi-jade/src/bdi4jade/core/BDIAgent.java b/bdi-jade/src/bdi4jade/core/BDIAgent.java
index 82ceaba..917013c 100644
--- a/bdi-jade/src/bdi4jade/core/BDIAgent.java
+++ b/bdi-jade/src/bdi4jade/core/BDIAgent.java
@@ -22,17 +22,6 @@
 
 package bdi4jade.core;
 
-import jade.content.ContentManager;
-import jade.core.AID;
-import jade.core.Agent;
-import jade.core.AgentState;
-import jade.core.Location;
-import jade.core.ServiceException;
-import jade.core.ServiceHelper;
-import jade.core.Timer;
-import jade.lang.acl.ACLMessage;
-import jade.lang.acl.MessageTemplate;
-
 import java.util.Collection;
 import java.util.List;
 import java.util.Set;
@@ -45,6 +34,16 @@ import bdi4jade.reasoning.AgentBeliefRevisionStrategy;
 import bdi4jade.reasoning.AgentDeliberationFunction;
 import bdi4jade.reasoning.AgentOptionGenerationFunction;
 import bdi4jade.reasoning.AgentPlanSelectionStrategy;
+import jade.content.ContentManager;
+import jade.core.AID;
+import jade.core.Agent;
+import jade.core.AgentState;
+import jade.core.Location;
+import jade.core.ServiceException;
+import jade.core.ServiceHelper;
+import jade.core.Timer;
+import jade.lang.acl.ACLMessage;
+import jade.lang.acl.MessageTemplate;
 
 /**
  * This interfaces represents a BDIAgent that has a current set of goals, which
@@ -81,8 +80,7 @@ public interface BDIAgent {
 	 * 
 	 * @return true if the goal was added, false otherwise.
 	 */
-	public boolean addGoal(Capability dispatcher, Goal goal,
-			GoalListener goalListener);
+	public boolean addGoal(Capability dispatcher, Goal goal, GoalListener goalListener);
 
 	/**
 	 * Adds a new goal to this agent to be achieved.
@@ -108,6 +106,16 @@ public interface BDIAgent {
 	public boolean addGoal(Goal goal, GoalListener goalListener);
 
 	/**
+	 * Adds a listener to be notified when about events of a goal.
+	 * 
+	 * @param goal
+	 *            the goal to be monitored.
+	 * @param goalListener
+	 *            the listener to be notified.
+	 */
+	public boolean addGoalListener(Goal goal, GoalListener goalListener);
+
+	/**
 	 * Adds a listener to be notified when about goal events.
 	 * 
 	 * @param goalListener
@@ -406,7 +414,7 @@ public interface BDIAgent {
 	 * @see Agent#send(ACLMessage)
 	 */
 	public void send(ACLMessage msg);
-	
+
 	/**
 	 * @see Agent#setQueueSize(int)
 	 */
diff --git a/bdi-jade/src/bdi4jade/goal/NestedGoal.java b/bdi-jade/src/bdi4jade/goal/NestedGoal.java
new file mode 100644
index 0000000..40d0ff5
--- /dev/null
+++ b/bdi-jade/src/bdi4jade/goal/NestedGoal.java
@@ -0,0 +1,43 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2011  Ingrid Nunes
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+// 
+// To contact the authors:
+// http://inf.ufrgs.br/prosoft/bdi4jade/
+//
+//----------------------------------------------------------------------------
+
+package bdi4jade.goal;
+
+/**
+ * @author ingridnunes
+ *
+ */
+public class NestedGoal implements Goal {
+
+	private static final long serialVersionUID = -7779648429437829445L;
+
+	private final Goal goal;
+
+	public NestedGoal(Goal goal) {
+		this.goal = goal;
+	}
+
+	public Goal getGoal() {
+		return goal;
+	}
+
+}
diff --git a/bdi-jade/src/bdi4jade/plan/AbstractPlan.java b/bdi-jade/src/bdi4jade/plan/AbstractPlan.java
index 23d26fe..9e0de58 100644
--- a/bdi-jade/src/bdi4jade/plan/AbstractPlan.java
+++ b/bdi-jade/src/bdi4jade/plan/AbstractPlan.java
@@ -22,16 +22,16 @@
 
 package bdi4jade.plan;
 
-import jade.lang.acl.ACLMessage;
-import jade.lang.acl.MessageTemplate;
-
 import java.util.HashSet;
 import java.util.Set;
 
 import bdi4jade.core.MetadataElementImpl;
 import bdi4jade.goal.Goal;
 import bdi4jade.goal.GoalTemplate;
+import bdi4jade.goal.NestedGoal;
 import bdi4jade.message.MessageGoal;
+import jade.lang.acl.ACLMessage;
+import jade.lang.acl.MessageTemplate;
 
 /**
  * This class represents the plan abstraction, being an abstract implementation
@@ -89,8 +89,7 @@ public abstract class AbstractPlan extends MetadataElementImpl implements Plan {
 	 * @param messageTemplate
 	 *            the template of messages that this plan can process.
 	 */
-	public AbstractPlan(String id, GoalTemplate goalTemplate,
-			MessageTemplate messageTemplate) {
+	public AbstractPlan(String id, GoalTemplate goalTemplate, MessageTemplate messageTemplate) {
 		this();
 		if (id == null) {
 			throw new RuntimeException("Plan id cannot be null.");
@@ -162,7 +161,11 @@ public abstract class AbstractPlan extends MetadataElementImpl implements Plan {
 			canAchieve = canProcess(((MessageGoal) goal).getMessage());
 		} else {
 			for (GoalTemplate template : goalTemplates) {
-				if (template.match(goal)) {
+				Goal realGoal = goal;
+				if (goal instanceof NestedGoal) {
+					realGoal = ((NestedGoal) goal).getGoal();
+				}
+				if (template.match(realGoal)) {
 					canAchieve = true;
 					break;
 				}
diff --git a/bdi-jade/src/bdi4jade/plan/DefaultPlan.java b/bdi-jade/src/bdi4jade/plan/DefaultPlan.java
index 1fc7ef2..ecfbde9 100644
--- a/bdi-jade/src/bdi4jade/plan/DefaultPlan.java
+++ b/bdi-jade/src/bdi4jade/plan/DefaultPlan.java
@@ -22,9 +22,6 @@
 
 package bdi4jade.plan;
 
-import jade.core.behaviours.Behaviour;
-import jade.lang.acl.MessageTemplate;
-
 import java.lang.reflect.Modifier;
 
 import bdi4jade.core.BDIAgent;
@@ -34,6 +31,8 @@ import bdi4jade.goal.Goal;
 import bdi4jade.goal.GoalTemplate;
 import bdi4jade.goal.GoalTemplateFactory;
 import bdi4jade.plan.planbody.PlanBody;
+import jade.core.behaviours.Behaviour;
+import jade.lang.acl.MessageTemplate;
 
 /**
  * This class represents a plan whose plan body is a class that can be
@@ -45,9 +44,8 @@ import bdi4jade.plan.planbody.PlanBody;
  */
 public class DefaultPlan extends AbstractPlan {
 
-	private static String generateId(Class<? extends Goal> goalClass,
-			GoalTemplate goalTemplate, MessageTemplate messageTemplate,
-			Class<? extends PlanBody> planBodyClass) {
+	private static String generateId(Class<? extends Goal> goalClass, GoalTemplate goalTemplate,
+			MessageTemplate messageTemplate, Class<? extends PlanBody> planBodyClass) {
 		StringBuffer sb = new StringBuffer("[");
 		if (goalClass != null) {
 			sb.append(" ").append(goalClass.getName());
@@ -75,10 +73,8 @@ public class DefaultPlan extends AbstractPlan {
 	 * @param planBodyClass
 	 *            the class of this plan body.
 	 */
-	public DefaultPlan(Class<? extends Goal> goalClass,
-			Class<? extends PlanBody> planBodyClass) {
-		super(generateId(goalClass, null, null, planBodyClass),
-				GoalTemplateFactory.goalOfType(goalClass));
+	public DefaultPlan(Class<? extends Goal> goalClass, Class<? extends PlanBody> planBodyClass) {
+		super(generateId(goalClass, null, null, planBodyClass), GoalTemplateFactory.goalOfType(goalClass));
 		this.planBodyClass = planBodyClass;
 	}
 
@@ -108,8 +104,7 @@ public class DefaultPlan extends AbstractPlan {
 	 * @param planBodyClass
 	 *            the class of this plan body.
 	 */
-	public DefaultPlan(GoalTemplate goalTemplate,
-			Class<? extends PlanBody> planBodyClass) {
+	public DefaultPlan(GoalTemplate goalTemplate, Class<? extends PlanBody> planBodyClass) {
 		super(generateId(null, goalTemplate, null, planBodyClass), goalTemplate);
 		this.planBodyClass = planBodyClass;
 	}
@@ -134,11 +129,27 @@ public class DefaultPlan extends AbstractPlan {
 	 * @param planBodyClass
 	 *            the class of this plan body.
 	 */
-	public DefaultPlan(GoalTemplate goalTemplate,
-			MessageTemplate messageTemplate,
+	public DefaultPlan(GoalTemplate goalTemplate, MessageTemplate messageTemplate,
 			Class<? extends PlanBody> planBodyClass) {
-		super(generateId(null, goalTemplate, messageTemplate, planBodyClass),
-				goalTemplate, messageTemplate);
+		super(generateId(null, goalTemplate, messageTemplate, planBodyClass), goalTemplate, messageTemplate);
+		this.planBodyClass = planBodyClass;
+	}
+
+	/**
+	 * Creates a new simple plan, which is able to achieve goals that match the
+	 * provided templates. It is a plan whose body is the specified class and
+	 * its id is the plan body class name.
+	 * 
+	 * @param goalTemplate
+	 *            the template of goals that this plan can achieve.
+	 * @param planBodyClass
+	 *            the class of this plan body.
+	 */
+	public DefaultPlan(GoalTemplate[] goalTemplates, Class<? extends PlanBody> planBodyClass) {
+		super(generateId(null, goalTemplates[0], null, planBodyClass));
+		for (GoalTemplate goalTemplate : goalTemplates) {
+			addGoalTemplate(goalTemplate);
+		}
 		this.planBodyClass = planBodyClass;
 	}
 
@@ -156,10 +167,8 @@ public class DefaultPlan extends AbstractPlan {
 	 * @param planBodyClass
 	 *            the class of this plan body.
 	 */
-	public DefaultPlan(MessageTemplate messageTemplate,
-			Class<? extends PlanBody> planBodyClass) {
-		super(generateId(null, null, messageTemplate, planBodyClass),
-				messageTemplate);
+	public DefaultPlan(MessageTemplate messageTemplate, Class<? extends PlanBody> planBodyClass) {
+		super(generateId(null, null, messageTemplate, planBodyClass), messageTemplate);
 		this.planBodyClass = planBodyClass;
 	}
 
@@ -197,8 +206,7 @@ public class DefaultPlan extends AbstractPlan {
 	 * @param planBodyClass
 	 *            the class of this plan body.
 	 */
-	public DefaultPlan(String id, GoalTemplate goalTemplate,
-			Class<? extends PlanBody> planBodyClass) {
+	public DefaultPlan(String id, GoalTemplate goalTemplate, Class<? extends PlanBody> planBodyClass) {
 		super(id, goalTemplate);
 		this.planBodyClass = planBodyClass;
 	}
@@ -224,8 +232,7 @@ public class DefaultPlan extends AbstractPlan {
 	 * @param planBodyClass
 	 *            the class of this plan body.
 	 */
-	public DefaultPlan(String id, GoalTemplate goalTemplate,
-			MessageTemplate messageTemplate,
+	public DefaultPlan(String id, GoalTemplate goalTemplate, MessageTemplate messageTemplate,
 			Class<? extends PlanBody> planBodyClass) {
 		super(id, goalTemplate, messageTemplate);
 		this.planBodyClass = planBodyClass;
@@ -246,8 +253,7 @@ public class DefaultPlan extends AbstractPlan {
 	 * @param planBodyClass
 	 *            the class of this plan body.
 	 */
-	public DefaultPlan(String id, MessageTemplate messageTemplate,
-			Class<? extends PlanBody> planBodyClass) {
+	public DefaultPlan(String id, MessageTemplate messageTemplate, Class<? extends PlanBody> planBodyClass) {
 		super(id, messageTemplate);
 		this.planBodyClass = planBodyClass;
 	}
@@ -262,20 +268,16 @@ public class DefaultPlan extends AbstractPlan {
 	public PlanBody createPlanBody() throws PlanInstantiationException {
 		try {
 			Class<?> enclosingClass = planBodyClass.getEnclosingClass();
-			if (!Modifier.isStatic(planBodyClass.getModifiers())
-					&& enclosingClass != null) {
+			if (!Modifier.isStatic(planBodyClass.getModifiers()) && enclosingClass != null) {
 				if (BDIAgent.class.isAssignableFrom(enclosingClass)) {
 					return planBodyClass.getDeclaredConstructor(enclosingClass)
-							.newInstance(
-									getPlanLibrary().getCapability()
-											.getMyAgent());
+							.newInstance(getPlanLibrary().getCapability().getMyAgent());
 				} else if (Capability.class.isAssignableFrom(enclosingClass)) {
 					return planBodyClass.getDeclaredConstructor(enclosingClass)
 							.newInstance(getPlanLibrary().getCapability());
 				} else {
 					assert Plan.class.isAssignableFrom(enclosingClass);
-					return planBodyClass.getDeclaredConstructor(enclosingClass)
-							.newInstance(this);
+					return planBodyClass.getDeclaredConstructor(enclosingClass).newInstance(this);
 				}
 			} else {
 				return this.planBodyClass.newInstance();
diff --git a/bdi-jade/src/bdi4jade/plan/planbody/AbstractPlanBody.java b/bdi-jade/src/bdi4jade/plan/planbody/AbstractPlanBody.java
index 1f87c7b..ef22ed6 100644
--- a/bdi-jade/src/bdi4jade/plan/planbody/AbstractPlanBody.java
+++ b/bdi-jade/src/bdi4jade/plan/planbody/AbstractPlanBody.java
@@ -22,8 +22,6 @@
 
 package bdi4jade.plan.planbody;
 
-import jade.core.behaviours.Behaviour;
-
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -40,9 +38,11 @@ import bdi4jade.event.GoalListener;
 import bdi4jade.exception.ParameterException;
 import bdi4jade.exception.PlanInstantiationException;
 import bdi4jade.goal.Goal;
+import bdi4jade.goal.NestedGoal;
 import bdi4jade.plan.Plan;
 import bdi4jade.plan.Plan.EndState;
 import bdi4jade.util.ReflectionUtils;
+import jade.core.behaviours.Behaviour;
 
 /**
  * This class provides an almost complete implementation of the {@link PlanBody}
@@ -76,16 +76,14 @@ public abstract class AbstractPlanBody extends Behaviour implements PlanBody {
 	 * @see PlanBody#dispatchGoal(Goal)
 	 */
 	public boolean dispatchGoal(Goal goal) {
-		return this.intention.getMyAgent().addGoal(
-				this.plan.getPlanLibrary().getCapability(), goal);
+		return this.intention.getMyAgent().addGoal(this.plan.getPlanLibrary().getCapability(), goal);
 	}
 
 	/**
 	 * @see PlanBody#dispatchSubgoal(Goal)
 	 */
 	public boolean dispatchSubgoal(Goal subgoal) {
-		boolean goalAdded = this.intention.getMyAgent().addGoal(
-				this.plan.getPlanLibrary().getCapability(), subgoal);
+		boolean goalAdded = this.intention.getMyAgent().addGoal(this.plan.getPlanLibrary().getCapability(), subgoal);
 		synchronized (subgoals) {
 			if (goalAdded)
 				this.subgoals.add(subgoal);
@@ -97,8 +95,8 @@ public abstract class AbstractPlanBody extends Behaviour implements PlanBody {
 	 * @see PlanBody#dispatchSubgoalAndListen(Goal)
 	 */
 	public boolean dispatchSubgoalAndListen(Goal subgoal) {
-		boolean goalAdded = this.intention.getMyAgent().addGoal(
-				this.plan.getPlanLibrary().getCapability(), subgoal, this);
+		boolean goalAdded = this.intention.getMyAgent().addGoal(this.plan.getPlanLibrary().getCapability(), subgoal,
+				this);
 		synchronized (subgoals) {
 			if (goalAdded)
 				this.subgoals.add(subgoal);
@@ -168,7 +166,11 @@ public abstract class AbstractPlanBody extends Behaviour implements PlanBody {
 	 * @return the goal.
 	 */
 	public final Goal getGoal() {
-		return this.intention.getGoal();
+		if (this.intention.getGoal() instanceof NestedGoal) {
+			return ((NestedGoal) this.intention.getGoal()).getGoal();
+		} else {
+			return this.intention.getGoal();
+		}
 	}
 
 	/**
@@ -291,16 +293,14 @@ public abstract class AbstractPlanBody extends Behaviour implements PlanBody {
 	 * @throws PlanInstantiationException
 	 *             if this plan body has already been initialized.
 	 */
-	public final void init(Plan plan, Intention intention)
-			throws PlanInstantiationException {
+	public final void init(Plan plan, Intention intention) throws PlanInstantiationException {
 		if (this.plan != null || this.intention != null) {
-			throw new PlanInstantiationException(
-					"This plan body has already been initialized.");
+			throw new PlanInstantiationException("This plan body has already been initialized.");
 		}
 		this.plan = plan;
 		this.intention = intention;
 		try {
-			ReflectionUtils.setPlanBodyInput(this, intention.getGoal());
+			ReflectionUtils.setPlanBodyInput(this, getGoal());
 			ReflectionUtils.setupBeliefs(this);
 		} catch (ParameterException exc) {
 			throw new PlanInstantiationException(exc);
@@ -332,8 +332,7 @@ public abstract class AbstractPlanBody extends Behaviour implements PlanBody {
 					((OutputPlanBody) this).setGoalOutput(getGoal());
 				} else {
 					try {
-						ReflectionUtils.setPlanBodyOutput(this,
-								intention.getGoal());
+						ReflectionUtils.setPlanBodyOutput(this, getGoal());
 					} catch (ParameterException exc) {
 						log.warn("Could not set all goal outputs: " + exc);
 					}
diff --git a/bdi-jade-extensions/.classpath b/bdi-jade-extensions/.classpath
index bdac129..42c9295 100644
--- a/bdi-jade-extensions/.classpath
+++ b/bdi-jade-extensions/.classpath
@@ -2,10 +2,10 @@
 <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="lib/weka.jar"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/bdi-jade"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/goal/CauseEffectProblem.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/goal/CauseEffectProblem.java
new file mode 100644
index 0000000..2a76d95
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/goal/CauseEffectProblem.java
@@ -0,0 +1,107 @@
+package bdi4jade.extension.palliative.goal;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import bdi4jade.core.BDIAgent;
+import bdi4jade.event.GoalEvent;
+import bdi4jade.event.GoalListener;
+import bdi4jade.extension.palliative.graph.CauseEffectRelationship;
+import bdi4jade.extension.palliative.logics.Fact;
+import bdi4jade.goal.BeliefValueGoal;
+import bdi4jade.goal.Goal;
+import bdi4jade.goal.GoalStatus;
+
+public class CauseEffectProblem implements GoalListener {
+
+	public enum CauseEffectProblemStatus {
+		CAUSE_PARTIALLY_RESOLVED, CAUSE_RESOLVED, FULLY_RESOLVED, MITIGATED, PARTIALLY_RESOLVED, UNSUCCESSFUL;
+	}
+
+	private final CauseEffectRelationship causeEffectRelationship;
+	private Map<Fact, CauseFactorStatus> causeFactorStatus;
+	private final BeliefValueGoal<?, ?> effectGoal;
+	private final Goal parentGoal;
+	private GoalStatus effectGoalStatus;
+	private CauseEffectProblemStatus status;
+
+	public CauseEffectProblem(BeliefValueGoal<?, ?> effectGoal, CauseEffectRelationship causeEffectRelationship,
+			BDIAgent agent, Goal parentGoal) {
+		this.effectGoal = effectGoal;
+		this.parentGoal = parentGoal;
+		this.causeEffectRelationship = causeEffectRelationship;
+		if (parentGoal != null) {
+			agent.addGoalListener(parentGoal, this);
+		} else {
+			agent.addGoalListener(effectGoal, this);
+		}
+
+		this.causeFactorStatus = new HashMap<>();
+		for (Fact fact : causeEffectRelationship.getAllPossibleCauses()) {
+			causeFactorStatus.put(fact, new CauseFactorStatus(fact));
+		}
+
+		this.effectGoalStatus = null;
+		this.status = null;
+	}
+
+	public void setCauseFactorStatus(Set<CauseFactorStatus> cause) {
+		this.causeFactorStatus = new HashMap<>();
+		for (CauseFactorStatus cf : cause) {
+			this.causeFactorStatus.put(cf.getFact(), cf);
+		}
+	}
+
+	public Collection<CauseFactorStatus> getCauseFactorStatus() {
+		return causeFactorStatus.values();
+	}
+
+	public CauseFactorStatus getCauseFactorStatus(Fact fact) {
+		return causeFactorStatus.get(fact);
+	}
+
+	public Goal getEffectGoal() {
+		return effectGoal;
+	}
+
+	public GoalStatus getEffectGoalStatus() {
+		return effectGoalStatus;
+	}
+
+	public CauseEffectProblemStatus getStatus() {
+		return status;
+	}
+
+	@Override
+	public void goalPerformed(GoalEvent event) {
+		if ((event.getGoal() == effectGoal || event.getGoal() == parentGoal) && event.getStatus().isFinished()) {
+			setEffectGoalStatus(event.getStatus());
+		}
+	}
+
+	public void setEffectGoalStatus(GoalStatus effectGoalStatus) {
+		this.effectGoalStatus = effectGoalStatus;
+	}
+
+	public void setStatus(CauseEffectProblemStatus status) {
+		this.status = status;
+	}
+
+	public CauseEffectRelationship getCauseEffectRelationship() {
+		return causeEffectRelationship;
+	}
+
+	@Override
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+		sb.append("< ").append(effectGoal).append(" [").append(effectGoalStatus).append("], {\n");
+		for (CauseFactorStatus cf : causeFactorStatus.values()) {
+			sb.append("\t").append(cf).append("\n");
+		}
+		sb.append("} > = ").append(status);
+		return sb.toString();
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/goal/CauseFactorStatus.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/goal/CauseFactorStatus.java
new file mode 100644
index 0000000..1ae135a
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/goal/CauseFactorStatus.java
@@ -0,0 +1,104 @@
+package bdi4jade.extension.palliative.goal;
+
+import bdi4jade.extension.palliative.logics.Fact;
+import bdi4jade.goal.BeliefPresentGoal;
+import bdi4jade.goal.Goal;
+import bdi4jade.goal.GoalStatus;
+import bdi4jade.goal.PredicateGoal;
+
+public class CauseFactorStatus {
+
+	private Goal achievementGoal;
+	private GoalStatus achievementGoalStatus;
+	private final Fact fact;
+	private Boolean initialStatus;
+	private Goal testGoal;
+	private GoalStatus testGoalStatus;
+	private Boolean updatedStatus;
+
+	public CauseFactorStatus(Fact fact) {
+		this.fact = fact;
+		this.initialStatus = null;
+		this.updatedStatus = null;
+		this.testGoal = null;
+		this.achievementGoal = null;
+		this.testGoalStatus = null;
+		this.achievementGoalStatus = null;
+	}
+
+	public PredicateGoal<?> generateAchievementGoal() {
+		this.achievementGoal = new PredicateGoal(this.fact.getPredicate(), !this.fact.getValue());
+		return (PredicateGoal<?>) this.achievementGoal;
+	}
+
+	public BeliefPresentGoal<?> generateTestGoal() {
+		this.testGoal = new BeliefPresentGoal<Object>(this.fact.getPredicate());
+		return (BeliefPresentGoal<?>) this.testGoal;
+	}
+
+	public Goal getAchievementGoal() {
+		return achievementGoal;
+	}
+
+	public GoalStatus getAchievementGoalStatus() {
+		return achievementGoalStatus;
+	}
+
+	public Fact getFact() {
+		return fact;
+	}
+
+	public Boolean getInitialStatus() {
+		return initialStatus;
+	}
+
+	public Goal getTestGoal() {
+		return testGoal;
+	}
+
+	public GoalStatus getTestGoalStatus() {
+		return testGoalStatus;
+	}
+
+	public Boolean getUpdatedStatus() {
+		return updatedStatus;
+	}
+
+	public void setAchievementGoal(Goal achievementGoal) {
+		this.achievementGoal = achievementGoal;
+	}
+
+	public void setAchievementGoalStatus(GoalStatus achievementGoalStatus) {
+		this.achievementGoalStatus = achievementGoalStatus;
+	}
+
+	public void setInitialStatus(Boolean initialStatus) {
+		this.initialStatus = initialStatus;
+	}
+
+	public void setTestGoal(Goal testGoal) {
+		this.testGoal = testGoal;
+	}
+
+	public void setTestGoalStatus(GoalStatus testGoalStatus) {
+		this.testGoalStatus = testGoalStatus;
+	}
+
+	public void setUpdatedStatus(Boolean updatedStatus) {
+		this.updatedStatus = updatedStatus;
+	}
+
+	@Override
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+		sb.append("< ").append(fact);
+		sb.append(", s_i = ").append(initialStatus);
+		sb.append(", s_u = ").append(updatedStatus);
+		sb.append(", ?g = ").append(testGoal);
+		sb.append(" [").append(testGoalStatus).append("]");
+		sb.append(", !g = ").append(achievementGoal);
+		sb.append(" [").append(achievementGoalStatus).append("] >");
+		return sb.toString();
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/goal/ConstrainedGoal.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/goal/ConstrainedGoal.java
new file mode 100644
index 0000000..1a15b30
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/goal/ConstrainedGoal.java
@@ -0,0 +1,54 @@
+package bdi4jade.extension.palliative.goal;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import bdi4jade.extension.palliative.Resource;
+import bdi4jade.extension.palliative.logics.LogicalExpression;
+import bdi4jade.goal.Goal;
+import bdi4jade.goal.NestedGoal;
+
+public class ConstrainedGoal extends NestedGoal {
+
+	private static final long serialVersionUID = -7779648429437829445L;
+
+	private Map<Resource, ObjectiveFunction> objectiveFunction;
+	private Set<LogicalExpression> operationConstraints;
+
+	public ConstrainedGoal(Goal goal) {
+		super(goal);
+		this.operationConstraints = new HashSet<>();
+		this.objectiveFunction = new HashMap<>();
+	}
+
+	public void addObjectiveFunction(Resource resource, ObjectiveFunction objectiveFunction) {
+		this.objectiveFunction.put(resource, objectiveFunction);
+	}
+
+	public void addOperationConstraint(LogicalExpression constraint) {
+		this.operationConstraints.add(constraint);
+	}
+
+	public Map<Resource, ObjectiveFunction> getObjectiveFunction() {
+		return objectiveFunction;
+	}
+
+	public ObjectiveFunction getObjectiveFunction(Resource resource) {
+		return this.objectiveFunction.get(resource);
+	}
+
+	public Set<LogicalExpression> getOperationConstraints() {
+		return operationConstraints;
+	}
+
+	public void setObjectiveFunction(Map<Resource, ObjectiveFunction> objectiveFunction) {
+		this.objectiveFunction = objectiveFunction;
+	}
+
+	public void setOperationConstraints(Set<LogicalExpression> operationConstraints) {
+		this.operationConstraints = operationConstraints;
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/goal/ObjectiveFunction.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/goal/ObjectiveFunction.java
new file mode 100644
index 0000000..0272fd4
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/goal/ObjectiveFunction.java
@@ -0,0 +1,7 @@
+package bdi4jade.extension.palliative.goal;
+
+public enum ObjectiveFunction {
+
+	MAXIMIZE, MINIMIZE;
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/graph/AlternativeCauseSet.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/graph/AlternativeCauseSet.java
new file mode 100644
index 0000000..6fa3870
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/graph/AlternativeCauseSet.java
@@ -0,0 +1,44 @@
+package bdi4jade.extension.palliative.graph;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import bdi4jade.extension.palliative.logics.Fact;
+
+public class AlternativeCauseSet {
+
+	private List<Fact> alternativeCauses;
+	private Integer max;
+	private Integer min;
+
+	public AlternativeCauseSet(Integer min, Integer max) {
+		setMin(min);
+		setMax(max);
+		this.alternativeCauses = new ArrayList<>();
+	}
+
+	public void addAlternativeCause(Fact cause) {
+		this.alternativeCauses.add(cause);
+	}
+
+	public List<Fact> getAlternativeCauses() {
+		return this.alternativeCauses;
+	}
+
+	public Integer getMax() {
+		return this.max;
+	}
+
+	public Integer getMin() {
+		return this.min;
+	}
+
+	public void setMax(Integer max) {
+		this.max = max;
+	}
+
+	public void setMin(Integer min) {
+		this.min = min;
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/graph/CauseEffectKnowledgeModel.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/graph/CauseEffectKnowledgeModel.java
new file mode 100644
index 0000000..37c81db
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/graph/CauseEffectKnowledgeModel.java
@@ -0,0 +1,42 @@
+package bdi4jade.extension.palliative.graph;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import bdi4jade.belief.TransientBelief;
+import bdi4jade.extension.palliative.logics.Fact;
+import bdi4jade.extension.palliative.logics.Predicate;
+import bdi4jade.goal.BeliefValueGoal;
+import bdi4jade.goal.Goal;
+import bdi4jade.goal.PredicateGoal;
+
+public class CauseEffectKnowledgeModel extends TransientBelief<String, Map<Fact, CauseEffectRelationship>> {
+
+	public static final String NAME = "CauseEffectModel";
+
+	public CauseEffectKnowledgeModel() {
+		super(NAME, new HashMap<>());
+	}
+
+	public void addCauseEffectRelationship(CauseEffectRelationship causes) {
+		this.getValue().put(causes.getEffect(), causes);
+	}
+
+	public CauseEffectRelationship getCauseEffectRelationship(Goal goal) {
+		if (goal instanceof PredicateGoal<?>) {
+			PredicateGoal<? extends Predicate> bgoal = (PredicateGoal<? extends Predicate>) goal;
+			Fact fact = new Fact(bgoal.getBeliefName(), !bgoal.getValue());
+			return getCausesOf(fact);
+		}
+		return null;
+	}
+
+	public CauseEffectRelationship getCausesOf(Fact effect) {
+		return this.getValue().get(effect);
+	}
+
+	public boolean isEffect(Fact fact) {
+		return getValue().containsKey(fact);
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/graph/CauseEffectRelationship.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/graph/CauseEffectRelationship.java
new file mode 100644
index 0000000..48bbb7f
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/graph/CauseEffectRelationship.java
@@ -0,0 +1,65 @@
+package bdi4jade.extension.palliative.graph;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import bdi4jade.extension.palliative.logics.Fact;
+
+public class CauseEffectRelationship {
+
+	private List<AlternativeCauseSet> alternativeCauseSets;
+	private Fact effect;
+	private List<Fact> mandatoryCauses;
+	private List<Fact> optionalCauses;
+
+	public CauseEffectRelationship(Fact effect) {
+		this.effect = effect;
+		this.mandatoryCauses = new ArrayList<>();
+		this.optionalCauses = new ArrayList<>();
+		this.alternativeCauseSets = new ArrayList<>();
+	}
+
+	public void addAlternativeCauseSet(AlternativeCauseSet acs) {
+		this.alternativeCauseSets.add(acs);
+	}
+
+	public void addMandatoryCause(Fact cause) {
+		this.mandatoryCauses.add(cause);
+	}
+
+	public void addOptionalCause(Fact cause) {
+		this.optionalCauses.add(cause);
+	}
+
+	public List<Fact> getAllPossibleCauses() {
+		ArrayList<Fact> possibleCauses = new ArrayList<>();
+		possibleCauses.addAll(mandatoryCauses);
+		possibleCauses.addAll(optionalCauses);
+		possibleCauses.addAll(getAlternativeCauses());
+		return possibleCauses;
+	}
+
+	public List<Fact> getAlternativeCauses() {
+		ArrayList<Fact> alternativeCauses = new ArrayList<>();
+		for (AlternativeCauseSet causeSet : this.alternativeCauseSets) {
+			alternativeCauses.addAll(causeSet.getAlternativeCauses());
+		}
+		return alternativeCauses;
+	}
+
+	public List<AlternativeCauseSet> getAlternativeCauseSets() {
+		return this.alternativeCauseSets;
+	}
+
+	public Fact getEffect() {
+		return effect;
+	}
+
+	public List<Fact> getMandatoryCauses() {
+		return this.mandatoryCauses;
+	}
+
+	public List<Fact> getOptionalCauses() {
+		return this.optionalCauses;
+	}
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/And.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/And.java
new file mode 100644
index 0000000..7642eb0
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/And.java
@@ -0,0 +1,65 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2011  Ingrid Nunes
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+// 
+// To contact the authors:
+// http://inf.ufrgs.br/prosoft/bdi4jade/
+//
+//----------------------------------------------------------------------------
+
+package bdi4jade.extension.palliative.logics;
+
+import java.util.Map;
+
+import bdi4jade.belief.BeliefBase;
+
+/**
+ * @author ingridnunes
+ *
+ */
+public class And extends BinaryLogicalExpression {
+
+	public And() {
+
+	}
+
+	public And(LogicalExpression expression1, LogicalExpression expression2) {
+		super(expression1, expression2);
+	}
+
+	@Override
+	public Boolean getValue(BeliefBase beliefBase) {
+		return getExpression1().getValue(beliefBase) && getExpression2().getValue(beliefBase);
+	}
+
+	@Override
+	public Boolean getValue(Map<Object, Object> values) {
+		return getExpression1().getValue(values) && getExpression2().getValue(values);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.Object#toString()
+	 */
+	@Override
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+		sb.append("(").append(expression1).append(" ^ ").append(expression2).append(")");
+		return sb.toString();
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/BinaryLogicalExpression.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/BinaryLogicalExpression.java
new file mode 100644
index 0000000..6aa2344
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/BinaryLogicalExpression.java
@@ -0,0 +1,73 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2011  Ingrid Nunes
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+// 
+// To contact the authors:
+// http://inf.ufrgs.br/prosoft/bdi4jade/
+//
+//----------------------------------------------------------------------------
+
+package bdi4jade.extension.palliative.logics;
+
+/**
+ * @author ingridnunes
+ *
+ */
+public abstract class BinaryLogicalExpression implements LogicalExpression {
+
+	protected LogicalExpression expression1;
+	protected LogicalExpression expression2;
+
+	public BinaryLogicalExpression() {
+
+	}
+
+	public BinaryLogicalExpression(LogicalExpression expression1, LogicalExpression expression2) {
+		this.expression1 = expression1;
+		this.expression2 = expression2;
+	}
+
+	/**
+	 * @return the expression1
+	 */
+	public LogicalExpression getExpression1() {
+		return expression1;
+	}
+
+	/**
+	 * @return the expression2
+	 */
+	public LogicalExpression getExpression2() {
+		return expression2;
+	}
+
+	/**
+	 * @param expression1
+	 *            the expression1 to set
+	 */
+	public void setExpression1(LogicalExpression expression1) {
+		this.expression1 = expression1;
+	}
+
+	/**
+	 * @param expression2
+	 *            the expression2 to set
+	 */
+	public void setExpression2(LogicalExpression expression2) {
+		this.expression2 = expression2;
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/BinaryPredicate.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/BinaryPredicate.java
new file mode 100644
index 0000000..28167c9
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/BinaryPredicate.java
@@ -0,0 +1,94 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2011  Ingrid Nunes
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+// 
+// To contact the authors:
+// http://inf.ufrgs.br/prosoft/bdi4jade/
+//
+//----------------------------------------------------------------------------
+package bdi4jade.extension.palliative.logics;
+
+/**
+ * @author Ingrid Nunes
+ */
+public abstract class BinaryPredicate<T, U> extends Predicate {
+
+	private static final long serialVersionUID = -1506723105103606268L;
+
+	protected T variable1;
+	protected U variable2;
+
+	public BinaryPredicate() {
+
+	}
+
+	public BinaryPredicate(T first, U second) {
+		this.variable1 = first;
+		this.variable2 = second;
+	}
+
+	protected void appendVariables(StringBuffer sb) {
+		sb.append(variable1);
+		sb.append(",");
+		sb.append(variable2);
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (obj != null && this.getClass().equals(obj.getClass())) {
+			BinaryPredicate<?, ?> p = (BinaryPredicate<?, ?>) obj;
+			return this.variable1.equals(p.variable1) && this.variable2.equals(p.variable2);
+		}
+		return false;
+	}
+
+	public T getVariable1() {
+		return variable1;
+	}
+
+	public U getVariable2() {
+		return variable2;
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((this.getClass() == null) ? 0 : this.getClass().hashCode());
+		result = prime * result + ((variable1 == null) ? 0 : variable1.hashCode());
+		result = prime * result + ((variable2 == null) ? 0 : variable2.hashCode());
+		return result;
+	}
+
+	public void setVariable1(T first) {
+		this.variable1 = first;
+	}
+
+	public void setVariable2(U second) {
+		this.variable2 = second;
+	}
+
+	@Override
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+		sb.append(super.toString());
+		sb.append("(");
+		appendVariables(sb);
+		sb.append(")");
+		return sb.toString();
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/Fact.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/Fact.java
new file mode 100644
index 0000000..a0cb052
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/Fact.java
@@ -0,0 +1,57 @@
+package bdi4jade.extension.palliative.logics;
+
+import java.io.Serializable;
+
+import jade.content.Concept;
+import jade.content.ContentElement;
+
+public class Fact implements Serializable, Concept, ContentElement {
+
+	private static final long serialVersionUID = -7208284763130171013L;
+
+	private Predicate proposition;
+	private Boolean value;
+
+	public Fact(Predicate proposition, Boolean val) {
+		this.proposition = proposition;
+		this.value = val;
+	}
+
+	public Predicate getPredicate() {
+		return proposition;
+	}
+
+	public Boolean getValue() {
+		return this.value;
+	}
+
+	@Override
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+		if (value == null) {
+			sb.append("not ");
+		} else if (!value) {
+			sb.append("~");
+		}
+		sb.append(proposition);
+		return sb.toString();
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (!(obj instanceof Fact))
+			return false;
+		Fact other = (Fact) obj;
+		return this.proposition.equals(other.proposition) && this.value.equals(other.value);
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + proposition.hashCode();
+		result = prime * result + value.hashCode();
+		return result;
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/Implication.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/Implication.java
new file mode 100644
index 0000000..adbcaac
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/Implication.java
@@ -0,0 +1,65 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2011  Ingrid Nunes
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+// 
+// To contact the authors:
+// http://inf.ufrgs.br/prosoft/bdi4jade/
+//
+//----------------------------------------------------------------------------
+
+package bdi4jade.extension.palliative.logics;
+
+import java.util.Map;
+
+import bdi4jade.belief.BeliefBase;
+
+/**
+ * @author ingridnunes
+ *
+ */
+public class Implication extends BinaryLogicalExpression {
+
+	public Implication() {
+
+	}
+
+	public Implication(LogicalExpression expression1, LogicalExpression expression2) {
+		super(expression1, expression2);
+	}
+
+	@Override
+	public Boolean getValue(BeliefBase beliefBase) {
+		return !getExpression1().getValue(beliefBase) || getExpression2().getValue(beliefBase);
+	}
+
+	@Override
+	public Boolean getValue(Map<Object, Object> values) {
+		return !getExpression1().getValue(values) || getExpression2().getValue(values);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.Object#toString()
+	 */
+	@Override
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+		sb.append("(").append(expression1).append(" -> ").append(expression2).append(")");
+		return sb.toString();
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/LogicalExpression.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/LogicalExpression.java
new file mode 100644
index 0000000..a5032d5
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/LogicalExpression.java
@@ -0,0 +1,42 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2011  Ingrid Nunes
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+// 
+// To contact the authors:
+// http://inf.ufrgs.br/prosoft/bdi4jade/
+//
+//----------------------------------------------------------------------------
+
+package bdi4jade.extension.palliative.logics;
+
+import java.io.Serializable;
+import java.util.Map;
+
+import bdi4jade.belief.BeliefBase;
+import jade.content.Concept;
+import jade.content.ContentElement;
+
+/**
+ * @author ingridnunes
+ *
+ */
+public interface LogicalExpression extends Serializable, Concept, ContentElement {
+
+	public Boolean getValue(BeliefBase beliefBase);
+
+	public Boolean getValue(Map<Object, Object> values);
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/MathExpression.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/MathExpression.java
new file mode 100644
index 0000000..2f87ec2
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/MathExpression.java
@@ -0,0 +1,82 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2011  Ingrid Nunes
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+// 
+// To contact the authors:
+// http://inf.ufrgs.br/prosoft/bdi4jade/
+//
+//----------------------------------------------------------------------------
+
+package bdi4jade.extension.palliative.logics;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import bdi4jade.belief.Belief;
+import bdi4jade.belief.BeliefBase;
+import bdi4jade.extension.palliative.logics.MathExpression.Operator;
+
+/**
+ * @author ingridnunes
+ *
+ */
+public class MathExpression<T> extends TernaryPredicate<T, Operator, Double> {
+
+	private static final long serialVersionUID = 11514826399908986L;
+
+	public enum Operator {
+
+		EQUAL_TO, NOT_EQUAL_TO, LESS_THAN, LESS_THAN_OR_EQUAL_TO, GREATER_THAN, GREATER_THAN_OR_EQUAL_TO;
+
+	}
+	
+	public MathExpression() {
+		
+	}
+	
+	public MathExpression(T freeVariable, Operator operator, Double value) {
+		super(freeVariable, operator, value);
+	}
+	
+	@Override
+	public Boolean getValue(BeliefBase beliefBase) {
+		Belief<T, Double> belief = (Belief<T, Double>) beliefBase.getBelief(getVariable1());
+		Map<Object, Object> values = new HashMap<>();
+		values.put(getVariable1(), belief.getValue());
+		return getValue(beliefBase);
+	}
+	
+	@Override
+	public Boolean getValue(Map<Object, Object> values) {
+		Double variableValue = (Double) values.get(getVariable1());
+		switch (getVariable2()) {
+		case EQUAL_TO:
+			return variableValue == getVariable3();
+		case NOT_EQUAL_TO:
+			return variableValue != getVariable3();
+		case LESS_THAN:
+			return variableValue < getVariable3();
+		case LESS_THAN_OR_EQUAL_TO:
+			return variableValue <= getVariable3();
+		case GREATER_THAN:
+			return variableValue > getVariable3();
+		case GREATER_THAN_OR_EQUAL_TO:
+			return variableValue >= getVariable3();
+		}
+		return null;
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/Not.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/Not.java
new file mode 100644
index 0000000..8cc676b
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/Not.java
@@ -0,0 +1,65 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2011  Ingrid Nunes
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+// 
+// To contact the authors:
+// http://inf.ufrgs.br/prosoft/bdi4jade/
+//
+//----------------------------------------------------------------------------
+
+package bdi4jade.extension.palliative.logics;
+
+import java.util.Map;
+
+import bdi4jade.belief.BeliefBase;
+
+/**
+ * @author ingridnunes
+ *
+ */
+public class Not extends UnaryLogicalExpression {
+
+	public Not() {
+
+	}
+
+	public Not(LogicalExpression expression) {
+		super(expression);
+	}
+
+	@Override
+	public Boolean getValue(BeliefBase beliefBase) {
+		return !getExpression().getValue(beliefBase);
+	}
+
+	@Override
+	public Boolean getValue(Map<Object, Object> values) {
+		return !getExpression().getValue(values);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.Object#toString()
+	 */
+	@Override
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+		sb.append("!").append(expression);
+		return sb.toString();
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/Or.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/Or.java
new file mode 100644
index 0000000..c1da5e9
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/Or.java
@@ -0,0 +1,65 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2011  Ingrid Nunes
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+// 
+// To contact the authors:
+// http://inf.ufrgs.br/prosoft/bdi4jade/
+//
+//----------------------------------------------------------------------------
+
+package bdi4jade.extension.palliative.logics;
+
+import java.util.Map;
+
+import bdi4jade.belief.BeliefBase;
+
+/**
+ * @author ingridnunes
+ *
+ */
+public class Or extends BinaryLogicalExpression {
+
+	public Or() {
+
+	}
+
+	public Or(LogicalExpression expression1, LogicalExpression expression2) {
+		super(expression1, expression2);
+	}
+
+	@Override
+	public Boolean getValue(BeliefBase beliefBase) {
+		return getExpression1().getValue(beliefBase) || getExpression2().getValue(beliefBase);
+	}
+
+	@Override
+	public Boolean getValue(Map<Object, Object> values) {
+		return getExpression1().getValue(values) || getExpression2().getValue(values);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.Object#toString()
+	 */
+	@Override
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+		sb.append("(").append(expression1).append(" v ").append(expression2).append(")");
+		return sb.toString();
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/Predicate.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/Predicate.java
new file mode 100644
index 0000000..4938bbe
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/Predicate.java
@@ -0,0 +1,64 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2011  Ingrid Nunes
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+// 
+// To contact the authors:
+// http://inf.ufrgs.br/prosoft/bdi4jade/
+//
+//----------------------------------------------------------------------------
+
+package bdi4jade.extension.palliative.logics;
+
+import java.util.Map;
+
+import bdi4jade.belief.BeliefBase;
+import bdi4jade.belief.PredicateBelief;
+
+/**
+ * @author ingridnunes
+ *
+ */
+public abstract class Predicate implements LogicalExpression {
+
+	public String getStatement() {
+		return toString();
+	}
+
+	@Override
+	public Boolean getValue(BeliefBase beliefBase) {
+		PredicateBelief<Predicate> belief = (PredicateBelief<Predicate>) beliefBase.getBelief(this);
+		if (belief != null) {
+			return belief.getValue();
+		}
+		return null;
+	}
+
+	@Override
+	public Boolean getValue(Map<Object, Object> values) {
+		return (Boolean) values.get(this);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.Object#toString()
+	 */
+	@Override
+	public String toString() {
+		return this.getClass().getSimpleName();
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/Proposition.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/Proposition.java
new file mode 100644
index 0000000..4f5ea9a
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/Proposition.java
@@ -0,0 +1,41 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2011  Ingrid Nunes
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+// 
+// To contact the authors:
+// http://inf.ufrgs.br/prosoft/bdi4jade/
+//
+//----------------------------------------------------------------------------
+
+package bdi4jade.extension.palliative.logics;
+
+/**
+ * @author ingridnunes
+ *
+ */
+public class Proposition extends Predicate {
+
+	@Override
+	public boolean equals(Object obj) {
+		return (obj == null || !(obj instanceof Proposition) || !this.getClass().equals(obj.getClass()));
+	}
+
+	@Override
+	public int hashCode() {
+		return this.getClass().hashCode();
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/TernaryPredicate.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/TernaryPredicate.java
new file mode 100644
index 0000000..b5e9a07
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/TernaryPredicate.java
@@ -0,0 +1,50 @@
+package bdi4jade.extension.palliative.logics;
+
+public abstract class TernaryPredicate<T, U, V> extends BinaryPredicate<T, U> {
+
+	private static final long serialVersionUID = -1506723105103606268L;
+
+	protected V variable3;
+
+	public TernaryPredicate() {
+
+	}
+
+	public TernaryPredicate(T first, U second, V third) {
+		super(first, second);
+		this.variable3 = third;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (obj != null && this.getClass().equals(obj.getClass())) {
+			TernaryPredicate<?, ?, ?> p = (TernaryPredicate<?, ?, ?>) obj;
+			return this.variable1.equals(p.variable1) && this.variable2.equals(p.variable2)
+					&& this.variable3.equals(p.variable3);
+		}
+		return false;
+	}
+
+	public V getVariable3() {
+		return variable3;
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = super.hashCode();
+		result = prime * result + ((variable3 == null) ? 0 : variable3.hashCode());
+		return result;
+	}
+
+	public void setVariable3(V variable3) {
+		this.variable3 = variable3;
+	}
+
+	protected void appendVariables(StringBuffer sb) {
+		super.appendVariables(sb);
+		sb.append(",");
+		sb.append(variable3);
+	}
+
+}
\ No newline at end of file
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/UnaryLogicalExpression.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/UnaryLogicalExpression.java
new file mode 100644
index 0000000..b4852c4
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/UnaryLogicalExpression.java
@@ -0,0 +1,56 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2011  Ingrid Nunes
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+// 
+// To contact the authors:
+// http://inf.ufrgs.br/prosoft/bdi4jade/
+//
+//----------------------------------------------------------------------------
+
+package bdi4jade.extension.palliative.logics;
+
+/**
+ * @author ingridnunes
+ *
+ */
+public abstract class UnaryLogicalExpression implements LogicalExpression {
+
+	protected LogicalExpression expression;
+
+	public UnaryLogicalExpression() {
+
+	}
+
+	public UnaryLogicalExpression(LogicalExpression expression) {
+		this.expression = expression;
+	}
+
+	/**
+	 * @return the expression
+	 */
+	public LogicalExpression getExpression() {
+		return expression;
+	}
+
+	/**
+	 * @param expression
+	 *            the expression to set
+	 */
+	public void setExpression(LogicalExpression expression) {
+		this.expression = expression;
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/UnaryPredicate.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/UnaryPredicate.java
new file mode 100644
index 0000000..d60cbe1
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/logics/UnaryPredicate.java
@@ -0,0 +1,100 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2011  Ingrid Nunes
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+// 
+// To contact the authors:
+// http://inf.ufrgs.br/prosoft/bdi4jade/
+//
+//----------------------------------------------------------------------------
+package bdi4jade.extension.palliative.logics;
+
+import java.util.Map;
+
+import bdi4jade.belief.BeliefBase;
+import bdi4jade.belief.PredicateBelief;
+
+/**
+ * @author Ingrid Nunes
+ */
+public abstract class UnaryPredicate<T> extends Predicate {
+
+	private static final long serialVersionUID = -1506723105103606268L;
+
+	protected T variable;
+
+	public UnaryPredicate() {
+
+	}
+
+	public UnaryPredicate(T concept) {
+		this.variable = concept;
+	}
+
+	protected void appendVariables(StringBuffer sb) {
+		sb.append(variable);
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (obj != null && this.getClass().equals(obj.getClass())) {
+			UnaryPredicate<?> p = (UnaryPredicate<?>) obj;
+			return this.variable.equals(p.variable);
+		}
+		return false;
+	}
+
+	@Override
+	public Boolean getValue(BeliefBase beliefBase) {
+		PredicateBelief<Predicate> belief = (PredicateBelief<Predicate>) beliefBase.getBelief(this);
+		if (belief != null) {
+			return belief.getValue();
+		}
+		return null;
+	}
+
+	@Override
+	public Boolean getValue(Map<Object, Object> values) {
+		return (Boolean) values.get(this);
+	}
+
+	public T getVariable() {
+		return variable;
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((this.getClass() == null) ? 0 : this.getClass().hashCode());
+		result = prime * result + ((variable == null) ? 0 : variable.hashCode());
+		return result;
+	}
+
+	public void setConcept(T concept) {
+		this.variable = concept;
+	}
+
+	@Override
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+		sb.append(super.toString());
+		sb.append("(");
+		appendVariables(sb);
+		sb.append(")");
+		return sb.toString();
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/NamedResource.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/NamedResource.java
new file mode 100644
index 0000000..b9773f8
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/NamedResource.java
@@ -0,0 +1,101 @@
+package bdi4jade.extension.palliative;
+
+import bdi4jade.core.MetadataElement;
+import bdi4jade.core.MetadataElementImpl;
+
+/**
+ * This class provides a default implementation for a resource, representing it
+ * just with a given name.
+ * 
+ * It implements the {@link MetadataElement} interface, allowing to associate
+ * metadata with resources.
+ * 
+ * @author Ingrid Nunes
+ * 
+ */
+public class NamedResource extends MetadataElementImpl implements Resource, MetadataElement {
+
+	private static final long serialVersionUID = 3958189054716876043L;
+
+	private String name;
+
+	/**
+	 * The default constructor. It should be only used if persistence frameworks
+	 * are used.
+	 */
+	protected NamedResource() {
+
+	}
+
+	/**
+	 * Initializes a resource with its name.
+	 * 
+	 * @param name
+	 *            the resource name.
+	 */
+	public NamedResource(String name) {
+		this.name = name;
+	}
+
+	/**
+	 * Returns true of the object is a named resource and has the same name of
+	 * this named resource.
+	 * 
+	 * @param obj
+	 *            to object to be tested if it is equal to this named resource.
+	 * 
+	 * @see Object#equals(Object)
+	 */
+	@Override
+	public final boolean equals(Object obj) {
+		if (obj instanceof NamedResource) {
+			NamedResource sg = (NamedResource) obj;
+			return this.name.equals(sg.name);
+		}
+		return false;
+	}
+
+	/**
+	 * Returns the name of this resource.
+	 * 
+	 * @return the name.
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * Returns the hash code of this named resource.
+	 * 
+	 * @return the hash code of the name of this resource.
+	 * 
+	 * @see java.lang.Object#hashCode()
+	 */
+	@Override
+	public final int hashCode() {
+		return name == null ? 0 : this.name.hashCode();
+	}
+
+	/**
+	 * Sets the name of this resource. Ideally, the name should be final and
+	 * initialized in the constructor. This method should be only used if
+	 * persistence frameworks are used.
+	 * 
+	 * @param name
+	 *            the name to set.
+	 */
+	protected void setName(String name) {
+		this.name = name;
+	}
+
+	/**
+	 * Returns the string representation of this resource, which is its name.
+	 * 
+	 * @see java.lang.Object#toString()
+	 */
+	@Override
+	public String toString() {
+		return name;
+	}
+
+}
\ No newline at end of file
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/PalliativeCapability.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/PalliativeCapability.java
new file mode 100644
index 0000000..58829aa
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/PalliativeCapability.java
@@ -0,0 +1,24 @@
+package bdi4jade.extension.palliative;
+
+import bdi4jade.annotation.Belief;
+import bdi4jade.core.Capability;
+import bdi4jade.extension.palliative.graph.CauseEffectKnowledgeModel;
+import bdi4jade.extension.palliative.reasoning.PalliativeOptionGenerationFunction;
+import bdi4jade.extension.palliative.reasoning.PalliativePlanSelectionStrategy;
+
+public class PalliativeCapability extends Capability {
+
+	private static final long serialVersionUID = -1818834346847016992L;
+
+	@Belief(name = CauseEffectKnowledgeModel.NAME)
+	protected CauseEffectKnowledgeModel causeEffectKnowledgeModel = new CauseEffectKnowledgeModel();
+
+	@Belief(name = ResourcePreferences.NAME)
+	protected ResourcePreferences preferences = new ResourcePreferences();
+
+	public PalliativeCapability() {
+		setOptionGenerationFunction(new PalliativeOptionGenerationFunction(this));
+		setPlanSelectionStrategy(new PalliativePlanSelectionStrategy(this));
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/PlanRequiredResource.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/PlanRequiredResource.java
new file mode 100644
index 0000000..94abec9
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/PlanRequiredResource.java
@@ -0,0 +1,33 @@
+package bdi4jade.extension.palliative;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class PlanRequiredResource {
+
+	public static final String METADATA_NAME = PlanRequiredResource.class.getSimpleName();
+
+	private final Map<Resource, Double> requiredResources;
+
+	public PlanRequiredResource() {
+		this.requiredResources = new HashMap<>();
+	}
+
+	public Double getRequiredResource(Resource resource) {
+		return this.requiredResources.get(resource);
+	}
+
+	public Map<Resource, Double> getRequiredResources() {
+		return requiredResources;
+	}
+
+	public Set<Resource> getResources() {
+		return requiredResources.keySet();
+	}
+
+	public void setRequiredResource(Resource resource, Double value) {
+		this.requiredResources.put(resource, value);
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/reasoning/PalliativeOptionGenerationFunction.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/reasoning/PalliativeOptionGenerationFunction.java
new file mode 100644
index 0000000..fe42cbe
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/reasoning/PalliativeOptionGenerationFunction.java
@@ -0,0 +1,254 @@
+package bdi4jade.extension.palliative.reasoning;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import bdi4jade.belief.PredicateBelief;
+import bdi4jade.core.Capability;
+import bdi4jade.core.GoalUpdateSet;
+import bdi4jade.core.GoalUpdateSet.GoalDescription;
+import bdi4jade.event.GoalEvent;
+import bdi4jade.event.GoalListener;
+import bdi4jade.extension.palliative.goal.CauseEffectProblem;
+import bdi4jade.extension.palliative.goal.CauseEffectProblem.CauseEffectProblemStatus;
+import bdi4jade.extension.palliative.goal.CauseFactorStatus;
+import bdi4jade.extension.palliative.graph.AlternativeCauseSet;
+import bdi4jade.extension.palliative.graph.CauseEffectKnowledgeModel;
+import bdi4jade.extension.palliative.graph.CauseEffectRelationship;
+import bdi4jade.extension.palliative.logics.Fact;
+import bdi4jade.goal.Goal;
+import bdi4jade.goal.GoalStatus;
+import bdi4jade.goal.NestedGoal;
+import bdi4jade.goal.PredicateGoal;
+import bdi4jade.reasoning.OptionGenerationFunction;
+
+public class PalliativeOptionGenerationFunction implements OptionGenerationFunction {
+
+	private Capability capability;
+	private final Map<Goal, CauseEffectProblem> causeEffectProblems;
+
+	public PalliativeOptionGenerationFunction(Capability capability) {
+		setCapability(capability);
+		this.causeEffectProblems = new HashMap<>();
+	}
+
+	private CauseEffectKnowledgeModel getCauseEffectKnowledgeModel() {
+		return (CauseEffectKnowledgeModel) this.capability.getBeliefBase().getBelief(CauseEffectKnowledgeModel.NAME);
+	}
+
+	private Boolean causeFinished(Collection<CauseFactorStatus> causeEffectStatus) {
+		for (CauseFactorStatus causeFactor : causeEffectStatus) {
+			if (causeFactor.getUpdatedStatus() == null || !causeFactor.getUpdatedStatus()) {
+				return Boolean.FALSE;
+			}
+		}
+		return Boolean.TRUE;
+	}
+
+	private Boolean causeNotFound(Collection<CauseFactorStatus> causeEffectStatus) {
+		boolean existUnachievable = false;
+		boolean existOnGoing = false;
+		for (CauseFactorStatus causeFactor : causeEffectStatus) {
+			if (causeFactor.getInitialStatus() == null) {
+				if (causeFactor.getTestGoal() != null) {
+					if (causeFactor.getTestGoalStatus() != null) {
+						existUnachievable = true;
+					} else {
+						existOnGoing = true;
+					}
+				}
+			}
+		}
+		return existUnachievable && !existOnGoing;
+	}
+
+	@Override
+	public void generateGoals(GoalUpdateSet goalUpdateSet) {
+
+		// Algorithm 1 - lines 2-5
+		for (GoalDescription goalDescription : goalUpdateSet.getCurrentGoals()) {
+			Goal goal = goalDescription.getGoal();
+			Goal parentGoal = null;
+			if (goal instanceof NestedGoal) {
+				parentGoal = goal;
+				goal = ((NestedGoal) goal).getGoal();
+			}
+
+			CauseEffectProblem cep = this.causeEffectProblems.get(goal);
+			CauseEffectRelationship cer = getCauseEffectKnowledgeModel().getCauseEffectRelationship(goal);
+			if (cep == null && cer != null) {
+				cep = new CauseEffectProblem((PredicateGoal<?>) goal, cer, capability.getMyAgent(), parentGoal);
+				causeEffectProblems.put(cep.getEffectGoal(), cep);
+			}
+
+		}
+
+		Collection<CauseEffectProblem> problems = new ArrayList<>(causeEffectProblems.values());
+		for (CauseEffectProblem cep : problems) {
+			// Algorithm 1 - lines 7-17
+			for (CauseFactorStatus causeFactor : cep.getCauseFactorStatus()) {
+				updateCauseFactor(causeFactor);
+			}
+
+			// Algorithm 1 - lines 18-35
+			if (cep.getEffectGoalStatus() != null) {
+				if (knownCause(cep, cep.getCauseEffectRelationship())) {
+					if (causeFinished(cep.getCauseFactorStatus())) {
+						setEndState(cep);
+						causeEffectProblems.remove(cep.getEffectGoal());
+					} else {
+						for (CauseFactorStatus causeFactor : cep.getCauseFactorStatus()) {
+							if (!causeFactor.getUpdatedStatus() && causeFactor.getAchievementGoal() == null) {
+								Goal achievementGoal = causeFactor.generateAchievementGoal();
+								GoalListener listener = new GoalListener() {
+									@Override
+									public void goalPerformed(GoalEvent event) {
+										if (event.getStatus().isFinished()) {
+											causeFactor.setAchievementGoalStatus(event.getStatus());
+										}
+									}
+								};
+								goalUpdateSet.generateGoal(achievementGoal, capability, listener);
+							}
+						}
+					}
+				} else if (causeNotFound(cep.getCauseFactorStatus())) {
+					setEndState(cep);
+					causeEffectProblems.remove(cep);
+				} else {
+					for (CauseFactorStatus causeFactor : cep.getCauseFactorStatus()) {
+						if (causeFactor.getInitialStatus() == null && causeFactor.getTestGoal() == null) {
+							Goal testGoal = causeFactor.generateTestGoal();
+							GoalListener listener = new GoalListener() {
+								@Override
+								public void goalPerformed(GoalEvent event) {
+									if (event.getStatus().isFinished()) {
+										causeFactor.setTestGoalStatus(event.getStatus());
+									}
+								}
+							};
+							goalUpdateSet.generateGoal(testGoal, capability, listener);
+						}
+					}
+				}
+			}
+
+		}
+	}
+
+	private Boolean knownCause(CauseEffectProblem cep, CauseEffectRelationship cer) {
+		for (CauseFactorStatus cf : cep.getCauseFactorStatus()) {
+			if (cf.getInitialStatus() == null) {
+				return Boolean.FALSE;
+			}
+		}
+
+		Set<CauseFactorStatus> currentCauses = new HashSet<>();
+
+		for (Fact fact : cer.getMandatoryCauses()) {
+			CauseFactorStatus cf = cep.getCauseFactorStatus(fact);
+			if (!cf.getInitialStatus()) {
+				return Boolean.FALSE;
+			} else {
+				currentCauses.add(cf);
+			}
+		}
+
+		for (Fact fact : cer.getOptionalCauses()) {
+			CauseFactorStatus cf = cep.getCauseFactorStatus(fact);
+			if (cf.getInitialStatus()) {
+				currentCauses.add(cf);
+			}
+		}
+
+		for (AlternativeCauseSet acs : cer.getAlternativeCauseSets()) {
+			Set<CauseFactorStatus> alternativeCauses = new HashSet<>();
+			for (Fact fact : acs.getAlternativeCauses()) {
+				CauseFactorStatus cf = cep.getCauseFactorStatus(fact);
+				if (cf.getInitialStatus()) {
+					alternativeCauses.add(cf);
+					currentCauses.add(cf);
+				}
+				if (alternativeCauses.size() < acs.getMin() || alternativeCauses.size() > acs.getMax()) {
+					return Boolean.FALSE;
+				}
+			}
+		}
+
+		cep.setCauseFactorStatus(currentCauses);
+		return Boolean.TRUE;
+	}
+
+	@Override
+	public void setCapability(Capability capability) {
+		if (this.capability != null) {
+			if (!this.capability.equals(capability)) {
+				throw new IllegalArgumentException(
+						"This reasoning strategy is already associated with another capability.");
+			}
+		}
+		this.capability = capability;
+	}
+
+	private void setEndState(CauseEffectProblem cep) {
+		Collection<CauseFactorStatus> causeEffectStatus = cep.getCauseFactorStatus();
+		GoalStatus effectStatus = cep.getEffectGoalStatus();
+
+		boolean existsResolved = false;
+		boolean existsUnresolved = false;
+		for (CauseFactorStatus causeFactor : causeEffectStatus) {
+			if (causeFactor.getUpdatedStatus()) {
+				existsResolved = true;
+			} else {
+				existsUnresolved = true;
+			}
+		}
+
+		if (effectStatus.equals(GoalStatus.ACHIEVED)) {
+			if (!existsResolved) {
+				cep.setStatus(CauseEffectProblemStatus.MITIGATED);
+			} else if (!existsUnresolved) {
+				cep.setStatus(CauseEffectProblemStatus.FULLY_RESOLVED);
+			} else {
+				cep.setStatus(CauseEffectProblemStatus.PARTIALLY_RESOLVED);
+			}
+		} else {
+			if (!existsResolved) {
+				cep.setStatus(CauseEffectProblemStatus.UNSUCCESSFUL);
+			} else if (!existsUnresolved) {
+				cep.setStatus(CauseEffectProblemStatus.CAUSE_RESOLVED);
+			} else {
+				cep.setStatus(CauseEffectProblemStatus.CAUSE_PARTIALLY_RESOLVED);
+			}
+		}
+		System.out.println(cep);
+	}
+
+	private void updateCauseFactor(CauseFactorStatus cf) {
+		PredicateBelief<?> belief = (PredicateBelief<?>) this.capability.getBeliefBase()
+				.getBelief(cf.getFact().getPredicate());
+		if (belief == null)
+			return;
+
+		// Algorithm 1 - lines 8-12
+		if (cf.getInitialStatus() == null) {
+			if (belief.getValue().equals(cf.getFact().getValue())) {
+				cf.setInitialStatus(Boolean.TRUE);
+			} else {
+				cf.setInitialStatus(Boolean.FALSE);
+			}
+			cf.setUpdatedStatus(Boolean.FALSE);
+			// Algorithm 1 - lines 13-17
+		} else {
+			if ((cf.getInitialStatus() && belief.getValue().equals(!cf.getFact().getValue()))
+					|| (!cf.getInitialStatus() && belief.getValue().equals(cf.getFact().getValue()))) {
+				cf.setUpdatedStatus(Boolean.TRUE);
+			}
+		}
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/reasoning/PalliativePlanSelectionStrategy.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/reasoning/PalliativePlanSelectionStrategy.java
new file mode 100644
index 0000000..0c293c0
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/reasoning/PalliativePlanSelectionStrategy.java
@@ -0,0 +1,152 @@
+package bdi4jade.extension.palliative.reasoning;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import bdi4jade.core.Capability;
+import bdi4jade.extension.palliative.PlanRequiredResource;
+import bdi4jade.extension.palliative.Resource;
+import bdi4jade.extension.palliative.ResourcePreferences;
+import bdi4jade.extension.palliative.goal.ConstrainedGoal;
+import bdi4jade.extension.palliative.goal.ObjectiveFunction;
+import bdi4jade.extension.palliative.logics.And;
+import bdi4jade.extension.palliative.logics.LogicalExpression;
+import bdi4jade.goal.Goal;
+import bdi4jade.plan.Plan;
+import bdi4jade.reasoning.DefaultPlanSelectionStrategy;
+import bdi4jade.reasoning.PlanSelectionStrategy;
+
+public class PalliativePlanSelectionStrategy extends DefaultPlanSelectionStrategy implements PlanSelectionStrategy {
+
+	private class Boundary {
+		public final Double max;
+		public final Double min;
+
+		public Boundary(Double min, Double max) {
+			this.min = min;
+			this.max = max;
+		}
+	}
+
+	public PalliativePlanSelectionStrategy(Capability capability) {
+		setCapability(capability);
+	}
+
+	private Map<Resource, Boundary> getBoundaries(Set<Resource> resources, Set<Plan> plans) {
+		Map<Resource, Boundary> boundaries = new HashMap<>();
+
+		for (Resource resource : resources) {
+			boundaries.put(resource, new Boundary(getMinBoundary(resource, plans), getMaxBoundary(resource, plans)));
+		}
+		return boundaries;
+	}
+
+	private Set<Plan> getCandidatePlans(ConstrainedGoal goal, Set<Resource> resources, Set<Plan> plans) {
+		Set<Plan> candidatePlans = new HashSet<>();
+
+		LogicalExpression constraint = null;
+		for (LogicalExpression c : goal.getOperationConstraints()) {
+			if (constraint == null) {
+				constraint = c;
+			} else {
+				c = new And(c, constraint);
+			}
+		}
+
+		for (Plan plan : plans) {
+			PlanRequiredResource prr = (PlanRequiredResource) plan.getMetadata(PlanRequiredResource.METADATA_NAME);
+			if (prr == null) {
+				candidatePlans.add(plan);
+			} else {
+				// FIXME haven't tested
+				Map<Object, Object> values = new HashMap<>();
+				values.putAll(prr.getRequiredResources());
+				if (constraint != null && constraint.getValue(values)) {
+					candidatePlans.add(plan);
+				}
+			}
+		}
+
+		return candidatePlans;
+	}
+
+	private Double getMaxBoundary(Resource resource, Set<Plan> plans) {
+		Double max = null;
+		for (Plan plan : plans) {
+			PlanRequiredResource prr = (PlanRequiredResource) plan.getMetadata(PlanRequiredResource.METADATA_NAME);
+			if (prr == null) {
+				continue;
+			}
+			Double requiredResource = prr.getRequiredResource(resource);
+			if (requiredResource != null && (max == null || max < requiredResource)) {
+				max = requiredResource;
+			}
+		}
+		return max;
+	}
+
+	private Double getMinBoundary(Resource resource, Set<Plan> plans) {
+		Double min = null;
+		for (Plan plan : plans) {
+			PlanRequiredResource prr = (PlanRequiredResource) plan.getMetadata(PlanRequiredResource.METADATA_NAME);
+			if (prr == null) {
+				continue;
+			}
+			Double requiredResource = prr.getRequiredResource(resource);
+			if (requiredResource != null && (min == null || min > requiredResource)) {
+				min = requiredResource;
+			}
+		}
+		return min;
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public Plan selectPlan(Goal goal, Set<Plan> capabilityPlans) {
+		if (goal instanceof ConstrainedGoal) {
+			ConstrainedGoal g_c = (ConstrainedGoal) goal;
+			ResourcePreferences preferences = (ResourcePreferences) capability.getBeliefBase()
+					.getBelief(ResourcePreferences.NAME);
+			Map<Resource, Boundary> boundaries = getBoundaries(preferences.getResources(), capabilityPlans);
+
+			Set<Plan> candidatePlans = getCandidatePlans(g_c, preferences.getResources(), capabilityPlans);
+
+			Plan selectedPlan = null;
+			Double maxUtility = null;
+			for (Plan plan : candidatePlans) {
+				double utility = 0;
+
+				for (Resource resource : preferences.getResources()) {
+					ObjectiveFunction obj = g_c.getObjectiveFunction().get(resource);
+					if (obj == null) {
+						continue;
+					}
+
+					Double prr = ((PlanRequiredResource) plan.getMetadata(PlanRequiredResource.METADATA_NAME))
+							.getRequiredResource(resource);
+					Double preference = preferences.getPreferenceForResource(resource);
+					Boundary boundary = boundaries.get(resource);
+
+					if (preference != null) {
+						double value = (prr - boundary.min) / ((boundary.max - boundary.min));
+						if (obj.equals(ObjectiveFunction.MINIMIZE)) {
+							value = 1 - value;
+						}
+						utility += preference * value;
+					}
+
+					if (selectedPlan == null || maxUtility < utility) {
+						selectedPlan = plan;
+						maxUtility = utility;
+					}
+				}
+			}
+			return selectedPlan;
+		} else {
+			return super.selectPlan(goal, capabilityPlans);
+		}
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/Resource.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/Resource.java
new file mode 100644
index 0000000..d60c94e
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/Resource.java
@@ -0,0 +1,10 @@
+package bdi4jade.extension.palliative;
+
+import java.io.Serializable;
+
+import jade.content.Concept;
+import jade.content.ContentElement;
+
+public interface Resource extends Serializable, Concept, ContentElement {
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/palliative/ResourcePreferences.java b/bdi-jade-extensions/src/bdi4jade/extension/palliative/ResourcePreferences.java
new file mode 100644
index 0000000..f508df1
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/palliative/ResourcePreferences.java
@@ -0,0 +1,31 @@
+package bdi4jade.extension.palliative;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import bdi4jade.belief.TransientBelief;
+
+public class ResourcePreferences extends TransientBelief<String, Map<Resource, Double>> {
+
+	public static final String NAME = "ResourcePreferences";
+
+	private static final long serialVersionUID = -3150138426400180011L;
+
+	public ResourcePreferences() {
+		super(NAME, new HashMap<Resource, Double>());
+	}
+
+	public Double getPreferenceForResource(Resource resource) {
+		return this.value.get(resource);
+	}
+
+	public Set<Resource> getResources() {
+		return getValue().keySet();
+	}
+
+	public void setPreferenceForResource(Resource resource, Double preference) {
+		this.value.put(resource, preference);
+	}
+
+}