Skip to content

Commit

Permalink
Improved the applicability graph generation time and memory consumption
Browse files Browse the repository at this point in the history
  • Loading branch information
kris701 committed Jun 12, 2024
1 parent f57ff46 commit 9ab6020
Show file tree
Hide file tree
Showing 15 changed files with 108 additions and 60 deletions.
56 changes: 53 additions & 3 deletions FlashPlanner.Core/Models/BitMask.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
namespace FlashPlanner.Core.Models
using System.Collections;

namespace FlashPlanner.Core.Models
{

/// <summary>
/// An implementation of 32 bit bitmasks.
/// It is strongly inspired by the <seealso cref="System.Collections.BitArray"/> class
/// </summary>
public class BitMask
public class BitMask : IEnumerable<int>
{
/// <summary>
/// How many indexes can be stored in the bitmask
/// </summary>
public int Length { get; set; }
public int Length;

internal int[] _data;
internal readonly int _dataLength;
Expand Down Expand Up @@ -130,5 +132,53 @@ public bool IsSubsetOf(BitMask other)
return false;
return true;
}

public override string ToString()
{
var str = $"Facts ({GetTrueBits()}): ";
foreach (var fact in this)
str += $"{fact}, ";
return str;
}

public IEnumerator<int> GetEnumerator() => new BitMaskEnumerator(this);

IEnumerator IEnumerable.GetEnumerator() => new BitMaskEnumerator(this);
}

public class BitMaskEnumerator : IEnumerator<int>
{
private readonly BitMask _mask;
private int _position = -1;

public BitMaskEnumerator(BitMask mask)
{
_mask = mask;
}

public bool MoveNext()
{
do
{
_position++;
if (_position >= _mask.Length)
return false;
}
while (!_mask[_position]);
return (_position < _mask.Length);
}

public void Reset()
{
_position = -1;
}

object IEnumerator.Current => Current;

public int Current => _position;

public void Dispose()
{
}
}
}
25 changes: 25 additions & 0 deletions FlashPlanner.Core/Models/LinkedGraph.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace FlashPlanner.Core.Models
{
public class LinkedGraph
{
private readonly BitMask[] _matrix;

public LinkedGraph(int size)
{
_matrix = new BitMask[size];
for (int i = 0; i < size; i++)
_matrix[i] = new BitMask(size);
}

public BitMask this[int from] => _matrix[from];

public void LinkAll(int from, List<int> tos)
{
foreach (var to in tos)
if (to != from)
_matrix[from][to] = true;
}

public int Count => _matrix.Sum(x => x.GetTrueBits());
}
}
2 changes: 1 addition & 1 deletion FlashPlanner.Core/Models/SAS/SASDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public SASDecl(List<Operator> operators, Fact[] goal, Fact[] init, int factCount
Operators = operators;
Goal = goal;
Init = init;
_operatorDict = new Dictionary<int, Operator>();
_operatorDict = new Dictionary<int, Operator>(operators.Count);
foreach (var op in operators)
{
if (_operatorDict.ContainsKey(op.ID))
Expand Down
2 changes: 1 addition & 1 deletion FlashPlanner.Core/Models/StateMove.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public StateMove(SASStateSpace state)
State = state;
hValue = int.MaxValue;
Steps = 0;
Operator = -1;
Operator = 0;
}

/// <summary>
Expand Down
5 changes: 2 additions & 3 deletions FlashPlanner.Core/Models/TranslatorContext.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using FlashPlanner.Core.Models.SAS;
using PDDLSharp.Models.PDDL;
using PDDLSharp.Models.PDDL.Expressions;

namespace FlashPlanner.Core.Models
{
Expand All @@ -24,7 +23,7 @@ public class TranslatorContext
/// <summary>
/// A graph saying that when a given operator have been executed, these following operators could now be applicable
/// </summary>
public Dictionary<int, List<int>> ApplicabilityGraph;
public LinkedGraph ApplicabilityGraph;

/// <summary>
/// Main constructor
Expand All @@ -49,7 +48,7 @@ public TranslatorContext()
SAS = new SASDecl();
PDDL = new PDDLDecl();
FactHashes = new int[0];
ApplicabilityGraph = new Dictionary<int, List<int>>();
ApplicabilityGraph = new LinkedGraph(0);
}
}
}
4 changes: 2 additions & 2 deletions FlashPlanner.Core/RelaxedPlanningGraphs/OperatorRPG.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ public List<Layer> GenerateRelaxedPlanningGraph(RelaxedSASStateSpace state, List
List<Layer> layers = new List<Layer>();
var newLayer = new Layer(
GetNewApplicableOperators(state, operators, covered),
state.GetFacts());
state.ToHashSet());
layers.Add(newLayer);
int previousLayer = 0;
while (!state.IsInGoal())
Expand All @@ -168,7 +168,7 @@ public List<Layer> GenerateRelaxedPlanningGraph(RelaxedSASStateSpace state, List

newLayer = new Layer(
GetNewApplicableOperators(state, operators, covered),
state.GetFacts());
state.ToHashSet());

