From 62b1947577f7cded628fcbb39c23c6af24c85ec2 Mon Sep 17 00:00:00 2001
From: angloth <angus.lothian@hotmail.com>
Date: Wed, 18 Mar 2020 17:16:29 +0100
Subject: [PATCH] Move abstract operation to operation module and move utilties
 implementation to operation, remove abstract operation and utilities module.

---
 b_asic/__init__.py           |   2 -
 b_asic/abstract_operation.py | 114 ---------------------------------
 b_asic/core_operations.py    |   2 +-
 b_asic/operation.py          | 118 ++++++++++++++++++++++++++++++++++-
 b_asic/signal_flow_graph.py  |   2 +-
 b_asic/utilities.py          |  21 -------
 6 files changed, 118 insertions(+), 141 deletions(-)
 delete mode 100644 b_asic/abstract_operation.py
 delete mode 100644 b_asic/utilities.py

diff --git a/b_asic/__init__.py b/b_asic/__init__.py
index 67e1c856..7e40ad52 100644
--- a/b_asic/__init__.py
+++ b/b_asic/__init__.py
@@ -2,7 +2,6 @@
 Better ASIC Toolbox.
 TODO: More info.
 """
-from b_asic.abstract_operation import *
 from b_asic.core_operations import *
 from b_asic.graph_component import *
 from b_asic.graph_id import *
@@ -13,4 +12,3 @@ from b_asic.schema import *
 from b_asic.signal_flow_graph import *
 from b_asic.signal import *
 from b_asic.simulation import *
-from b_asic.utilities import *
diff --git a/b_asic/abstract_operation.py b/b_asic/abstract_operation.py
deleted file mode 100644
index 68b3c02a..00000000
--- a/b_asic/abstract_operation.py
+++ /dev/null
@@ -1,114 +0,0 @@
-"""@package docstring
-B-ASIC Abstract Operation Module.
-TODO: More info
-"""
-
-from abc import abstractmethod
-from typing import List, Dict, Optional, Any
-from numbers import Number
-
-from b_asic.operation import Operation
-from b_asic.graph_component import AbstractGraphComponent, Name
-from b_asic.port import InputPort, OutputPort
-from b_asic.simulation import SimulationState, OperationState
-from b_asic.utilities import breadth_first_search
-from b_asic.signal import Signal
-
-
-class AbstractOperation(Operation, AbstractGraphComponent):
-    """Generic abstract operation class which most implementations will derive from.
-    TODO: More info.
-    """
-
-    _input_ports: List[InputPort]
-    _output_ports: List[OutputPort]
-    _parameters: Dict[str, Optional[Any]]
-
-    def __init__(self, name: Name = ""):
-        super().__init__(name)
-        self._input_ports = []
-        self._output_ports = []
-        self._parameters = {}
-
-    @abstractmethod
-    def evaluate(self, *inputs) -> Any: # pylint: disable=arguments-differ
-        """Evaluate the operation and generate a list of output values given a
-        list of input values."""
-        raise NotImplementedError
-
-    def inputs(self) -> List[InputPort]:
-        return self._input_ports.copy()
-
-    def outputs(self) -> List[OutputPort]:
-        return self._output_ports.copy()
-
-    def input_count(self) -> int:
-        return len(self._input_ports)
-
-    def output_count(self) -> int:
-        return len(self._output_ports)
-
-    def input(self, i: int) -> InputPort:
-        return self._input_ports[i]
-
-    def output(self, i: int) -> OutputPort:
-        return self._output_ports[i]
-
-    def params(self) -> Dict[str, Optional[Any]]:
-        return self._parameters.copy()
-
-    def param(self, name: str) -> Optional[Any]:
-        return self._parameters.get(name)
-
-    def set_param(self, name: str, value: Any) -> None:
-        assert name in self._parameters # TODO: Error message.
-        self._parameters[name] = value
-
-    def evaluate_outputs(self, state: SimulationState) -> List[Number]:
-        # TODO: Check implementation.
-        input_count: int = self.input_count()
-        output_count: int = self.output_count()
-        assert input_count == len(self._input_ports) # TODO: Error message.
-        assert output_count == len(self._output_ports) # TODO: Error message.
-
-        self_state: OperationState = state.operation_states[self]
-
-        while self_state.iteration < state.iteration:
-            input_values: List[Number] = [0] * input_count
-            for i in range(input_count):
-                source: Signal = self._input_ports[i].signal
-                input_values[i] = source.operation.evaluate_outputs(state)[source.port_index]
-
-            self_state.output_values = self.evaluate(input_values)
-            assert len(self_state.output_values) == output_count # TODO: Error message.
-            self_state.iteration += 1
-            for i in range(output_count):
-                for signal in self._output_ports[i].signals():
-                    destination: Signal = signal.destination
-                    destination.evaluate_outputs(state)
-
-        return self_state.output_values
-
-    def split(self) -> List[Operation]:
-        # TODO: Check implementation.
-        results = self.evaluate(self._input_ports)
-        if all(isinstance(e, Operation) for e in results):
-            return results
-        return [self]
-
-    @property
-    def neighbours(self) -> List[Operation]:
-        neighbours: List[Operation] = []
-        for port in self._input_ports:
-            for signal in port.signals:
-                neighbours.append(signal.source.operation)
-
-        for port in self._output_ports:
-            for signal in port.signals:
-                neighbours.append(signal.destination.operation)
-
-        return neighbours
-
-    def traverse(self) -> Operation:
-        """Traverse the operation tree and return a generator with start point in the operation."""
-        return breadth_first_search(self)
diff --git a/b_asic/core_operations.py b/b_asic/core_operations.py
index 7b644f34..ce1019f3 100644
--- a/b_asic/core_operations.py
+++ b/b_asic/core_operations.py
@@ -8,7 +8,7 @@ from typing import Any
 from numpy import conjugate, sqrt, abs as np_abs
 from b_asic.port import InputPort, OutputPort
 from b_asic.graph_id import GraphIDType
-from b_asic.abstract_operation import AbstractOperation
+from b_asic.operation import AbstractOperation
 from b_asic.graph_component import Name, TypeName
 
 
diff --git a/b_asic/operation.py b/b_asic/operation.py
index ac6e0319..75644b73 100644
--- a/b_asic/operation.py
+++ b/b_asic/operation.py
@@ -5,9 +5,12 @@ TODO: More info.
 
 from abc import abstractmethod
 from numbers import Number
-from typing import List, Dict, Optional, Any, TYPE_CHECKING
+from typing import List, Dict, Optional, Any, Set, TYPE_CHECKING
+from collections import deque
 
-from b_asic.graph_component import GraphComponent
+from b_asic.graph_component import GraphComponent, AbstractGraphComponent, Name
+from b_asic.simulation import SimulationState, OperationState
+from b_asic.signal import Signal
 
 if TYPE_CHECKING:
     from b_asic.port import InputPort, OutputPort
@@ -88,3 +91,114 @@ class Operation(GraphComponent):
         If no neighbours are found this returns an empty list
         """
         raise NotImplementedError
