Source code for pacman.utilities.algorithm_utilities.partition_algorithm_utilities
# Copyright (c) 2017-2019 The University of Manchester
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
""" A collection of methods which support partitioning algorithms.
"""
from collections import OrderedDict
from spinn_utilities.ordered_set import OrderedSet
from pacman.utilities import utility_calls as utils
from pacman.exceptions import PacmanPartitionException
from pacman.model.constraints.partitioner_constraints import (
AbstractPartitionerConstraint, SameAtomsAsVertexConstraint,
MaxVertexAtomsConstraint, FixedVertexAtomsConstraint)
VERTICES_NEED_TO_BE_SAME_SIZE_ERROR = (
"Vertices {} ({} atoms) and {} ({} atoms) must be of the same size to"
" partition them together")
CONTRADICTORY_FIXED_ATOM_ERROR = (
"Vertex has multiple contradictory fixed atom constraints - cannot"
" be both {} and {}")
[docs]def determine_max_atoms_for_vertex(vertex):
""" returns the max atom constraint after assessing them all.
:param ApplicationVertex vertex: the vertex to find max atoms of
:return: the max number of atoms per core
:rtype: int
"""
possible_max_atoms = list()
n_atoms = None
max_atom_constraints = utils.locate_constraints_of_type(
vertex.constraints, MaxVertexAtomsConstraint)
for constraint in max_atom_constraints:
possible_max_atoms.append(constraint.size)
n_atom_constraints = utils.locate_constraints_of_type(
vertex.constraints, FixedVertexAtomsConstraint)
for constraint in n_atom_constraints:
if n_atoms is not None and constraint.size != n_atoms:
raise PacmanPartitionException(
CONTRADICTORY_FIXED_ATOM_ERROR.format(
n_atoms, constraint.size))
n_atoms = constraint.size
if len(possible_max_atoms) != 0:
return int(min(possible_max_atoms))
else:
return vertex.n_atoms
[docs]def get_remaining_constraints(vertex):
""" Gets the rest of the constraints from a vertex after removing\
partitioning constraints.
:param ApplicationVertex vertex:
:rtype: list(AbstractConstraint)
"""
return [constraint for constraint in vertex.constraints
if not isinstance(constraint, AbstractPartitionerConstraint)]
[docs]def get_same_size_vertex_groups(vertices):
""" Get a dictionary of vertex to vertex that must be partitioned the same\
size.
:param iterble(ApplicationVertex) vertices:
:rtype: dict(ApplicationVertex, set(ApplicationVertex))
"""
# Dict of vertex to list of vertices with same size
# (repeated lists expected)
same_size_vertices = OrderedDict()
for vertex in vertices:
# Find all vertices that have a same size constraint associated with
# this vertex
same_size_as_vertices = list()
for constraint in vertex.constraints:
if isinstance(constraint, SameAtomsAsVertexConstraint):
if vertex.n_atoms != constraint.vertex.n_atoms:
raise PacmanPartitionException(
VERTICES_NEED_TO_BE_SAME_SIZE_ERROR.format(
vertex.label, vertex.n_atoms,
constraint.vertex.label,
constraint.vertex.n_atoms))
same_size_as_vertices.append(constraint.vertex)
if not same_size_as_vertices:
same_size_vertices[vertex] = {vertex}
continue
# Go through all the vertices that want to have the same size
# as the top level vertex
for same_size_vertex in same_size_as_vertices:
# Neither vertex has been seen
if (same_size_vertex not in same_size_vertices and
vertex not in same_size_vertices):
# add both to a new group
group = OrderedSet([vertex, same_size_vertex])
same_size_vertices[vertex] = group
same_size_vertices[same_size_vertex] = group
# Both vertices have been seen elsewhere
elif (same_size_vertex in same_size_vertices and
vertex in same_size_vertices):
# merge their groups
group_1 = same_size_vertices[vertex]
group_2 = same_size_vertices[same_size_vertex]
group_1.update(group_2)
for vert in group_1:
same_size_vertices[vert] = group_1
# The current vertex has been seen elsewhere
elif vertex in same_size_vertices:
# add the new vertex to the existing group
group = same_size_vertices[vertex]
group.add(same_size_vertex)
same_size_vertices[same_size_vertex] = group
# The other vertex has been seen elsewhere
elif same_size_vertex in same_size_vertices:
# so add this vertex to the existing group
group = same_size_vertices[same_size_vertex]
group.add(vertex)
same_size_vertices[vertex] = group
return same_size_vertices