Source code for pacman.operations.placer_algorithms.connective_based_placer
import logging
from pacman.utilities.algorithm_utilities.placer_algorithm_utilities \
import sort_vertices_by_known_constraints
from pacman.model.constraints.placer_constraints \
import AbstractPlacerConstraint
from pacman.model.placements import Placements
from pacman.operations.placer_algorithms import RadialPlacer
from pacman.utilities import utility_calls
from spinn_utilities.progress_bar import ProgressBar
from pacman.utilities.utility_objs import ResourceTracker
logger = logging.getLogger(__name__)
[docs]class ConnectiveBasedPlacer(RadialPlacer):
""" A radial algorithm that can place a machine graph onto a\
machine using a circle out behaviour from a Ethernet at a given point\
and which will place things that are most connected closest to each\
other
"""
__slots__ = []
def __init__(self):
"""
"""
RadialPlacer.__init__(self)
def __call__(self, machine_graph, machine):
# check that the algorithm can handle the constraints
self._check_constraints(machine_graph.vertices)
# Sort the vertices into those with and those without
# placement constraints
placements = Placements()
constrained_vertices = list()
unconstrained_vertices = set()
for vertex in machine_graph.vertices:
placement_constraints = utility_calls.locate_constraints_of_type(
vertex.constraints, AbstractPlacerConstraint)
if len(placement_constraints) > 0:
constrained_vertices.append(vertex)
else:
unconstrained_vertices.add(vertex)
# Iterate over constrained vertices and generate placements
progress = ProgressBar(
machine_graph.n_vertices, "Placing graph vertices")
resource_tracker = ResourceTracker(
machine, self._generate_radial_chips(machine))
constrained_vertices = sort_vertices_by_known_constraints(
constrained_vertices)
for vertex in constrained_vertices:
self._place_vertex(vertex, resource_tracker, machine, placements)
progress.update()
while len(unconstrained_vertices) > 0:
# Keep track of all vertices connected to the currently placed ones
next_vertices = set()
# Initially, add the overall most connected vertex
max_connected_vertex = self._find_max_connected_vertex(
unconstrained_vertices, machine_graph)
next_vertices.add(max_connected_vertex)
while len(next_vertices) > 0:
# Find the vertex most connected to the currently placed
# vertices
vertex = self._find_max_connected_vertex(next_vertices,
machine_graph)
# Place the vertex
self._place_vertex(vertex, resource_tracker, machine,
placements)
progress.update()
unconstrained_vertices.remove(vertex)
next_vertices.remove(vertex)
# Add all vertices connected to this one to the set
for in_edge in (machine_graph
.get_edges_ending_at_vertex(vertex)):
if in_edge.pre_vertex in unconstrained_vertices:
next_vertices.add(in_edge.pre_vertex)
for out_edge in (machine_graph
.get_edges_starting_at_vertex(vertex)):
if out_edge.post_vertex in unconstrained_vertices:
next_vertices.add(out_edge.post_vertex)
# finished, so stop progress bar and return placements
progress.end()
return placements
def _find_max_connected_vertex(self, vertices, graph):
max_connected_vertex = None
max_weight = 0
for vertex in vertices:
in_weight = sum([
edge.weight
for edge in graph.get_edges_starting_at_vertex(vertex)])
out_weight = sum([
edge.weight
for edge in graph.get_edges_ending_at_vertex(vertex)])
weight = in_weight + out_weight
if max_connected_vertex is None or weight > max_weight:
max_connected_vertex = vertex
max_weight = weight
return max_connected_vertex