mirror of
https://github.com/lscharen/iigs-sprite-compiler.git
synced 2024-12-21 16:30:15 +00:00
Add Iterative Deepening search infrastructure
This commit is contained in:
parent
780f94050e
commit
2d25c5c295
@ -25,7 +25,7 @@
|
|||||||
this.expander = expander;
|
this.expander = expander;
|
||||||
}
|
}
|
||||||
|
|
||||||
public INodeExpander<A, S, T, C> Expander { get { return expander; } }
|
public INodeExpander<A, S, T, C> Expander { get { return expander; } set { expander = value; } }
|
||||||
|
|
||||||
public IEnumerable<T> Solution(T node)
|
public IEnumerable<T> Solution(T node)
|
||||||
{
|
{
|
||||||
|
24
SpriteCompiler/AI/CostNodeLimiter.cs
Normal file
24
SpriteCompiler/AI/CostNodeLimiter.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
namespace SpriteCompiler.AI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Class that taken a search node and detemines whether or not to terminate the
|
||||||
|
/// search at the node. This is different than a goal test and is used in the
|
||||||
|
/// contect of depth-limited searches.
|
||||||
|
/// </summary>
|
||||||
|
public class CostNodeLimiter<T, C> : INodeLimiter<T, C>
|
||||||
|
where T : ISearchNode<C>
|
||||||
|
where C : IPathCost<C>, new()
|
||||||
|
{
|
||||||
|
private readonly C maxCost;
|
||||||
|
|
||||||
|
public CostNodeLimiter(C maxCost)
|
||||||
|
{
|
||||||
|
this.maxCost = maxCost;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Cutoff(T node)
|
||||||
|
{
|
||||||
|
return node.PathCost.CompareTo(maxCost) >= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
SpriteCompiler/AI/DepthFirstSearch.cs
Normal file
32
SpriteCompiler/AI/DepthFirstSearch.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace SpriteCompiler.AI
|
||||||
|
{
|
||||||
|
public class DepthFirstSearch<A, S, T, C> : ISearch<A, S, T, C>
|
||||||
|
where T : ISearchNode<A, S, T, C>
|
||||||
|
where C : IPathCost<C>, new()
|
||||||
|
{
|
||||||
|
protected readonly AbstractAISearch<A, S, T, C> search;
|
||||||
|
protected readonly IQueue<T> fringe = new Lifo<T>();
|
||||||
|
|
||||||
|
public DepthFirstSearch(AbstractAISearch<A, S, T, C> search)
|
||||||
|
{
|
||||||
|
this.search = search;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IEnumerable<T> Search(ISearchProblem<A, S, C> problem, S initialState)
|
||||||
|
{
|
||||||
|
fringe.Clear();
|
||||||
|
return search.Search(problem, fringe, initialState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IEnumerable<T> ExtendSearch(ISearchProblem<A, S, C> problem)
|
||||||
|
{
|
||||||
|
return search.ExtendSearch(problem, fringe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
SpriteCompiler/AI/DepthLimitedNodeExpander.cs
Normal file
35
SpriteCompiler/AI/DepthLimitedNodeExpander.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace SpriteCompiler.AI
|
||||||
|
{
|
||||||
|
public class DepthLimitedNodeExpander<A, S, T, C> : NodeExpanderDelegator<A, S, T, C>
|
||||||
|
where T : ISearchNode<A, S, T, C>
|
||||||
|
where C : IPathCost<C>, new()
|
||||||
|
{
|
||||||
|
private readonly INodeLimiter<T, C> limit;
|
||||||
|
private bool cutoffOccured = false;
|
||||||
|
|
||||||
|
public DepthLimitedNodeExpander(INodeExpander<A, S, T, C> expander, INodeLimiter<T, C> limit)
|
||||||
|
: base(expander)
|
||||||
|
{
|
||||||
|
this.limit = limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CutoffOccured { get { return cutoffOccured; } }
|
||||||
|
|
||||||
|
public override IEnumerable<T> Expand(ISearchProblem<A, S, C> problem, T node)
|
||||||
|
{
|
||||||
|
if (limit.Cutoff(node))
|
||||||
|
{
|
||||||
|
cutoffOccured = true;
|
||||||
|
return Enumerable.Empty<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.Expand(problem, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
SpriteCompiler/AI/DepthLimitedSearch.cs
Normal file
60
SpriteCompiler/AI/DepthLimitedSearch.cs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace SpriteCompiler.AI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Depth-first search with a cutoff
|
||||||
|
/// </summary>
|
||||||
|
public class DepthLimitedSearch<A, S, T, C> : DepthFirstSearch<A, S, T, C>
|
||||||
|
where T : ISearchNode<A, S, T, C>
|
||||||
|
where C : IPathCost<C>, new()
|
||||||
|
{
|
||||||
|
protected readonly INodeLimiter<T, C> limit;
|
||||||
|
|
||||||
|
public DepthLimitedSearch(AbstractAISearch<A, S, T, C> search, INodeLimiter<T, C> limit)
|
||||||
|
: base(search)
|
||||||
|
{
|
||||||
|
this.limit = limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<T> Search(ISearchProblem<A, S, C> problem, S initialState)
|
||||||
|
{
|
||||||
|
// Save the old node expander
|
||||||
|
var oldExpander = search.Expander;
|
||||||
|
|
||||||
|
// Wrap the expander with a depth-limied expanded in order to
|
||||||
|
// terminate the search
|
||||||
|
var expander = new DepthLimitedNodeExpander<A, S, T, C>(oldExpander, limit);
|
||||||
|
search.Expander = expander;
|
||||||
|
|
||||||
|
// Run the search
|
||||||
|
var solution = base.Search(problem, initialState);
|
||||||
|
|
||||||
|
// Restore the old expander
|
||||||
|
search.Expander = oldExpander;
|
||||||
|
|
||||||
|
// Check to see we failed and if the reason for failing was not reaching the cutoff depth.
|
||||||
|
if (search.IsFailure(solution) && expander.CutoffOccured)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return solution;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<T> ExtendSearch(ISearchProblem<A, S, C> problem)
|
||||||
|
{
|
||||||
|
return base.ExtendSearch(problem);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsCutoff(IEnumerable<T> result)
|
||||||
|
{
|
||||||
|
return result == null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
SpriteCompiler/AI/INodeLimiter.cs
Normal file
9
SpriteCompiler/AI/INodeLimiter.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace SpriteCompiler.AI
|
||||||
|
{
|
||||||
|
public interface INodeLimiter<T, C>
|
||||||
|
where T : ISearchNode<C>
|
||||||
|
where C : IPathCost<C>, new()
|
||||||
|
{
|
||||||
|
bool Cutoff(T node);
|
||||||
|
}
|
||||||
|
}
|
@ -12,15 +12,15 @@
|
|||||||
public interface ISearchNode<A, S, T, C> : ISearchNode<C> where C : IPathCost<C>
|
public interface ISearchNode<A, S, T, C> : ISearchNode<C> where C : IPathCost<C>
|
||||||
{
|
{
|
||||||
A Action { get; set; }
|
A Action { get; set; }
|
||||||
C PathCost { get; }
|
|
||||||
C StepCost { get; set; }
|
|
||||||
int Depth { get; }
|
|
||||||
S State { get; }
|
S State { get; }
|
||||||
T Parent { get; }
|
T Parent { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ISearchNode<C>
|
public interface ISearchNode<C>
|
||||||
{
|
{
|
||||||
|
C PathCost { get; }
|
||||||
|
C StepCost { get; set; }
|
||||||
|
int Depth { get; }
|
||||||
C EstCost { get; }
|
C EstCost { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
45
SpriteCompiler/AI/IterativeDeepeningAStarSearch.cs
Normal file
45
SpriteCompiler/AI/IterativeDeepeningAStarSearch.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace SpriteCompiler.AI
|
||||||
|
{
|
||||||
|
public class IterativeDeepeningAStarSearch<A, S, T, C> : ISearch<A, S, T, C>
|
||||||
|
where T : ISearchNode<A, S, T, C>
|
||||||
|
where C : IPathCost<C>, new()
|
||||||
|
{
|
||||||
|
protected readonly AbstractAISearch<A, S, T, C> search;
|
||||||
|
protected readonly C limit;
|
||||||
|
|
||||||
|
public IterativeDeepeningAStarSearch(AbstractAISearch<A, S, T, C> search, C limit)
|
||||||
|
{
|
||||||
|
this.search = search;
|
||||||
|
this.limit = limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<T> Search(ISearchProblem<A, S, C> problem, S initialState)
|
||||||
|
{
|
||||||
|
C bound = new C();
|
||||||
|
while (bound.CompareTo(limit) < 0)
|
||||||
|
{
|
||||||
|
var dls = new DepthLimitedSearch<A, S, T, C>(search, new CostNodeLimiter<T, C>(bound));
|
||||||
|
var result = dls.Search(problem, initialState);
|
||||||
|
|
||||||
|
if (!dls.IsCutoff(result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// An empty list signals failure
|
||||||
|
return Enumerable.Empty<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<T> ExtendSearch(ISearchProblem<A, S, C> problem)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
41
SpriteCompiler/AI/Lifo.cs
Normal file
41
SpriteCompiler/AI/Lifo.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace SpriteCompiler.AI
|
||||||
|
{
|
||||||
|
public class Lifo<T> : IQueue<T>
|
||||||
|
{
|
||||||
|
private readonly Stack<T> stack = new Stack<T>();
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
stack.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Empty
|
||||||
|
{
|
||||||
|
get { return stack.Count == 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Remove()
|
||||||
|
{
|
||||||
|
return stack.Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Enqueue(T item)
|
||||||
|
{
|
||||||
|
stack.Push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRange(IEnumerable<T> items)
|
||||||
|
{
|
||||||
|
foreach (var item in items)
|
||||||
|
{
|
||||||
|
stack.Push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
SpriteCompiler/AI/NodeExpanderDelegator.cs
Normal file
26
SpriteCompiler/AI/NodeExpanderDelegator.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
namespace SpriteCompiler.AI
|
||||||
|
{
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class NodeExpanderDelegator<A, S, T, C> : INodeExpander<A, S, T, C>
|
||||||
|
where T : ISearchNode<A, S, T, C>
|
||||||
|
where C : IPathCost<C>
|
||||||
|
{
|
||||||
|
private readonly INodeExpander<A, S, T, C> expander;
|
||||||
|
|
||||||
|
public NodeExpanderDelegator(INodeExpander<A, S, T, C> expander)
|
||||||
|
{
|
||||||
|
this.expander = expander;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IEnumerable<T> Expand(ISearchProblem<A, S, C> problem, T node)
|
||||||
|
{
|
||||||
|
return expander.Expand(problem, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual T CreateNode(T parent, S state)
|
||||||
|
{
|
||||||
|
return expander.CreateNode(parent, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -58,9 +58,14 @@
|
|||||||
<Compile Include="AI\AStarComparer.cs" />
|
<Compile Include="AI\AStarComparer.cs" />
|
||||||
<Compile Include="AI\AStarSearch.cs" />
|
<Compile Include="AI\AStarSearch.cs" />
|
||||||
<Compile Include="AI\BestFirstSearch.cs" />
|
<Compile Include="AI\BestFirstSearch.cs" />
|
||||||
|
<Compile Include="AI\CostNodeLimiter.cs" />
|
||||||
|
<Compile Include="AI\DepthFirstSearch.cs" />
|
||||||
|
<Compile Include="AI\DepthLimitedNodeExpander.cs" />
|
||||||
|
<Compile Include="AI\DepthLimitedSearch.cs" />
|
||||||
<Compile Include="AI\HeuristicSearchNode.cs" />
|
<Compile Include="AI\HeuristicSearchNode.cs" />
|
||||||
<Compile Include="AI\IHeuristicFunction.cs" />
|
<Compile Include="AI\IHeuristicFunction.cs" />
|
||||||
<Compile Include="AI\InformedNodeExpander.cs" />
|
<Compile Include="AI\InformedNodeExpander.cs" />
|
||||||
|
<Compile Include="AI\INodeLimiter.cs" />
|
||||||
<Compile Include="AI\ISuccessorFunction.cs" />
|
<Compile Include="AI\ISuccessorFunction.cs" />
|
||||||
<Compile Include="AI\IGoalTest.cs" />
|
<Compile Include="AI\IGoalTest.cs" />
|
||||||
<Compile Include="AI\INodeExpander.cs" />
|
<Compile Include="AI\INodeExpander.cs" />
|
||||||
@ -70,6 +75,9 @@
|
|||||||
<Compile Include="AI\ISearchNode.cs" />
|
<Compile Include="AI\ISearchNode.cs" />
|
||||||
<Compile Include="AI\ISearchProblem.cs" />
|
<Compile Include="AI\ISearchProblem.cs" />
|
||||||
<Compile Include="AI\IStepCostFunction.cs" />
|
<Compile Include="AI\IStepCostFunction.cs" />
|
||||||
|
<Compile Include="AI\IterativeDeepeningAStarSearch.cs" />
|
||||||
|
<Compile Include="AI\Lifo.cs" />
|
||||||
|
<Compile Include="AI\NodeExpanderDelegator.cs" />
|
||||||
<Compile Include="AI\SearchProblem.cs" />
|
<Compile Include="AI\SearchProblem.cs" />
|
||||||
<Compile Include="AI\GraphSearch.cs" />
|
<Compile Include="AI\GraphSearch.cs" />
|
||||||
<Compile Include="AI\TreeSearch.cs" />
|
<Compile Include="AI\TreeSearch.cs" />
|
||||||
|
Loading…
Reference in New Issue
Block a user