-
Notifications
You must be signed in to change notification settings - Fork 3
/
A_Star_WithOD.cs
159 lines (128 loc) · 6.23 KB
/
A_Star_WithOD.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
using System;
using System.Collections.Generic;
using System.IO;
namespace mapf
{
/// <summary>
/// A* implementation with Standley's operator decomposition (OD).
/// See AAAI 2010 paper by Trevor Standley on Cooperative Pathfinding.
/// </summary>
public class A_Star_WithOD : A_Star
{
protected int expandedFullStates;
protected int accExpandedFullStates;
protected int generatedFullStates;
protected int accGeneratedFullStates;
public A_Star_WithOD(IHeuristicCalculator<WorldState> heuristic = null, bool mStar = false, bool mStarShuffle = false)
: base(heuristic, mStar, mStarShuffle) { }
override protected WorldState CreateSearchRoot(int minDepth = -1, int minCost = -1, MDDNode mddNode = null)
{
return new WorldStateWithOD(this.instance.agents, minDepth, minCost, mddNode);
}
protected override WorldState CreateSearchNode(WorldState from)
{
return new WorldStateWithOD((WorldStateWithOD)from);
}
public override string GetName() { return base.GetName() + "+OD"; }
public override void Setup(ProblemInstance problemInstance, int minDepth, Run runner,
ConflictAvoidanceTable CAT = null,
ISet<CbsConstraint> constraints = null, ISet<CbsConstraint> positiveConstraints = null,
int minCost = -1, int maxCost = int.MaxValue, MDD mdd = null)
{
base.Setup(problemInstance, minDepth, runner, CAT, constraints, positiveConstraints,
minCost, maxCost, mdd);
this.expandedFullStates = 0;
this.generatedFullStates = 0;
}
protected bool alreadyExpanded;
// Problem 59 of 3 agents and 9 obstacles is a good example of why
// equivalence over different times is difficult to get right
// with A*+OD (but possible).
/// <summary>
/// Expand a given node. This includes:
/// - Generating all possible children
/// - Inserting them to OPEN
/// - Insert the generated nodes to the hashtable of nodes, currently implmented together with the closed list.
/// </summary>
public override void Expand(WorldState node)
{
if (((WorldStateWithOD)node).agentTurn == 0)
expandedFullStates++;
this.alreadyExpanded = false;
base.Expand(node);
}
protected override List<WorldState> ExpandOneAgent(List<WorldState> intermediateNodes, int agentIndex)
{
if (this.alreadyExpanded == true) // Necessary because after expansion, the generated nodes have an incremented agentTurn that once again equals agentIndex
// and because it's possible that a node may have valid children that aren't already in the closed list
return intermediateNodes; // Do nothing to this agent
WorldStateWithOD parent = (WorldStateWithOD)intermediateNodes[0];
if (agentIndex < parent.agentTurn)
return intermediateNodes; // Do nothing to this agent
var generated = base.ExpandOneAgent(intermediateNodes, agentIndex);
int childAgentTurn = ((parent.agentTurn + 1) % (this.instance.agents.Length));
foreach (var node in generated)
{
WorldStateWithOD childNode = (WorldStateWithOD)node;
childNode.agentTurn = childAgentTurn;
// Makespan increases only if this is the move of the first agent. This makes sure that under a makespan
// cost function, partial nodes have a correct cost and can even serve as goal nodes.
if (parent.agentTurn != 0)
childNode.makespan--; // Cancel the increment in base
}
this.alreadyExpanded = true;
return generated;
}
protected override bool ProcessGeneratedNode(WorldState currentNode)
{
bool ret = base.ProcessGeneratedNode(currentNode);
var node = (WorldStateWithOD)currentNode;
if (node.agentTurn == 0)
this.generatedFullStates++;
return ret;
}
public override void OutputStatisticsHeader(TextWriter output)
{
base.OutputStatisticsHeader(output);
output.Write(this.ToString() + " Expanded Full States");
output.Write(Run.RESULTS_DELIMITER);
output.Write(this.ToString() + " Generated Full States");
output.Write(Run.RESULTS_DELIMITER);
}
public override void OutputStatistics(TextWriter output)
{
base.OutputStatistics(output);
Console.WriteLine("Total Expanded Full States: {0}", this.expandedFullStates);
Console.WriteLine("Total Generated Full States: {0}", this.generatedFullStates);
output.Write(this.expandedFullStates + Run.RESULTS_DELIMITER);
output.Write(this.generatedFullStates + Run.RESULTS_DELIMITER);
}
public override int NumStatsColumns
{
get
{
return 2 + base.NumStatsColumns;
}
}
public override void ClearAccumulatedStatistics()
{
base.ClearAccumulatedStatistics();
this.accExpandedFullStates = 0;
this.accGeneratedFullStates = 0;
}
public override void AccumulateStatistics()
{
base.AccumulateStatistics();
this.accExpandedFullStates += this.expandedFullStates;
this.accGeneratedFullStates += this.generatedFullStates;
}
public override void OutputAccumulatedStatistics(TextWriter output)
{
base.OutputAccumulatedStatistics(output);
Console.WriteLine("{0} Average Expanded Full States (Low-Level): {1}", this, this.accExpandedFullStates);
Console.WriteLine("{0} Average Generated Full States (Low-Level): {1}", this, this.accGeneratedFullStates);
output.Write(this.accExpandedFullStates + Run.RESULTS_DELIMITER);
output.Write(this.accGeneratedFullStates + Run.RESULTS_DELIMITER);
}
}
}