+
+
+class AbstractOperation(Operation, AbstractGraphComponent):
+    """Generic abstract operation class which most implementations will derive from.
+    TODO: More info.
+    """
+
+    _input_ports: List["InputPort"]
+    _output_ports: List["OutputPort"]
+    _parameters: Dict[str, Optional[Any]]
+
+    def __init__(self, name: Name = ""):
+        super().__init__(name)
+        self._input_ports = []
+        self._output_ports = []
+        self._parameters = {}
+
+    @abstractmethod
+    def evaluate(self, *inputs) -> Any: # pylint: disable=arguments-differ
+        """Evaluate the operation and generate a list of output values given a
+        list of input values."""
+        raise NotImplementedError
+
+    def inputs(self) -> List["InputPort"]:
+        return self._input_ports.copy()
+
+    def outputs(self) -> List["OutputPort"]:
+        return self._output_ports.copy()
+
+    def input_count(self) -> int:
+        return len(self._input_ports)
+
+    def output_count(self) -> int:
+        return len(self._output_ports)
+
+    def input(self, i: int) -> "InputPort":
+        return self._input_ports[i]
+
+    def output(self, i: int) -> "OutputPort":
+        return self._output_ports[i]
+
+    def params(self) -> Dict[str, Optional[Any]]:
+        return self._parameters.copy()
+
+    def param(self, name: str) -> Optional[Any]:
+        return self._parameters.get(name)
+
+    def set_param(self, name: str, value: Any) -> None:
+        assert name in self._parameters # TODO: Error message.
+        self._parameters[name] = value
+
+    def evaluate_outputs(self, state: SimulationState) -> List[Number]:
+        # TODO: Check implementation.
+        input_count: int = self.input_count()
+        output_count: int = self.output_count()
+        assert input_count == len(self._input_ports) # TODO: Error message.
+        assert output_count == len(self._output_ports) # TODO: Error message.
+
+        self_state: OperationState = state.operation_states[self]
+
+        while self_state.iteration < state.iteration:
+            input_values: List[Number] = [0] * input_count
+            for i in range(input_count):
+                source: Signal = self._input_ports[i].signal
+                input_values[i] = source.operation.evaluate_outputs(state)[source.port_index]
+
+            self_state.output_values = self.evaluate(input_values)
+            assert len(self_state.output_values) == output_count # TODO: Error message.
+            self_state.iteration += 1
+            for i in range(output_count):
+                for signal in self._output_ports[i].signals():
+                    destination: Signal = signal.destination
+                    destination.evaluate_outputs(state)
+
+        return self_state.output_values
+
+    def split(self) -> List[Operation]:
+        # TODO: Check implementation.
+        results = self.evaluate(self._input_ports)
+        if all(isinstance(e, Operation) for e in results):
+            return results
+        return [self]
+
+    @property
+    def neighbours(self) -> List[Operation]:
+        neighbours: List[Operation] = []
+        for port in self._input_ports:
+            for signal in port.signals:
+                neighbours.append(signal.source.operation)
+
+        for port in self._output_ports:
+            for signal in port.signals:
+                neighbours.append(signal.destination.operation)
+
+        return neighbours
+
+    def traverse(self) -> Operation:
+        """Traverse the operation tree and return a generator with start point in the operation."""
+        return self._breadth_first_search()
+
+    def _breadth_first_search(self) -> Operation:
+        """Use breadth first search to traverse the operation tree."""
+        visited: Set[Operation] = {self}
+        queue = deque([self])
+        while queue:
+            operation = queue.popleft()
+            yield operation
+            for n_operation in operation.neighbours:
+                if n_operation not in visited:
+                    visited.add(n_operation)
+                    queue.append(n_operation)
diff --git a/b_asic/signal_flow_graph.py b/b_asic/signal_flow_graph.py
index f59a246d..9c08aecc 100644
--- a/b_asic/signal_flow_graph.py
+++ b/b_asic/signal_flow_graph.py
@@ -7,7 +7,7 @@ from typing import List, Dict, Optional, DefaultDict
 from collections import defaultdict
 
 from b_asic.operation import Operation
-from b_asic.abstract_operation import AbstractOperation
+from b_asic.operation import AbstractOperation
 from b_asic.signal import Signal
 from b_asic.graph_id import GraphIDGenerator, GraphID
 from b_asic.graph_component import GraphComponent, Name, TypeName
diff --git a/b_asic/utilities.py b/b_asic/utilities.py
deleted file mode 100644
index 25707ff8..00000000
--- a/b_asic/utilities.py
+++ /dev/null
@@ -1,21 +0,0 @@
-"""@package docstring
-B-ASIC Operation Module.
-TODO: More info.
-"""
-
-from typing import Set
-from collections import deque
-
-from b_asic.operation import Operation
-
-def breadth_first_search(start: Operation) -> Operation:
-    """Use breadth first search to traverse the operation tree."""
-    visited: Set[Operation] = {start}
-    queue = deque([start])
-    while queue:
-        operation = queue.popleft()
-        yield operation
-        for n_operation in operation.neighbours:
-            if n_operation not in visited:
-                visited.add(n_operation)
-                queue.append(n_operation)
-- 
GitLab