Skip to content

Commit

Permalink
Merge master to lifelong (#47)
Browse files Browse the repository at this point in the history
* changes required to create LaCAM builder class (#37)

* Add low level expansion/generation rate, and add all rates to A_RunManager output ("log" files)

* add generation and expansion rates for low-level

* fix low level expansion/generation rate metric

* simplify (and optimize?) TieBreakingForLessConflictsAndHigherG

* lacam constraints support (#39)

* add constraints support in lacam, do constraints checks only if necessary for efficiency

* Update src/main/java/BasicMAPF/Solvers/LaCAM/LaCAM_Solver.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/BasicMAPF/Solvers/LaCAM/LaCAM_Solver.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/BasicMAPF/Solvers/LaCAM/LaCAM_Solver.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/BasicMAPF/Solvers/LaCAM/LaCAM_Solver.java

Co-authored-by: J-morag <[email protected]>

* refactoring and removing not necessary constraints set

* add constraints handling test

---------

Co-authored-by: J-morag <[email protected]>

* Add regenerated nodes metric. Low level only.

* Add regenerated nodes metric. Low level only.

* simplify Move.equals

* Transient seperating vertices (#43)

* add boolean to TransientMAPFSettings indicates avoid separating vertices

* Implementing Tarjan's Algorithm to find cut vertices with Iterative DFS

* Add separating vertices set to RunParameters

* Update src/main/java/BasicMAPF/DataTypesAndStructures/RunParameters.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/BasicMAPF/DataTypesAndStructures/RunParameters.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/BasicMAPF/DataTypesAndStructures/RunParameters.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/BasicMAPF/DataTypesAndStructures/RunParametersBuilder.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/BasicMAPF/Solvers/LaCAM/LaCAM_Solver.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/BasicMAPF/Solvers/LaCAM/LaCAM_Solver.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/TransientMAPF/TransientMAPFSettings.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/BasicMAPF/Solvers/LaCAM/LaCAM_Solver.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/BasicMAPF/Solvers/LaCAM/LaCAM_Solver.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/BasicMAPF/Solvers/LaCAM/LaCAM_Solver.java

Co-authored-by: J-morag <[email protected]>

* throw exceptions where needed, add separating vertices support for PIBT and improve efficiency

* refactoring of files locations, support finding SVs to I_ExplicitMap, make SV finder static, improve SV test class,

* Update src/main/java/BasicMAPF/Solvers/PrioritisedPlanning/PrioritisedPlanning_Solver.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/TransientMAPF/SeparatingVerticesFinder.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/BasicMAPF/Solvers/CBS/CBS_Solver.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/BasicMAPF/Solvers/LargeNeighborhoodSearch/LargeNeighborhoodSearch_Solver.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/TransientMAPF/SeparatingVerticesFinder.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/TransientMAPF/TransientMAPFExampleMain.java

Co-authored-by: J-morag <[email protected]>

* Update src/test/java/BasicMAPF/Solvers/LargeNeighborhoodSearch/LargeNeighborhoodSearch_SolverTest.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/TransientMAPF/SeparatingVerticesFinder.java

Co-authored-by: J-morag <[email protected]>

* Update src/main/java/TransientMAPF/SeparatingVerticesFinder.java

Co-authored-by: J-morag <[email protected]>

* visualize SV in visualizer and print in test

* final fixes before PR

---------

Co-authored-by: J-morag <[email protected]>

* merge fixes and add LaCAMBuilder

---------

Co-authored-by: J-morag <[email protected]>
  • Loading branch information
NoyGabay and J-morag authored Nov 18, 2024
1 parent e6fd292 commit fe934e8
Show file tree
Hide file tree
Showing 25 changed files with 516 additions and 102 deletions.
14 changes: 3 additions & 11 deletions src/main/java/BasicMAPF/DataTypesAndStructures/Move.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,12 @@ public String toString() {
return this.timeNow + ":" + this.prevLocation.getCoordinate() + "->" + this.currLocation.getCoordinate();
}

/**
* Ignores the {@link #agent} field.
*/
@Override
public boolean equals(Object o) {
public final boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Move move = (Move) o;

if (timeNow != move.timeNow) return false;
if (!prevLocation.equals(move.prevLocation)) return false;
return currLocation.equals(move.currLocation);
if (!(o instanceof Move move)) return false;

return timeNow == move.timeNow && prevLocation.equals(move.prevLocation) && currLocation.equals(move.currLocation);
}

/**
Expand Down
15 changes: 13 additions & 2 deletions src/main/java/BasicMAPF/DataTypesAndStructures/RunParameters.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package BasicMAPF.DataTypesAndStructures;

import BasicMAPF.Instances.Agent;
import BasicMAPF.Instances.Maps.I_Location;
import BasicMAPF.Solvers.AStar.CostsAndHeuristics.SingleAgentGAndH;
import BasicMAPF.Solvers.ConstraintsAndConflicts.Constraint.I_ConstraintSet;
import BasicMAPF.Solvers.I_Solver;
Expand All @@ -10,6 +11,7 @@
import org.jetbrains.annotations.Nullable;

import java.util.Random;
import java.util.Set;

/**
* A set of parameters for a {@link I_Solver solver} to use when solving an {@link BasicMAPF.Instances.MAPF_Instance instance}.
Expand Down Expand Up @@ -61,6 +63,14 @@ public class RunParameters {
* optional heuristic function to use in the single agent solver.
*/
public final SingleAgentGAndH singleAgentGAndH;

/**
* Set of separating vertices for a given map.
* Separating vertices are vertices in a graph whose removal increases the number of connected componenets in a graph,
* effectively disconneccting it.
*/
public final Set<I_Location> separatingVertices;

/**
* Start time of the problem. {@link Solution solutions} and {@link SingleAgentPlan plans} start at this time.
* Not real-time.
Expand All @@ -87,7 +97,7 @@ public class RunParameters {
* Intentionally package-private constructor.
* Use {@link RunParametersBuilder} to create a {@link RunParameters} object.
*/
RunParameters(long timeout, I_ConstraintSet constraints, InstanceReport instanceReport, Solution existingSolution, long softTimeout, SingleAgentGAndH singleAgentGAndH, int problemStartTime, @Nullable Random randomNumberGenerator, Agent[] priorityOrder) {
RunParameters(long timeout, I_ConstraintSet constraints, InstanceReport instanceReport, Solution existingSolution, long softTimeout, SingleAgentGAndH singleAgentGAndH, int problemStartTime, @Nullable Random randomNumberGenerator, Agent[] priorityOrder, Set<I_Location> separatingVertices) {
this.timeout = timeout;
this.softTimeout = softTimeout;
if (this.softTimeout > this.timeout){
Expand All @@ -100,10 +110,11 @@ public class RunParameters {
this.problemStartTime = problemStartTime;
this.randomNumberGenerator = randomNumberGenerator;
this.priorityOrder = priorityOrder;
this.separatingVertices = separatingVertices;
}

public RunParameters(RunParameters runParameters) {
this(runParameters.timeout, runParameters.constraints, runParameters.instanceReport, runParameters.existingSolution, runParameters.softTimeout, runParameters.singleAgentGAndH, runParameters.problemStartTime, runParameters.randomNumberGenerator, runParameters.priorityOrder);
this(runParameters.timeout, runParameters.constraints, runParameters.instanceReport, runParameters.existingSolution, runParameters.softTimeout, runParameters.singleAgentGAndH, runParameters.problemStartTime, runParameters.randomNumberGenerator, runParameters.priorityOrder, runParameters.separatingVertices);
}

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package BasicMAPF.DataTypesAndStructures;

import BasicMAPF.Instances.Agent;
import BasicMAPF.Instances.Maps.I_Location;
import BasicMAPF.Solvers.AStar.CostsAndHeuristics.SingleAgentGAndH;
import BasicMAPF.Solvers.ConstraintsAndConflicts.Constraint.I_ConstraintSet;
import Environment.Metrics.InstanceReport;

import java.util.Random;
import java.util.Set;

public class RunParametersBuilder {
private long timeout = 1000*60*5 /*5 minutes*/;
Expand All @@ -17,6 +19,7 @@ public class RunParametersBuilder {
public int problemStartTime = 0;
public Random randomNumberGenerator;
public Agent[] priorityOrder;
public Set<I_Location> separatingVertices;

public RunParametersBuilder copy(RunParameters rp) {
this.timeout = rp.timeout;
Expand All @@ -28,6 +31,7 @@ public RunParametersBuilder copy(RunParameters rp) {
this.problemStartTime = rp.problemStartTime;
this.randomNumberGenerator = rp.randomNumberGenerator;
this.priorityOrder = rp.priorityOrder;
this.separatingVertices = rp.separatingVertices;
return this;
}

Expand Down Expand Up @@ -104,7 +108,15 @@ public RunParametersBuilder setPriorityOrder(Agent[] priorityOrder) {
return this;
}

/**
* @see RunParameters#separatingVertices
*/
public RunParametersBuilder setseparatingVertices(Set<I_Location> separatingVertices) {
this.separatingVertices = separatingVertices;
return this;
}

public RunParameters createRP() {
return new RunParameters(timeout, constraints, instanceReport, existingSolution, softTimeout, singleAgentGAndH, problemStartTime, randomNumberGenerator, priorityOrder);
return new RunParameters(timeout, constraints, instanceReport, existingSolution, softTimeout, singleAgentGAndH, problemStartTime, randomNumberGenerator, priorityOrder, separatingVertices);
}
}
17 changes: 10 additions & 7 deletions src/main/java/BasicMAPF/Solvers/AStar/SingleAgentAStar_Solver.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public class SingleAgentAStar_Solver extends A_Solver {
protected int problemStartTime;
protected int expandedNodes;
private int generatedNodes;
private int numRegeneratedNodes;
/**
* Maximum allowed f value ({@link SingleAgentPlan} cost). Will stop and return null if proved that it cannot be found.
*/
Expand Down Expand Up @@ -156,6 +157,7 @@ protected void init(MAPF_Instance instance, RunParameters runParameters){

this.expandedNodes = 0;
this.generatedNodes = 0;
this.numRegeneratedNodes = 0;
}

/* = A* algorithm = */
Expand Down Expand Up @@ -336,6 +338,7 @@ protected void writeMetricsToReport(Solution solution) {
if(instanceReport != null){
instanceReport.putIntegerValue(InstanceReport.StandardFields.expandedNodesLowLevel, this.expandedNodes);
instanceReport.putIntegerValue(InstanceReport.StandardFields.generatedNodesLowLevel, this.generatedNodes);
instanceReport.putIntegerValue(InstanceReport.StandardFields.regeneratedNodesLowLevel, this.numRegeneratedNodes);
}
}

Expand Down Expand Up @@ -425,7 +428,10 @@ private float calcH() {

protected void keepTheStateWithMinG(AStarState newState, AStarState existingState) {
// decide which state to keep, seeing as how they are both equal and in open.
openList.keepOne(existingState, newState, SingleAgentAStar_Solver.equalStatesDiscriminator);
AStarState dropped = openList.keepOne(existingState, newState, SingleAgentAStar_Solver.equalStatesDiscriminator);
if (dropped == existingState){
SingleAgentAStar_Solver.this.numRegeneratedNodes++;
}
}

/**
Expand Down Expand Up @@ -523,12 +529,10 @@ protected int getG(@Nullable AStarState prev, Move move){
* For sorting the open list.
*/
private static class TieBreakingForLessConflictsAndHigherG implements Comparator<AStarState>{

private static final Comparator<AStarState> fComparator = Comparator.comparing(AStarState::getF);

@Override
public int compare(AStarState o1, AStarState o2) {
if(Math.abs(o1.getF() - o2.getF()) < 0.1){ // floats are equal
float fCompared = o1.getF() - o2.getF();
if(Math.abs(fCompared) < 0.1){ // floats are equal
// if f() value is equal, we consider the state with less conflicts to be better.
if(o1.conflicts == o2.conflicts){
// if equal in conflicts, we break ties for higher g. Therefore, we want to return a negative
Expand All @@ -547,7 +551,7 @@ public int compare(AStarState o1, AStarState o2) {
}
}
else {
return fComparator.compare(o1, o2);
return fCompared > 0 ? 1 : -1;
}
}
}
Expand All @@ -572,7 +576,6 @@ public int compare(AStarState o1, AStarState o2) {
else{
return o1.conflicts - o2.conflicts; // less conflicts is better
}

}
else {
return o1.g - o2.g; //lower g is better
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/BasicMAPF/Solvers/A_Solver.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public abstract class A_Solver implements I_Solver{
protected long endTime;
protected boolean abortedForTimeout;
protected int totalLowLevelNodesGenerated;
protected int totalLowLevelNodesRegenerated;
protected int totalLowLevelNodesExpanded;
protected int totalLowLevelTimeMS;
protected int totalLowLevelCalls;
Expand Down Expand Up @@ -87,6 +88,7 @@ protected void init(MAPF_Instance instance, RunParameters parameters){
this.generatedNodes = 0;

this.totalLowLevelNodesGenerated = 0;
this.totalLowLevelNodesRegenerated = 0;
this.totalLowLevelNodesExpanded = 0;
this.totalLowLevelTimeMS = 0;
this.totalLowLevelCalls = 0;
Expand All @@ -105,6 +107,8 @@ protected void init(MAPF_Instance instance, RunParameters parameters){
protected void digestSubproblemReport(InstanceReport subproblemReport) {
Integer statesGenerated = subproblemReport.getIntegerValue(InstanceReport.StandardFields.generatedNodesLowLevel);
this.totalLowLevelNodesGenerated += statesGenerated==null ? 0 : statesGenerated;
Integer statesRegenerated = subproblemReport.getIntegerValue(InstanceReport.StandardFields.regeneratedNodesLowLevel);
this.totalLowLevelNodesRegenerated += statesRegenerated==null ? 0 : statesRegenerated;
Integer statesExpanded = subproblemReport.getIntegerValue(InstanceReport.StandardFields.expandedNodesLowLevel);
this.totalLowLevelNodesExpanded += statesExpanded==null ? 0 : statesExpanded;
Integer totalLowLevelTimeMS = subproblemReport.getIntegerValue(InstanceReport.StandardFields.elapsedTimeMS);
Expand Down Expand Up @@ -144,9 +148,12 @@ protected void writeMetricsToReport(Solution solution){
else{
instanceReport.putIntegerValue(InstanceReport.StandardFields.solved, 0);
}
instanceReport.putIntegerValue(InstanceReport.StandardFields.totalLowLevelTimeMS, this.totalLowLevelTimeMS);
instanceReport.putIntegerValue(InstanceReport.StandardFields.generatedNodesLowLevel, this.totalLowLevelNodesGenerated);
instanceReport.putFloatValue(InstanceReport.StandardFields.generationRateLowLevel,(float) this.totalLowLevelNodesGenerated / ((float) (this.totalLowLevelTimeMS) / 1000f));
instanceReport.putIntegerValue(InstanceReport.StandardFields.regeneratedNodesLowLevel, this.totalLowLevelNodesRegenerated);
instanceReport.putIntegerValue(InstanceReport.StandardFields.expandedNodesLowLevel, this.totalLowLevelNodesExpanded);
instanceReport.putIntegerValue(InstanceReport.StandardFields.totalLowLevelTimeMS, this.totalLowLevelTimeMS);
instanceReport.putFloatValue(InstanceReport.StandardFields.expansionRateLowLevel, (float) this.totalLowLevelNodesExpanded / ((float) (this.totalLowLevelTimeMS) / 1000f));
instanceReport.putIntegerValue(InstanceReport.StandardFields.totalLowLevelCalls, this.totalLowLevelCalls);
}

Expand Down
5 changes: 4 additions & 1 deletion src/main/java/BasicMAPF/Solvers/CBS/CBS_Solver.java
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ public class CBS_Solver extends A_Solver implements I_LifelongCompatibleSolver {
this.ignoresStayAtSharedGoals = Objects.requireNonNullElse(ignoresStayAtSharedGoals, false);
this.sharedSources = Objects.requireNonNullElse(sharedSources, false);
this.transientMAPFSettings = Objects.requireNonNullElse(transientMAPFSettings, TransientMAPFSettings.defaultRegularMAPF);
if (this.transientMAPFSettings.avoidSeparatingVertices()) {
throw new IllegalArgumentException("CBS does not support transient with separating vertices.");
}
if (RHCR_Horizon != null && RHCR_Horizon <= 0){
throw new IllegalArgumentException("RHCR_Horizon must be positive");
}
Expand Down Expand Up @@ -404,7 +407,7 @@ private RunParameters getSubproblemParameters(Solution currentSolution, I_Constr

// TMAPF goal condition
if (transientMAPFSettings.isTransientMAPF()){
if (transientMAPFSettings.useBlacklist()) {
if (transientMAPFSettings.avoidOtherAgentsTargets()) {
Set<I_Coordinate> targetsOfAgentsThatHaventPlannedYet = new HashSet<>();
for (Agent agentToBlack : this.instance.agents) {
if (!agent.equals(agentToBlack)) {
Expand Down
45 changes: 45 additions & 0 deletions src/main/java/BasicMAPF/Solvers/LaCAM/LaCAMBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package BasicMAPF.Solvers.LaCAM;

import BasicMAPF.CostFunctions.I_SolutionCostFunction;
import BasicMAPF.CostFunctions.SumOfCosts;
import TransientMAPF.TransientMAPFSettings;

import java.util.Objects;

public class LaCAMBuilder {
private I_SolutionCostFunction solutionCostFunction = null;
private TransientMAPFSettings transientMAPFSettings = null;
private Integer RHCR_Horizon = Integer.MAX_VALUE;

private Boolean returnPartialSolutions = false;

private Boolean ignoresStayAtSharedGoals = false;
public LaCAMBuilder setSolutionCostFunction(I_SolutionCostFunction solutionCostFunction) {
this.solutionCostFunction = solutionCostFunction;
return this;
}

public LaCAMBuilder setTransientMAPFBehaviour(TransientMAPFSettings transientMAPFSettings) {
this.transientMAPFSettings = transientMAPFSettings;
return this;
}

public LaCAMBuilder setRHCRHorizon(Integer RHCR_Horizon) {
this.RHCR_Horizon = RHCR_Horizon;
return this;
}

public LaCAMBuilder setReturnPartialSolutions(Boolean returnPartialSolutions) {
this.returnPartialSolutions = returnPartialSolutions;
return this;
}

public LaCAMBuilder setIgnoresStayAtSharedGoals(Boolean ignoresStayAtSharedGoals) {
this.ignoresStayAtSharedGoals = ignoresStayAtSharedGoals;
return this;
}

public LaCAM_Solver createLaCAM() {
return new LaCAM_Solver(solutionCostFunction, transientMAPFSettings, RHCR_Horizon, returnPartialSolutions, ignoresStayAtSharedGoals);
}
}
3 changes: 1 addition & 2 deletions src/main/java/BasicMAPF/Solvers/LaCAM/LaCAMStar_Solver.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class LaCAMStar_Solver extends A_Solver {
* @param transientMAPFSettings indicates whether to solve transient-MAPF.
*/
public LaCAMStar_Solver(I_SolutionCostFunction solutionCostFunction, TransientMAPFSettings transientMAPFSettings) {
this.lacamSolver = new LaCAM_Solver(solutionCostFunction, transientMAPFSettings, null, null, null);
this.lacamSolver = new LaCAMBuilder().setSolutionCostFunction(solutionCostFunction).setTransientMAPFBehaviour(transientMAPFSettings).createLaCAM();
super.name = "LaCAMStar" + (this.lacamSolver.transientMAPFSettings.isTransientMAPF() ? "t" : "");
}

Expand Down Expand Up @@ -353,7 +353,6 @@ protected void releaseMemory() {
@Override
protected void writeMetricsToReport(Solution solution) {
super.writeMetricsToReport(solution);

this.lacamSolver.writeMetricsToReport(solution);
this.expandedNodes += instanceReport.getIntegerValue(InstanceReport.StandardFields.expandedNodes);
this.generatedNodes += instanceReport.getIntegerValue(InstanceReport.StandardFields.generatedNodes);
Expand Down
Loading

0 comments on commit fe934e8

Please sign in to comment.