Skip to content

Commit

Permalink
Merge branch 'master' into upgrade_travis_dist_to_bionic
Browse files Browse the repository at this point in the history
  • Loading branch information
dkfellows committed Jun 8, 2020
2 parents a3c18df + b1986bf commit e1b4542
Show file tree
Hide file tree
Showing 28 changed files with 653 additions and 116 deletions.
39 changes: 31 additions & 8 deletions pacman/executor/pacman_algorithm_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,8 @@ def _determine_algorithm_order(

# Set up the token tracking and make all specified tokens complete
token_states = TokenStates()
for token_name in tokens:
token = Token(token_name)
for token in tokens:
token = Token(token.name, token.part)
token_states.track_token(token)
token_states.process_output_token(token)

Expand All @@ -288,7 +288,8 @@ def _determine_algorithm_order(
for algorithm in chain(
self.__algorithm_data, self.__optional_algorithm_data):
for token in algorithm.generated_output_tokens:
if not token_states.is_token_complete(token):
if (not token_states.is_token_complete(token) or
not token_states.is_tracking_token_part(token)):
token_states.track_token(token)

# Go through the algorithms and add a fake token for any algorithm that
Expand Down Expand Up @@ -429,6 +430,26 @@ def __find_suitable_algorithm(
for token in algorithm.generated_output_tokens:
algorithms_by_token[token.name].append("{}: part={}".format(
algorithm.algorithm_id, token.part))

# create complete token string
completed_tokens_string = ""
for token in token_states.get_completed_tokens():
completed_tokens_string += "{}, ".format(token.name)

# create fake token string
fake_token_string = ""
for token in fake_tokens.get_completed_tokens():
fake_token_string += (
"{},{} ".format(token.name, token.part))

# tokens to find string
token_to_find_string = ""
for token_name in tokens_to_find:
token = token_states.get_token(token_name)
for incomplete_part in token.incomplete_parts:
token_to_find_string += (
"{}:{}".format(token_name, incomplete_part))

raise PacmanConfigurationException(
"Unable to deduce a future algorithm to use.\n"
" Inputs: {}\n"
Expand All @@ -446,9 +467,9 @@ def __find_suitable_algorithm(
sorted(self._inputs),
sorted(fake_inputs),
outputs_to_find,
token_states.get_completed_tokens(),
fake_tokens.get_completed_tokens(),
tokens_to_find,
completed_tokens_string,
fake_token_string,
token_to_find_string,
algorithms_to_find_names,
optional_algorithms_names,
algorithms_used,
Expand All @@ -470,7 +491,8 @@ def _remove_outputs_which_are_inputs(self, required_outputs):
copy_required_outputs.remove(input_type)
return copy_required_outputs

def _remove_complete_tokens(self, tokens, output_tokens):
@staticmethod
def _remove_complete_tokens(tokens, output_tokens):
"""
:param TokenStates tokens:
:param output_tokens:
Expand All @@ -481,8 +503,9 @@ def _remove_complete_tokens(self, tokens, output_tokens):
if not tokens.is_token_complete(Token(token))
}

@staticmethod
def __deduce_inputs_required_to_run(
self, algorithm, inputs, tokens, fake_inputs, fake_tokens):
algorithm, inputs, tokens, fake_inputs, fake_tokens):
"""
:param AbstractAlgorithm algorithm:
:param inputs: the inputs available *currently*
Expand Down
38 changes: 33 additions & 5 deletions pacman/executor/token_states.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from six import iteritems
from pacman.executor.algorithm_decorators import Token


class _TokenState(object):
Expand Down Expand Up @@ -76,6 +76,18 @@ def is_complete(self, part=None):
return not self._incomplete_parts
return part in self._complete_parts

@property
def complete_parts(self):
""" returns the complete parts
:return: the complete parts of this token
"""
return self._complete_parts

@property
def incomplete_parts(self):
return self._incomplete_parts


class TokenStates(object):
""" Keeps track of multiple token state objects to determine if they\
Expand Down Expand Up @@ -129,7 +141,23 @@ def is_token_complete(self, token):
def get_completed_tokens(self):
""" Get a list of tokens that have been completed
"""
return [
name for name, token in iteritems(self._tokens)
if token.is_complete()
]
tokens_to_return = list()
for token_name in self._tokens:
for completed_part in self._tokens[token_name].complete_parts:
tokens_to_return.append(
Token(name=token_name, part=completed_part))
return tokens_to_return

def get_token(self, name):
return self._tokens[name]

def is_tracking_token_part(self, token):
""" checks if a token part is actually being tracked
:param token: the token whom's part is to be checked.
:return: bool
"""
if token.name not in self._tokens:
return False

return self._tokens[token.name].is_tracking_token_part(token.part)
2 changes: 1 addition & 1 deletion pacman/model/graphs/common/graph_mapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from spinn_utilities.ordered_default_dict import DefaultOrderedDict
from spinn_utilities.default_ordered_dict import DefaultOrderedDict
from spinn_utilities.ordered_set import OrderedSet
from pacman.exceptions import PacmanValueError

Expand Down
3 changes: 1 addition & 2 deletions pacman/model/graphs/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from collections import OrderedDict
from spinn_utilities.ordered_default_dict import DefaultOrderedDict
from spinn_utilities.default_ordered_dict import DefaultOrderedDict
from spinn_utilities.ordered_set import OrderedSet
from pacman.exceptions import (
PacmanAlreadyExistsException, PacmanInvalidParameterException)
Expand Down Expand Up @@ -201,7 +201,6 @@ def add_edges(self, edges, outgoing_edge_partition_name):

def add_outgoing_edge_partition(self, outgoing_edge_partition):
""" Add an outgoing edge partition to the graph.
:param OutgoingEdgePartition outgoing_edge_partition:
The outgoing edge partition to add
:raises PacmanAlreadyExistsException:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ def set_n_keys_for_partition(self, partition, n_keys):

@overrides(AbstractMachinePartitionNKeysMap.n_keys_for_partition)
def n_keys_for_partition(self, partition):
return self._n_keys_map[partition]
if partition in self._n_keys_map:
return self._n_keys_map[partition]

@overrides(AbstractMachinePartitionNKeysMap.__iter__)
def __iter__(self):
Expand Down
8 changes: 6 additions & 2 deletions pacman/model/routing_tables/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from .multicast_routing_table import MulticastRoutingTable
from .uncompressed_multicast_routing_table import (
UnCompressedMulticastRoutingTable)
from .compressed_multicast_routing_table import (
CompressedMulticastRoutingTable)
from .multicast_routing_tables import MulticastRoutingTables

__all__ = ["MulticastRoutingTable", "MulticastRoutingTables"]
__all__ = ["UnCompressedMulticastRoutingTable",
"CompressedMulticastRoutingTable", "MulticastRoutingTables"]
79 changes: 79 additions & 0 deletions pacman/model/routing_tables/abstract_multicast_routing_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Copyright (c) 2019-2020 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/>.

from six import add_metaclass
from spinn_utilities.abstract_base import AbstractBase, abstractproperty, \
abstractmethod


@add_metaclass(AbstractBase)
class AbsractMulticastRoutingTable(object):

@abstractproperty
def x(self):
"""The x-coordinate of the chip of this table
:return: The x-coordinate
:rtype: int
"""

@abstractproperty
def y(self):
""" The y-coordinate of the chip of this table
:return: The y-coordinate
:rtype: int
"""

@abstractproperty
def multicast_routing_entries(self):
""" The multicast routing entries in the table
:return: an iterable of multicast routing entries
:rtype: iterable(:py:class:`spinn_machine.MulticastRoutingEntry`)
:raise None: does not raise any known exceptions
"""

@abstractproperty
def number_of_entries(self):
""" The number of multi-cast routing entries there are in the\
multicast routing table
:return: int
"""

@abstractproperty
def number_of_defaultable_entries(self):
""" The number of multi-cast routing entries that are set to be\
defaultable within this multicast routing table
:return: int
"""

@abstractmethod
def __eq__(self, other):
"""equals method"""

@abstractmethod
def __ne__(self, other):
""" not equals method"""

@abstractmethod
def __hash__(self):
"""hash"""

@abstractmethod
def __repr__(self):
"""repr"""
127 changes: 127 additions & 0 deletions pacman/model/routing_tables/compressed_multicast_routing_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# Copyright (c) 2019-2020 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/>.

from pacman.model.routing_tables.abstract_multicast_routing_table import \
AbsractMulticastRoutingTable
from spinn_utilities.overrides import overrides


class CompressedMulticastRoutingTable(AbsractMulticastRoutingTable):
""" Represents a compressed routing table for a chip.
"""

__slots__ = [
# The x-coordinate of the chip for which this is the routing table
"_x",

# The y-coordinate of the chip for which this is the routing tables
"_y",

# An iterable of routing entries to add to the table
"_multicast_routing_entries",

# counter of how many entries in their multicast routing table are
# defaultable
"_number_of_defaulted_routing_entries"
]

def __init__(self, x, y, multicast_routing_entries=None):
"""
:param x: \
The x-coordinate of the chip for which this is the routing table
:type x: int
:param y: \
The y-coordinate of the chip for which this is the routing tables
:type y: int
:param multicast_routing_entries: \
The routing entries to add to the table
:type multicast_routing_entries: \
iterable(:py:class:`spinn_machine.MulticastRoutingEntry`)
:raise pacman.exceptions.PacmanAlreadyExistsException: If any two\
routing entries contain the same key-mask combination
"""
self._x = x
self._y = y
self._number_of_defaulted_routing_entries = 0
self._multicast_routing_entries = list()

if multicast_routing_entries is not None:
for multicast_routing_entry in multicast_routing_entries:
self.add_multicast_routing_entry(multicast_routing_entry)

def add_multicast_routing_entry(self, multicast_routing_entry):
""" Adds a routing entry to this table
:param multicast_routing_entry: The route to add
:type multicast_routing_entry:\
:py:class:`spinn_machine.MulticastRoutingEntry`
:rtype: None
:raise pacman.exceptions.PacmanAlreadyExistsException: If a routing\
entry with the same key-mask combination already exists
"""
self._multicast_routing_entries.append(multicast_routing_entry)

# update default routed counter if required
if multicast_routing_entry.defaultable:
self._number_of_defaulted_routing_entries += 1

@property
@overrides(AbsractMulticastRoutingTable.x)
def x(self):
return self._x

@property
@overrides(AbsractMulticastRoutingTable.y)
def y(self):
return self._y

@property
@overrides(AbsractMulticastRoutingTable.multicast_routing_entries)
def multicast_routing_entries(self):
return self._multicast_routing_entries

@property
@overrides(AbsractMulticastRoutingTable.number_of_entries)
def number_of_entries(self):
return len(self._multicast_routing_entries)

@property
@overrides(AbsractMulticastRoutingTable.number_of_defaultable_entries)
def number_of_defaultable_entries(self):
return self._number_of_defaulted_routing_entries

@overrides(AbsractMulticastRoutingTable.__eq__)
def __eq__(self, other):
if not isinstance(other, CompressedMulticastRoutingTable):
return False
if self._x != other.x and self._y != other.y:
return False
return self._multicast_routing_entries == \
other.multicast_routing_entries

@overrides(AbsractMulticastRoutingTable.__ne__)
def __ne__(self, other):
return not self.__eq__(other)

@overrides(AbsractMulticastRoutingTable.__repr__)
def __repr__(self):
entry_string = ""
for entry in self._multicast_routing_entries:
entry_string += "{}\n".format(entry)
return "{}:{}\n\n{}".format(self._x, self._y, entry_string)

@overrides(AbsractMulticastRoutingTable.__hash__)
def __hash__(self):
return id(self)

0 comments on commit e1b4542

Please sign in to comment.