mirror of
https://github.com/lscharen/iigs-sprite-compiler.git
synced 2024-08-31 18:29:06 +00:00
Add Iterative Deepening search infrastructure
This commit is contained in:
parent
780f94050e
commit
2d25c5c295
@ -25,7 +25,7 @@
|
||||
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)
|
||||
{
|
||||
|
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>
|
||||
{
|
||||
A Action { get; set; }
|
||||
C PathCost { get; }
|
||||
C StepCost { get; set; }
|
||||
int Depth { get; }
|
||||
S State { get; }
|
||||
T Parent { get; }
|
||||
}
|
||||
|
||||
public interface ISearchNode<C>
|
||||
{
|
||||
C PathCost { get; }
|
||||
C StepCost { get; set; }
|
||||
int Depth { 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\AStarSearch.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\IHeuristicFunction.cs" />
|
||||
<Compile Include="AI\InformedNodeExpander.cs" />
|
||||
<Compile Include="AI\INodeLimiter.cs" />
|
||||
<Compile Include="AI\ISuccessorFunction.cs" />
|
||||
<Compile Include="AI\IGoalTest.cs" />
|
||||
<Compile Include="AI\INodeExpander.cs" />
|
||||
@ -70,6 +75,9 @@
|
||||
<Compile Include="AI\ISearchNode.cs" />
|
||||
<Compile Include="AI\ISearchProblem.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\GraphSearch.cs" />
|
||||
<Compile Include="AI\TreeSearch.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user