# See the License for the specific language governing permissions and
# limitations under the License.
-# Services related to pathfinding of graphs using A*
-# A single graph may have different properties according to the `PathContext` used
+# A* pathfinding in graphs
#
+# A single graph may have different properties according to the `PathContext` used
#
# Usage:
#
# lifetime limited to evocation of `path_to`
private var open: Bool = false
- # Main functionnality, returns path from `self` to `dest`
+ # Main functionality, returns path from `self` to `dest`
fun path_to(dest: N, max_cost: Int, context: PathContext): nullable AStarPath[N]
do
return path_to_alts(dest, max_cost, context, null)
end
end
+ # Find the closest node accepted by `cond` under `max_cost`
+ fun find_closest(max_cost: Int, context: PathContext, cond: nullable TargetCondition[N]): nullable N
+ do
+ var path = path_to_alts(null, max_cost, context, cond)
+ if path == null then return null
+ return path.nodes.last
+ end
+
# We customize the serialization process to avoid problems with recursive
# serialization engines. These engines, such as `JsonSerializer`,
# are at danger to serialize the graph as a very deep tree.
# With a large graph it can cause a stack overflow.
#
# Instead, we serialize the nodes first and then the links.
- redef fun core_serialize_to(serializer: Serializer)
+ redef fun core_serialize_to(serializer)
do
serializer.serialize_attribute("graph", graph)
end
do
deserializer.notify_of_creation self
- var graph = deserializer.deserialize_attribute("graph")
- assert graph isa Graph[N, Link]
+ var graph = deserializer.deserialize_attribute("graph", (new GetName[Graph[N, Link]]).to_s)
+ if not graph isa Graph[N, Link] then graph = new Graph[N, Link]
self.graph = graph
end
end
# Link between two nodes and associated to a graph
class Link
- auto_serializable
+ serialize
# Type of the nodes in `graph`
type N: Node
super Serializable
# Nodes in this graph
- var nodes: Set[N] = new HashSet[N]
+ var nodes = new Set[N]
# Links in this graph
- var links: Set[L] = new HashSet[L]
+ var links = new Set[L]
# Add a `node` to this graph
fun add_node(node: N): N
# Used to check if nodes have been searched in one pathfinding
private var pathfinding_current_evocation: Int = 0
- redef fun core_serialize_to(serializer: Serializer)
+ redef fun core_serialize_to(serializer)
do
serializer.serialize_attribute("nodes", nodes)
serializer.serialize_attribute("links", links)
do
deserializer.notify_of_creation self
- var nodes = deserializer.deserialize_attribute("nodes")
- assert nodes isa HashSet[N]
- self.nodes = nodes
+ var nodes = deserializer.deserialize_attribute("nodes", (new GetName[Set[N]]).to_s)
+ if deserializer.deserialize_attribute_missing then
+ deserializer.errors.add new AttributeMissingError(self, "nodes")
+ end
+ if nodes isa Set[N] then self.nodes = nodes
- var links = deserializer.deserialize_attribute("links")
- assert links isa HashSet[L]
- for link in links do add_link link
+ var links = deserializer.deserialize_attribute("links", (new GetName[Set[L]]).to_s)
+ if deserializer.deserialize_attribute_missing then
+ deserializer.errors.add new AttributeMissingError(self, "links")
+ end
+ if links isa Set[L] then for link in links do add_link link
end
end
# Result from path finding and a walkable path
class AStarPath[N]
- auto_serializable
+ serialize
# Total cost of this path
var total_cost: Int
end
# Context related to an evocation of pathfinding
-class PathContext
- auto_serializable
+abstract class PathContext
+ serialize
# Type of the nodes in `graph`
type N: Node
# Warning: A* is not optimize for such a case
class ConstantPathContext
super PathContext
- auto_serializable
+ serialize
redef fun worst_cost do return 1
redef fun cost(l) do return 1
# A `PathContext` for graphs with `WeightedLink`
class WeightedPathContext
super PathContext
- auto_serializable
+ serialize
redef type L: WeightedLink
self.worst_cost = worst_cost
end
- redef var worst_cost: Int is noinit
+ redef var worst_cost is noinit
redef fun cost(l) do
return l.weight
# A `Link` with a `weight`
class WeightedLink
super Link
- auto_serializable
+ serialize
# The `weight`, or cost, of this link
var weight: Int
end
# Advanced path conditions with customizable accept states
-class TargetCondition[N: Node]
- auto_serializable
+abstract class TargetCondition[N: Node]
+ serialize
# Should the pathfinding accept `node` as a goal?
fun accept(node: N): Bool is abstract