a_star :: Node :: defaultinit
a_star :: Node :: find_closest
Find the closest node accepted bycond
under max_cost
a_star :: Node :: path_to_alts
Find a path to a possibledestination
or a node accepted by alt_targets
a_star $ Node :: core_serialize_to
We customize the serialization process to avoid problems with recursivea_star $ Node :: from_deserializer
Create an instance of this class from thedeserializer
serialization :: Serializable :: accept_json_serializer
Refinable service to customize the serialization of this class to JSONserialization :: Serializable :: accept_msgpack_attribute_counter
Hook to customize the behavior of theAttributeCounter
serialization :: Serializable :: accept_msgpack_serializer
Hook to customize the serialization of this class to MessagePackserialization :: Serializable :: add_to_bundle
Called by[]=
to dynamically choose the appropriate method according
core :: Object :: class_factory
Implementation used byget_class
to create the specific class.
serialization :: Serializable :: core_serialize_to
Actual serialization ofself
to serializer
core :: Object :: defaultinit
a_star :: Node :: defaultinit
a_star :: Node :: find_closest
Find the closest node accepted bycond
under max_cost
serialization :: Serializable :: from_deserializer
Create an instance of this class from thedeserializer
core :: Object :: is_same_instance
Return true ifself
and other
are the same instance (i.e. same identity).
core :: Object :: is_same_serialized
Isself
the same as other
in a serialization context?
core :: Object :: is_same_type
Return true ifself
and other
have the same dynamic type.
serialization :: Serializable :: msgpack_extra_array_items
Hook to request a larger than usual metadata arraycore :: Object :: output_class_name
Display class name on stdout (debug only).a_star :: Node :: path_to_alts
Find a path to a possibledestination
or a node accepted by alt_targets
serialization :: Serializable :: serialize_msgpack
Serializeself
to MessagePack bytes
serialization :: Serializable :: serialize_to
Serializeself
to serializer
serialization :: Serializable :: serialize_to_json
Serializeself
to JSON
serialization :: Serializable :: to_pretty_json
Serializeself
to plain pretty JSON
Serializer::serialize
# General graph node
class Node
super Serializable
# Type of the others nodes in the `graph`
type N: Node
# parent graph
var graph: Graph[N, Link]
init
do
graph.add_node(self)
end
# adjacent nodes
var links: Set[Link] = new HashSet[Link]
# used to check if node has been searched in one pathfinding
private var last_pathfinding_evocation: Int = 0
# cost up to in current evocation
# lifetime limited to evocation of `path_to`
private var best_cost_up_to: Int = 0
# source node
# lifetime limited to evocation of `path_to`
private var best_source: nullable N = null
# is in frontier or buckets
# lifetime limited to evocation of `path_to`
private var open: Bool = false
# 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
# Find a path to a possible `destination` or a node accepted by `alt_targets`
fun path_to_alts(destination: nullable N, max_cost: Int, context: PathContext,
alt_targets: nullable TargetCondition[N]): nullable AStarPath[N]
do
var cost = 0
var nbr_buckets = context.worst_cost + context.worst_heuristic_cost + 1
var buckets = new Array[List[N]].with_capacity(nbr_buckets)
for i in [0 .. nbr_buckets[ do
buckets.add(new List[N])
end
graph.pathfinding_current_evocation += 1
# open source node
buckets[0].add(self)
open = true
self.last_pathfinding_evocation = graph.pathfinding_current_evocation
self.best_cost_up_to = 0
loop
var frontier_node: nullable N = null
var bucket_searched = 0
# find next valid node in frontier/buckets
loop
var current_bucket = buckets[cost % nbr_buckets]
if current_bucket.is_empty then # move to next bucket
cost += 1
if cost > max_cost then return null
bucket_searched += 1
if bucket_searched > nbr_buckets then break
else # found a node
frontier_node = current_bucket.pop
if frontier_node.open then break
end
end
# no path possible
if frontier_node == null then
return null
# at destination
else if frontier_node == destination or
(alt_targets != null and alt_targets.accept(frontier_node)) then
var path = new AStarPath[N](cost)
while frontier_node != self do
path.nodes.unshift(frontier_node)
frontier_node = frontier_node.best_source
assert frontier_node != null
end
return path
# adds all next nodes to frontier/buckets
else
frontier_node.open = false
for link in frontier_node.links do
var peek_node = link.to
if not context.is_blocked(link) and
(peek_node.last_pathfinding_evocation != graph.pathfinding_current_evocation or
(peek_node.open and
peek_node.best_cost_up_to > cost + context.cost(link)))
then
peek_node.open = true
peek_node.last_pathfinding_evocation = graph.pathfinding_current_evocation
peek_node.best_cost_up_to = cost + context.cost(link)
peek_node.best_source = frontier_node
var est_cost
if destination != null then
est_cost = peek_node.best_cost_up_to + context.heuristic_cost(peek_node, destination)
else if alt_targets != null then
est_cost = peek_node.best_cost_up_to + alt_targets.heuristic_cost(peek_node, link)
else est_cost = 0
var at_bucket = buckets[est_cost % nbr_buckets]
at_bucket.add(peek_node)
end
end
end
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)
do
serializer.serialize_attribute("graph", graph)
end
redef init from_deserializer(deserializer)
do
deserializer.notify_of_creation self
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
lib/a_star/a_star.nit:60,1--218,3