Skip to content
Snippets Groups Projects
Commit 3548e462 authored by Jacob Wahlman's avatar Jacob Wahlman :ok_hand:
Browse files

Merge branch '11-operation-traversing' into 'develop'

Resolve "Operation Traversing"

See merge request PUM_TDDD96/B-ASIC!7
parents 1541f59d 72cb843b
No related branches found
No related tags found
4 merge requests!67WIP: B-ASIC version 1.0.0 hotfix,!65B-ASIC version 1.0.0,!15Add changes from sprint 1 and 2 to master,!7Resolve "Operation Traversing"
Pipeline #10193 passed
...@@ -14,4 +14,4 @@ from b_asic.schema import * ...@@ -14,4 +14,4 @@ from b_asic.schema import *
from b_asic.signal_flow_graph import * from b_asic.signal_flow_graph import *
from b_asic.signal import * from b_asic.signal import *
from b_asic.simulation import * from b_asic.simulation import *
from b_asic.traverse_tree import * from b_asic.utilities import *
...@@ -4,13 +4,14 @@ TODO: More info. ...@@ -4,13 +4,14 @@ TODO: More info.
""" """
from abc import abstractmethod from abc import abstractmethod
from typing import List, Dict, Optional, Any from typing import List, Set, Dict, Optional, Any
from numbers import Number from numbers import Number
from b_asic.port import InputPort, OutputPort from b_asic.port import InputPort, OutputPort
from b_asic.signal import Signal from b_asic.signal import Signal
from b_asic.operation import Operation from b_asic.operation import Operation
from b_asic.simulation import SimulationState, OperationState from b_asic.simulation import SimulationState, OperationState
from b_asic.utilities import breadth_first_search
from b_asic.abstract_graph_component import AbstractGraphComponent from b_asic.abstract_graph_component import AbstractGraphComponent
class AbstractOperation(Operation, AbstractGraphComponent): class AbstractOperation(Operation, AbstractGraphComponent):
...@@ -106,4 +107,8 @@ class AbstractOperation(Operation, AbstractGraphComponent): ...@@ -106,4 +107,8 @@ class AbstractOperation(Operation, AbstractGraphComponent):
return neighbours 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)
# TODO: More stuff. # TODO: More stuff.
"""@package docstring
B-ASIC Operation Tree Traversing Module.
"""
from typing import List, Optional
from collections import deque
from b_asic.operation import Operation
class Traverse:
"""Traverse operation tree."""
def __init__(self, operation: Operation):
"""Construct a TraverseTree."""
self._initial_operation = operation
def _breadth_first_search(self, start: Operation) -> List[Operation]:
"""Use breadth first search to traverse the operation tree."""
visited: List[Operation] = [start]
queue = deque([start])
while queue:
operation = queue.popleft()
for n_operation in operation.neighbours:
if n_operation not in visited:
visited.append(n_operation)
queue.append(n_operation)
return visited
def traverse(self, type_: Optional[Operation] = None) -> List[Operation]:
"""Traverse the the operation tree and return operation where type matches.
If the type is None then return the entire tree.
Keyword arguments:
type_-- the operation type to search for (default None)
"""
operations: List[Operation] = self._breadth_first_search(self._initial_operation)
if type_ is not None:
operations = [oper for oper in operations if isinstance(oper, type_)]
return operations
"""@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)
import pytest import pytest
from test.fixtures.signal import * from test.fixtures.signal import *
\ No newline at end of file from test.fixtures.operation_tree import *
\ No newline at end of file
from b_asic.core_operations import Addition, Constant
from b_asic.signal import Signal
import pytest
@pytest.fixture
def operation():
return Constant(2)
def create_operation(_type, dest_oper, index, **kwargs):
oper = _type(**kwargs)
oper_signal = Signal()
oper._output_ports[0].connect(oper_signal)
dest_oper._input_ports[index].connect(oper_signal)
return oper
@pytest.fixture
def operation_tree():
add_oper = Addition()
create_operation(Constant, add_oper, 0, value=2)
create_operation(Constant, add_oper, 1, value=3)
return add_oper
@pytest.fixture
def large_operation_tree():
add_oper = Addition()
add_oper_2 = Addition()
const_oper = create_operation(Constant, add_oper, 0, value=2)
create_operation(Constant, add_oper, 1, value=3)
create_operation(Constant, add_oper_2, 0, value=4)
create_operation(Constant, add_oper_2, 1, value=5)
add_oper_3 = Addition()
add_oper_signal = Signal(add_oper, add_oper_3)
add_oper._output_ports[0].connect(add_oper_signal)
add_oper_3._input_ports[0].connect(add_oper_signal)
add_oper_2_signal = Signal(add_oper_2, add_oper_3)
add_oper_2._output_ports[0].connect(add_oper_2_signal)
add_oper_3._input_ports[1].connect(add_oper_2_signal)
return const_oper
"""
TODO:
- Rewrite to more clean code, not so repetitive
- Update when signals and id's has been merged.
"""
from b_asic.core_operations import Constant, Addition from b_asic.core_operations import Constant, Addition
from b_asic.signal import Signal from b_asic.signal import Signal
from b_asic.port import InputPort, OutputPort from b_asic.port import InputPort, OutputPort
from b_asic.traverse_tree import Traverse
import pytest import pytest
@pytest.fixture
def operation():
return Constant(2)
def create_operation(_type, dest_oper, index, **kwargs):
oper = _type(**kwargs)
oper_signal = Signal()
oper._output_ports[0].connect(oper_signal)
dest_oper._input_ports[index].connect(oper_signal)
return oper
@pytest.fixture
def operation_tree():
add_oper = Addition()
const_oper = create_operation(Constant, add_oper, 0, value=2)
const_oper_2 = create_operation(Constant, add_oper, 1, value=3)
return add_oper
@pytest.fixture
def large_operation_tree():
add_oper = Addition()
add_oper_2 = Addition()
const_oper = create_operation(Constant, add_oper, 0, value=2)
const_oper_2 = create_operation(Constant, add_oper, 1, value=3)
const_oper_3 = create_operation(Constant, add_oper_2, 0, value=4)
const_oper_4 = create_operation(Constant, add_oper_2, 1, value=5)
add_oper_3 = Addition()
add_oper_signal = Signal(add_oper, add_oper_3)
add_oper._output_ports[0].connect(add_oper_signal)
add_oper_3._input_ports[0].connect(add_oper_signal)
add_oper_2_signal = Signal(add_oper_2, add_oper_3)
add_oper_2._output_ports[0].connect(add_oper_2_signal)
add_oper_3._input_ports[1].connect(add_oper_2_signal)
return const_oper
def test_traverse_single_tree(operation): def test_traverse_single_tree(operation):
traverse = Traverse(operation) """Traverse a tree consisting of one operation."""
assert traverse.traverse() == [operation] constant = Constant(None)
assert list(constant.traverse()) == [constant]
def test_traverse_tree(operation_tree): def test_traverse_tree(operation_tree):
traverse = Traverse(operation_tree) """Traverse a basic addition tree with two constants."""
assert len(traverse.traverse()) == 3 assert len(list(operation_tree.traverse())) == 3
def test_traverse_large_tree(large_operation_tree): def test_traverse_large_tree(large_operation_tree):
traverse = Traverse(large_operation_tree) """Traverse a larger tree."""
assert len(traverse.traverse()) == 7 assert len(list(large_operation_tree.traverse())) == 7
def test_traverse_type(large_operation_tree): def test_traverse_type(large_operation_tree):
traverse = Traverse(large_operation_tree) traverse = list(large_operation_tree.traverse())
assert len(traverse.traverse(Addition)) == 3 assert len(list(filter(lambda type_: isinstance(type_, Addition), traverse))) == 3
assert len(traverse.traverse(Constant)) == 4 assert len(list(filter(lambda type_: isinstance(type_, Constant), traverse))) == 4
def test_traverse_loop(operation_tree): def test_traverse_loop(operation_tree):
add_oper_signal = Signal() add_oper_signal = Signal()
operation_tree._output_ports[0].connect(add_oper_signal) operation_tree._output_ports[0].connect(add_oper_signal)
operation_tree._input_ports[0].connect(add_oper_signal) operation_tree._input_ports[0].connect(add_oper_signal)
traverse = Traverse(operation_tree) assert len(list(operation_tree.traverse())) == 2
assert len(traverse.traverse()) == 2
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment