-
Notifications
You must be signed in to change notification settings - Fork 16
/
CbsConstraint.cs
150 lines (128 loc) · 5.33 KB
/
CbsConstraint.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
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace mapf;
public class CbsConstraint : IComparable
{
public byte agentNum {get; protected set;}
public TimedMove move {get; protected set;}
public bool queryInstance = false;
public CbsConstraint(int agentNum, int posX, int posY, Move.Direction direction, int timeStep)
{
this.Init(agentNum, posX, posY, direction, timeStep);
}
public CbsConstraint(int agentNum, TimedMove move)
{
this.Init(agentNum, move);
}
public CbsConstraint() : this(-1, -1, -1, Move.Direction.NO_DIRECTION, -1) {} // Nonsense values until Init, just allocate move
public CbsConstraint(CbsConflict conflict, ProblemInstance instance, bool agentA)
{
Move move;
int agentNum;
if (agentA)
{
move = conflict.agentAmove;
agentNum = instance.agents[conflict.agentAIndex].agent.agentNum;
}
else
{
move = conflict.agentBmove;
agentNum = instance.agents[conflict.agentBIndex].agent.agentNum;
}
this.agentNum = (byte)agentNum;
this.move = new TimedMove(move, conflict.timeStep);
if (conflict.isVertexConflict)
this.move.direction = Move.Direction.NO_DIRECTION;
}
public void Init(int agentNum, int posX, int posY, Move.Direction direction, int timeStep)
{
this.Init(agentNum, new TimedMove(posX, posY, direction, timeStep));
}
public void Init(int agentNum, TimedMove move)
{
this.agentNum = (byte)agentNum;
this.move = move;
}
public int time
{
get
{
return this.move.time;
}
}
/// <summary>
/// Checks that the agentNum is equal, and compares the move.
/// If one of the constraints is a query, an instance only created and used to quickly search for a move in a set of constraints,
/// the direction is ignored if the other constraint is a vertex constraint.
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(object obj)
{
if (obj == null)
return false;
CbsConstraint other = (CbsConstraint)obj;
if (this.agentNum != other.agentNum)
return false;
Trace.Assert(this.queryInstance == false || other.queryInstance == false); // At most one of the instances is a query
Trace.Assert(this.queryInstance == false || this.move.direction != Move.Direction.NO_DIRECTION); // Must query regarding a specific direction
Trace.Assert(other.queryInstance == false || other.move.direction != Move.Direction.NO_DIRECTION); // Must query regarding a specific direction
if (this.queryInstance || other.queryInstance) // This way if the constraint is a vertex constraint than it will be equal to a query containing a move from any direction to that position,
// and if it is an edge constraint than it will only be equal to queries containing a move from that specific direction to that position.
return this.move.Equals(other.move);
else // A vertex constraint is different to an edge constraint for the same agentNum and position.
// Must check the direction explicitly because vertex constraints have no direction and moves with no direction
// compare equal to moves with any direction
// TODO: Get rid of all of this using Nathan's advice.
return this.move.Equals(other.move) && this.move.direction == other.move.direction;
}
/// <summary>
/// Uses the move and the agents.
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
unchecked
{
int ans = 0;
ans += this.move.GetHashCode() * 3;
ans += this.agentNum * 5;
return ans;
}
}
public int GetTimeStep() { return this.move.time; } // FIXME: Make this into a property
public Move.Direction GetDirection()
{
return this.move.direction;
}
public override string ToString()
{
return $"{move}-{move.direction,-12} time={move.time} agentNum {agentNum}";
}
/// <summary>
/// Kind of the opposite of Equals: checks that the moves are unequal or that not one of the other's agents appears in this.agents.
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
public bool Allows(CbsConstraint other)
{
if (this.move.Equals(other.move) == false) // Minor behavior change: if exactly one move has a set direction, and they're otherwise equal the method used to return true.
return true;
if (this.agentNum == other.agentNum)
return false;
return true;
}
public int CompareTo(object item)
{
CbsConstraint other = (CbsConstraint)item;
return this.move.time.CompareTo(other.move.time);
}
public bool ViolatesMustConstraint(byte agent, TimedMove move)
{
if (this.agentNum != agent)
return false;
return this.move.Equals(move) == false;
}
}