// Error condition: there are no applicable actions at all (most likely means the problem is unsolvable)
if (newLayer.Operators.Count == 0 && !state.IsInGoal())
Expand Down
23 changes: 3 additions & 20 deletions FlashPlanner.Core/States/SASStateSpace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,29 +94,12 @@ public SASStateSpace(SASStateSpace other, List<Operator> ops) : this(other)
Count = _state.GetTrueBits();
}

/// <summary>
/// Get all the facts in the state space.
/// </summary>
/// <returns></returns>
public HashSet<int> GetFacts()
{
var set = new HashSet<int>();
for (int i = 0; i < _state.Length; i++)
if (_state[i])
set.Add(i);

return set;
}

/// <summary>
/// If the state contains a given fact, by its SAS ID
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool this[int id]
{
get => _state[id];
}
public bool this[int id] => _state[id];

/// <summary>
/// Equals override for the state
Expand Down Expand Up @@ -172,7 +155,7 @@ public bool IsApplicable(Operator op)
/// Iterator to iterate through the facts in the state space.
/// </summary>
/// <returns></returns>
public IEnumerator<int> GetEnumerator() => GetFacts().GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetFacts().GetEnumerator();
public IEnumerator<int> GetEnumerator() => _state.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => _state.GetEnumerator();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using FlashPlanner.Core.Models;
using FlashPlanner.Core.Models.SAS;
using FlashPlanner.Core.States;
using System.Xml.Linq;

