Skip to content

Commit

Permalink
tidy up goap stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
svencc committed Sep 14, 2023
1 parent a58cbdd commit 0695be9
Show file tree
Hide file tree
Showing 11 changed files with 25 additions and 119 deletions.
19 changes: 5 additions & 14 deletions src/main/java/lib/gecom/action/GeAction.java
Original file line number Diff line number Diff line change
@@ -1,47 +1,39 @@
package lib.gecom.action;

import lib.gecom.GeAgent;
import lib.gecom.GeNullTarget;
import lib.gecom.stuff.GeNullTarget;
import lib.gecom.GeTargetable;
import lombok.*;
import lombok.experimental.SuperBuilder;

import java.util.HashMap;

@Getter
@SuperBuilder
@RequiredArgsConstructor
public abstract class GeAction implements GeActionable {
public abstract class GeAction {

@Getter
@NonNull
private final GeAgent agent;
@Getter
@NonNull
private final String name;
@Getter
@NonNull
@Builder.Default
private final Float cost = 1.0f;
@Getter
@NonNull
@Builder.Default
private final GeTargetable target = new GeNullTarget();
@NonNull
@Builder.Default
private final Float duration = 0.0f;
@Getter
@NonNull
@Builder.Default
private final HashMap<String, Integer> preconditions = new HashMap<>();
@Getter
@NonNull
@Builder.Default
private final HashMap<String, Integer> afterEffects = new HashMap<>();
// @NonNull
// @NonNull
// @Builder.Default
// private final GeWorldStates worldState = new GeWorldStates(); // required to calculate isAchievable!
@Setter
@Getter
@Setter
@Builder.Default
private boolean actionRunning = false;

Expand All @@ -54,7 +46,6 @@ public boolean arePreconditionsMet(@NonNull final HashMap<String, Integer> state
.allMatch(entry -> state.containsKey(entry.getKey()) && state.get(entry.getKey()).equals(entry.getValue()));
}


public abstract boolean prePerform();

public abstract boolean postPerform();
Expand Down
17 changes: 0 additions & 17 deletions src/main/java/lib/gecom/action/GeActionable.java

This file was deleted.

52 changes: 0 additions & 52 deletions src/main/java/lib/gecom/action/GeAnonymousAction.java

This file was deleted.

1 change: 1 addition & 0 deletions src/main/java/lib/gecom/plan/GePlan.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ public int compareTo(@NonNull final GePlan other) {

return mine.compareTo(theirs);
}

}
28 changes: 13 additions & 15 deletions src/main/java/lib/gecom/plan/GePlanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public Optional<GePlan> planCheapest(
}
}

// public List<GeNode> plan(
@NonNull
public PriorityQueue<GePlan> plan(
@NonNull final HashMap<String, Integer> agentsBelieves,
@NonNull final List<GeAction> possibleActions,
Expand All @@ -41,20 +41,20 @@ public PriorityQueue<GePlan> plan(
}
});

final List<GeNode> leaves = new ArrayList<>();
final GeNode start = new GeNode(null, agentsBelieves, null, 0f);
final List<GePlanningNode> leaves = new ArrayList<>();
final GePlanningNode startNode = new GePlanningNode(null, agentsBelieves, null, 0f);

boolean success = buildGraph(start, leaves, usableActions, goal);
boolean success = buildGraph(startNode, leaves, usableActions, goal);

if (!success) {
log.error("No solution found!");
return new PriorityQueue<>();
}

final PriorityQueue<GePlan> plans = new PriorityQueue<>();
for (@NonNull final GeNode currentPlansLastNode : leaves) {
for (@NonNull final GePlanner.GePlanningNode currentPlansLastNode : leaves) {
final ArrayList<GeAction> currentPlansActions = new ArrayList<>();
GeNode node = currentPlansLastNode;
GePlanningNode node = currentPlansLastNode;
while (node != null) {
if (node.action != null) {
currentPlansActions.add(node.action);
Expand All @@ -74,8 +74,8 @@ public PriorityQueue<GePlan> plan(
}

private boolean buildGraph(
@NonNull final GeNode parent,
@NonNull final List<GeNode> foundPlans,
@NonNull final GePlanner.GePlanningNode parent,
@NonNull final List<GePlanningNode> foundPlans,
@NonNull final List<GeAction> usableActions,
@NonNull final HashMap<String, Integer> goal
) {
Expand All @@ -92,7 +92,7 @@ private boolean buildGraph(
}
}

final GeNode derivedNodeFromPerformedAction = new GeNode(parent, currentState, action, parent.cost + action.getCost());
final GePlanningNode derivedNodeFromPerformedAction = new GePlanningNode(parent, currentState, action, parent.cost + action.getCost());

if (goalAchieved(goal, currentState)) {
// stop building the graph and return the path; as we found a path
Expand Down Expand Up @@ -133,26 +133,24 @@ private List<GeAction> subsetOfActions(
}


//@TODO can we use our old node?
@Getter
public class GeNode {
private static class GePlanningNode {
@Nullable
public final GeNode parent;
public final GePlanningNode parent;
@NonNull
public final HashMap<String, Integer> state;
@Nullable
public final GeAction action;
@NonNull
public Float cost;

public GeNode(
@Nullable final GeNode parent,
public GePlanningNode(
@Nullable final GePlanningNode parent,
@NonNull final HashMap<String, Integer> state,
@Nullable final GeAction action,
@NonNull final Float cost
) {
this.parent = parent;
// this.state = (HashMap<String, Integer>) state.clone(); // @TODO make a copy!
this.state = state;
this.action = action;
this.cost = cost;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package lib.gecom;
package lib.gecom.stuff;

import lib.gecom.action.GeAction;
import lib.gecom.plan.GePlan;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package lib.gecom;
package lib.gecom.stuff;

import lib.gecom.GeTargetable;
import lombok.NoArgsConstructor;
import lombok.NonNull;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package lib.gecom;
package lib.gecom.stuff;

import lombok.Getter;
import lombok.NonNull;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package lib.gecom;
package lib.gecom.stuff;

import lombok.Getter;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package lib.gecom;
package lib.gecom.stuff;

import lombok.Getter;
import lombok.NoArgsConstructor;
Expand Down
16 changes: 0 additions & 16 deletions src/test/java/lib/gecom/plan/GePlannerTest.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package lib.gecom.plan;

import lib.gecom.GeAgent;
import lib.gecom.action.GeAction;
import lib.gecom.plan.GePlan;
import lib.gecom.plan.GePlanner;
import lombok.experimental.SuperBuilder;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -60,10 +57,8 @@ void planCheapest_withOneSimpleAchievableAction_givesOnePlan() {
goal.put("goal", 1);

// Create an action that fulfills the goal
final GeAgent agent = new GeAgent(possibleActions);
final GeAction action = TestAction.builder()
.name("SetGoalToOneAction")
.agent(agent) // @TODO dependency of action to agent is not good. Decouple it. I dont know if the action should be bound to an agent Makes sense if action has an internal state!
.build();
action.getPreconditions().put("goal", 0);
action.getAfterEffects().put("goal", 1);
Expand Down Expand Up @@ -95,18 +90,15 @@ void planCheapest_withTwoSimpleAchievableAction_givesOnePlan() {
goal.put("i-am-hungry", 0);

// Create an action that fulfills the goal
final GeAgent agent = new GeAgent(possibleActions);
final GeAction findSomethingToEat = TestAction.builder()
.name("find-something-to-eat")
.agent(agent) // @TODO dependency of action to agent is not good. Decouple it. I dont know if the action should be bound to an agent Makes sense if action has an internal state!
.build();
findSomethingToEat.getPreconditions().put("has-something-to-eat", 0);
findSomethingToEat.getAfterEffects().put("has-something-to-eat", 1);
possibleActions.add(findSomethingToEat);

final GeAction eat = TestAction.builder()
.name("eat")
.agent(agent) // @TODO dependency of action to agent is not good. Decouple it. I dont know if the action should be bound to an agent Makes sense if action has an internal state!
.build();
eat.getPreconditions().put("has-something-to-eat", 1);
eat.getAfterEffects().put("i-am-hungry", 0);
Expand Down Expand Up @@ -141,18 +133,15 @@ void planCheapest_withTwoConcurrentAchievableBranches_givesCheapestPlan() {
goal.put("i-am-hungry", 0);

// Create an action that fulfills the goal
final GeAgent agent = new GeAgent(possibleActions);
final GeAction findSomethingToEat = TestAction.builder()
.name("find-something-to-eat")
.agent(agent) // @TODO dependency of action to agent is not good. Decouple it. I dont know if the action should be bound to an agent Makes sense if action has an internal state!
.build();
findSomethingToEat.getPreconditions().put("has-something-to-eat", 0);
findSomethingToEat.getAfterEffects().put("has-something-to-eat", 1);
possibleActions.add(findSomethingToEat);

final GeAction eat = TestAction.builder()
.name("eat")
.agent(agent) // @TODO dependency of action to agent is not good. Decouple it. I dont know if the action should be bound to an agent Makes sense if action has an internal state!
.build();
eat.getPreconditions().put("has-something-to-eat", 1);
eat.getAfterEffects().put("i-am-hungry", 0);
Expand All @@ -161,7 +150,6 @@ void planCheapest_withTwoConcurrentAchievableBranches_givesCheapestPlan() {

final GeAction action3 = TestAction.builder()
.name("hunt")
.agent(agent) // @TODO dependency of action to agent is not good. Decouple it. I dont know if the action should be bound to an agent Makes sense if action has an internal state!
.cost(10.0f)
.build();
action3.getPreconditions().put("has-something-to-eat", 0);
Expand Down Expand Up @@ -196,18 +184,15 @@ void plan_withTwoConcurrentAchievableBranches_gives2Plans() {
goal.put("i-am-hungry", 0);

// Create an action that fulfills the goal
final GeAgent agent = new GeAgent(possibleActions);
final GeAction findSomethingToEat = TestAction.builder()
.name("find-something-to-eat")
.agent(agent) // @TODO dependency of action to agent is not good. Decouple it. I dont know if the action should be bound to an agent Makes sense if action has an internal state!
.build();
findSomethingToEat.getPreconditions().put("has-something-to-eat", 0);
findSomethingToEat.getAfterEffects().put("has-something-to-eat", 1);
possibleActions.add(findSomethingToEat);

final GeAction eat = TestAction.builder()
.name("eat")
.agent(agent) // @TODO dependency of action to agent is not good. Decouple it. I dont know if the action should be bound to an agent Makes sense if action has an internal state!
.build();
eat.getPreconditions().put("has-something-to-eat", 1);
eat.getAfterEffects().put("i-am-hungry", 0);
Expand All @@ -216,7 +201,6 @@ void plan_withTwoConcurrentAchievableBranches_gives2Plans() {

final GeAction hunt = TestAction.builder()
.name("hunt")
.agent(agent) // @TODO dependency of action to agent is not good. Decouple it. I dont know if the action should be bound to an agent Makes sense if action has an internal state!
.cost(10.0f)
.build();
hunt.getPreconditions().put("has-something-to-eat", 0);
Expand Down

0 comments on commit 0695be9

Please sign in to comment.