namespace FlashPlanner.Core.Translators.Phases
{
Expand Down Expand Up @@ -34,24 +33,24 @@ public override TranslatorContext ExecutePhase(TranslatorContext from)

private TranslatorContext GenerateTotalGraph(TranslatorContext from)
{
var graphs = new Dictionary<int, List<int>>();
var graphs = new LinkedGraph(from.SAS.Operators.Count + 1);
var inits = GetInitApplicableOperators(from);
var all = from.SAS.Operators.Select(x => x.ID).ToList();
// -1 is from the initial state
graphs.Add(-1, inits.ToList());
// 0 is from the initial state
graphs.LinkAll(0, inits);
foreach (var op in from.SAS.Operators)
graphs.Add(op.ID, all);
graphs.LinkAll(op.ID, all);

from = new TranslatorContext(from) { ApplicabilityGraph = graphs };
return from;
}

private TranslatorContext GenerateApplicabilityGraph(TranslatorContext from, Dictionary<string, List<int>> argGraph, Dictionary<int, List<int>> preGraph)
{
var graphs = new Dictionary<int, List<int>>();
var graphs = new LinkedGraph(from.SAS.Operators.Count + 1);
var inits = GetInitApplicableOperators(from);
// -1 is from the initial state
graphs.Add(-1, inits.ToList());
// 0 is from the initial state
graphs.LinkAll(0, inits);
foreach (var op in from.SAS.Operators)
{
var possibles = new List<int>();
Expand All @@ -62,24 +61,20 @@ private TranslatorContext GenerateApplicabilityGraph(TranslatorContext from, Dic
if (preGraph.TryGetValue(add.ID, out List<int>? value))
possibles.AddRange(value);
possibles.AddRange(inits);
possibles = possibles.Distinct().ToList();
graphs.Add(op.ID, possibles);
graphs.LinkAll(op.ID, possibles);
}

foreach (var key in graphs.Keys)
graphs[key].RemoveAll(x => x == key);

var total = graphs.Sum(x => x.Value.Count);
var total = graphs.Count;
var worst = from.SAS.Operators.Count * from.SAS.Operators.Count;
DoLog?.Invoke($"Applicability graph reduces operator checking to {Math.Round((double)total / worst * 100, 2)}% of max");

from = new TranslatorContext(from) { ApplicabilityGraph = graphs };
return from;
}

private HashSet<int> GetInitApplicableOperators(TranslatorContext context)
private List<int> GetInitApplicableOperators(TranslatorContext context)
{
var ops = new HashSet<int>();
var ops = new List<int>();
var initState = new SASStateSpace(context);

foreach (var op in context.SAS.Operators)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private void RecountFacts(SASDecl decl)
unique.Add(fact);
check.RemoveAll(x => x.ContentEquals(fact));
}
var uniqueDict = new Dictionary<string,Fact>();
var uniqueDict = new Dictionary<string, Fact>();
foreach (var fact in unique)
uniqueDict.Add(fact.ToString(), fact);
int count = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ public NormalizeOperatorIDsPhase(LogEventHandler? doLog)
public override TranslatorContext ExecutePhase(TranslatorContext from)
{
DoLog?.Invoke($"Normalizing remaining operator IDs...");
int count = 0;
int count = from.SAS.Operators.Count;
foreach (var op in from.SAS.Operators)
op.ID = count++;
op.ID = count--;
from.SAS = new SASDecl(from.SAS.Operators, from.SAS.Goal, from.SAS.Init, from.SAS.Facts);
return from;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
using FlashPlanner.Core.Models.SAS;
using FlashPlanner.Core.Translators.Helpers;
using FlashPlanner.Core.Translators.Normalizers;
using PDDLSharp.Models.PDDL;
using PDDLSharp.Models.PDDL.Domain;
using PDDLSharp.Models.PDDL.Expressions;
using PDDLSharp.Models.PDDL.Overloads;
using PDDLSharp.Toolkits;
using PDDLSharp.Translators.Grounders;
using System;

namespace FlashPlanner.Core.Translators.Phases
{
Expand Down Expand Up @@ -77,16 +75,16 @@ private List<Operator> GroundActions(List<ActionDecl> actions, TranslatorContext

DoLog?.Invoke($"Grounding action '{action.Name}'...");
var permutations = Grounder.GetPermutations(action);
foreach(var permutation in permutations)
foreach (var permutation in permutations)
{
var newOp = baseOp.Copy();
var map = new Dictionary<string, string>();
for(int i = 0; i < baseOp.Arguments.Length; i++)
for (int i = 0; i < baseOp.Arguments.Length; i++)
map.Add(baseOp.Arguments[i], Grounder.GetObjectFromIndex(permutation[i]));

for (int i = 0; i < newOp.Arguments.Length; i++)
newOp.Arguments[i] = map[newOp.Arguments[i]];
for(int i = 0; i < newOp.Pre.Length; i++)
for (int i = 0; i < newOp.Pre.Length; i++)
for (int j = 0; j < newOp.Pre[i].Arguments.Length; j++)
if (newOp.Pre[i].Arguments[j].StartsWith('?'))
newOp.Pre[i].Arguments[j] = map[newOp.Pre[i].Arguments[j]];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using FlashPlanner.Core.Models;
using FlashPlanner.Core.Models.SAS;
using FlashPlanner.Core.States;
using PDDLSharp.Models.PDDL;

namespace FlashPlanner.Core.Translators.Phases
{
Expand Down Expand Up @@ -29,7 +28,7 @@ private List<Operator> GetPotentiallyReachableOperators(SASDecl decl)
{
bool any = true;
bool[] covered = new bool[decl.Operators.Count];
var state = new RelaxedSASStateSpace(new TranslatorContext(){ SAS = decl, FactHashes = new int[decl.Facts] });
var state = new RelaxedSASStateSpace(new TranslatorContext() { SAS = decl, FactHashes = new int[decl.Facts] });
var applicables = new List<Operator>();
while (any)
{
Expand Down
1 change: 0 additions & 1 deletion FlashPlanner.Tests/Search/EnforcedHillClimbingSTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ public static IEnumerable<object[]> GetData() => GetTestingData(new List<string>
"tpp",
"satellite",
"driverlog",
"blocks",
"logistics00",
"logistics98",
"freecell",
Expand Down
2 changes: 1 addition & 1 deletion FlashPlanner/FlashPlanner.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

<PropertyGroup>
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
<Version>1.2.15</Version>
<Version>1.2.16</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions FlashPlanner/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"profiles": {
"FlashPlanner.CLI": {
"commandName": "Project",
"commandLineArgs": "--domain ../../../../Dependencies/FocusedMetaActionsData/Benchmarks/scanalyzer/domain.pddl --problem ../../../../Dependencies/FocusedMetaActionsData/Benchmarks/scanalyzer/testing/p08.pddl --search \"greedy(hFF())\" --validate\""
"commandLineArgs": "--domain ../../../../Dependencies/FocusedMetaActionsData/Benchmarks/gripper/domain.pddl --problem ../../../../Dependencies/FocusedMetaActionsData/Benchmarks/gripper/testing/p30.pddl --search \"greedy_lazy(hFF())\" --validate\""
}
}
}
}

0 comments on commit 9ab6020

Please sign in to comment.