From 7ffba9a29508902f3f22ac297277e7e5336eb817 Mon Sep 17 00:00:00 2001 From: Andrei Bondarenko Date: Sat, 9 Oct 2021 22:25:50 +0200 Subject: [PATCH] More docs --- services/bottom/V0.py | 111 ++++++++++++++++++++++++++++++++++++ services/bottom/V1.py | 74 +++++++++++++++++++++++- services/point/cartesian.py | 50 ++++++++++++++++ services/point/polar.py | 50 ++++++++++++++++ 4 files changed, 283 insertions(+), 2 deletions(-) diff --git a/services/bottom/V0.py b/services/bottom/V0.py index cfa32eb..a8422c1 100644 --- a/services/bottom/V0.py +++ b/services/bottom/V0.py @@ -4,33 +4,94 @@ from typing import Any, List class Bottom: + """ + Implements services for LTM bottom (not yet explicitly modelled). + Implemented using the (Modelverse) state graph data structure + """ def __init__(self, state: State): self.state = state def create_node(self, value=None) -> UUID: + """ + Creates a node, which optionally contains a value. + + Args: + value: value to be stored in the node + + Returns: + UUID of the node. + """ if value is None: return self.state.create_node() else: return self.state.create_nodevalue(value) def create_edge(self, source: UUID, target: UUID, label=None): + """ + Creates an edge, which optionally is labelled. + + Args: + source: source element of the edge + target: target element of the edge + label: value to label the edge with + + Returns: + UUID of the edge. + """ if label is None: return self.state.create_edge(source, target) else: return self.state.create_dict(source, label, target) def read_value(self, node: UUID) -> Any: + """ + Reads value stored in a node. + + Args: + node: UUID of the node to read value from + + Returns: + Value contained in the node. If no value is found, returns None + """ return self.state.read_value(node) def read_edge_source(self, edge: UUID) -> UUID: + """ + Reads source element of an edge. + + Args: + edge: UUID of the edge to read source element of + + Returns: + UUID of source element of the edge + """ result = self.state.read_edge(edge) return result[0] if result is not None else result def read_edge_target(self, edge: UUID) -> UUID: + """ + Reads target element of an edge. + + Args: + edge: UUID of the edge to read target element of + + Returns: + UUID of target element of the edge + """ result = self.state.read_edge(edge) return result[1] if result is not None else result def read_incoming_edges(self, target: UUID, label=None) -> List[UUID]: + """ + Reads incoming edges of an element. Optionally, filter them based on their label + + Args: + target: UUID of the element to read incoming edges for + label: value to filter edge labels by + + Returns: + List of UUIDs of incoming edges + """ def read_label(_edge: UUID): try: label_edge, = self.state.read_outgoing(_edge) @@ -48,6 +109,16 @@ class Bottom: return edges def read_outgoing_edges(self, source: UUID, label=None) -> List[UUID]: + """ + Reads outgoing edges of an element. Optionally, filter them based on their label + + Args: + source: UUID of the element to read outgoing edges for + label: value to filter edge labels by + + Returns: + List of UUIDs of outgoing edges + """ def read_label(_edge: UUID): try: label_edge, = self.state.read_outgoing(_edge) @@ -65,6 +136,17 @@ class Bottom: return edges def read_incoming_elements(self, target: UUID, label=None) -> List[UUID]: + """ + Reads elements connected to given element via incoming edges. + Optionally, filter them based on the edge label. + + Args: + target: UUID of the element to read incoming elements for + label: value to filter edge labels by + + Returns: + List of UUIDs of elements connected via incoming edges + """ edges = self.read_incoming_edges(target, label) if edges is None or len(edges) == 0: return [] @@ -72,6 +154,17 @@ class Bottom: return [self.read_edge_source(e) for e in edges] def read_outgoing_elements(self, source: UUID, label=None) -> List[UUID]: + """ + Reads elements connected to given element via outgoing edges. + Optionally, filter them based on the edge label. + + Args: + source: UUID of the element to read outgoing elements for + label: value to filter edge labels by + + Returns: + List of UUIDs of elements connected via outgoing edges + """ edges = self.read_outgoing_edges(source, label) if edges is None or len(edges) == 0: return [] @@ -79,11 +172,29 @@ class Bottom: return [self.read_edge_target(e) for e in edges] def read_keys(self, element: UUID) -> List[str]: + """ + Retrieve list of outgoing edge labels + + Args: + element: UUID of the element to read outgoing edge labels for + + Returns: + List of outgoing edge labels + """ key_nodes = self.state.read_dict_keys(element) unique_keys = {self.state.read_value(node) for node in key_nodes} return list(unique_keys) def delete_element(self, element: UUID): + """ + Delete an element + + Args: + element: UUID of the element to be deleted + + Returns: + Nothing + """ src, tgt = self.state.read_edge(element) if src is None and tgt is None: # node diff --git a/services/bottom/V1.py b/services/bottom/V1.py index 0d9a774..2db0ba2 100644 --- a/services/bottom/V1.py +++ b/services/bottom/V1.py @@ -4,6 +4,10 @@ from services.bottom.V0 import Bottom as BottomV0 class Bottom: + """ + Implements services for LTM bottom. + Implemented using V0.Bottom + """ def __init__(self, model: UUID, state: State): type_model_id = state.read_dict(state.read_root(), "Bottom") self.type_model = UUID(state.read_value(type_model_id)) @@ -11,7 +15,16 @@ class Bottom: self.bottom = BottomV0(state) def create_node(self, name: str, value=None): + """ + Creates a node. + Args: + name: node name in model + value: value to be stored in the node + + Returns: + Nothing + """ if value is None: n = self.bottom.create_node() else: @@ -19,6 +32,17 @@ class Bottom: self.bottom.create_edge(self.model, n, label=name) def create_edge(self, name: str, source: str, target: str): + """ + Creates an edge. + + Args: + name: edge name in model + source: source element of the edge + target: target element of the edge + + Returns: + Nothing + """ try: src, = self.bottom.read_outgoing_elements(self.model, source) except ValueError: @@ -31,6 +55,15 @@ class Bottom: self.bottom.create_edge(self.model, e, label=name) def read_value(self, name: str): + """ + Reads value stored in a node. + + Args: + name: name of the node to read value from + + Returns: + Value contained in the node. If no value is found, returns None + """ try: element, = self.bottom.read_outgoing_elements(self.model, name) return self.bottom.read_value(element) @@ -38,16 +71,47 @@ class Bottom: raise RuntimeError(f"No element named {name}") def read_edge_source(self, name: str): + """ + Reads source element of an edge. + + Args: + name: name of the edge to read source element of + + Returns: + UUID of source element of the edge + """ try: element, = self.bottom.read_outgoing_elements(self.model, name) - return self.bottom.read_value(element) + return self.bottom.read_edge_source(element) except ValueError: raise RuntimeError(f"No element named {name}") def read_edge_target(self, name: str): - pass + """ + Reads target element of an edge. + + Args: + name: name of the edge to read target element of + + Returns: + UUID of target element of the edge + """ + try: + element, = self.bottom.read_outgoing_elements(self.model, name) + return self.bottom.read_edge_target(element) + except ValueError: + raise RuntimeError(f"No element named {name}") def delete_element(self, name: str): + """ + Delete an element + + Args: + element: UUID of the element to be deleted + + Returns: + Nothing + """ try: element, = self.bottom.read_outgoing_elements(self.model, name) self.bottom.delete_element(element) @@ -55,6 +119,12 @@ class Bottom: raise RuntimeError(f"No element named {name}") def list_elements(self): + """ + Lists elements in the model. + + Returns: + A list of elements in alphabetical order. + """ tm_names = {} for key in self.bottom.read_keys(self.type_model): element, = self.bottom.read_outgoing_elements(self.type_model, key) diff --git a/services/point/cartesian.py b/services/point/cartesian.py index 323de54..e3a7dc1 100644 --- a/services/point/cartesian.py +++ b/services/point/cartesian.py @@ -5,6 +5,10 @@ from services.primitives.float_type import Float class PointCartesian: + """ + Implements services for the point cartesian LTM. + Implementation is done in terms of Python data structures + """ def __init__(self, model: UUID, state: State): type_model_id = state.read_dict(state.read_root(), "PointCartesian") self.type_model = UUID(state.read_value(type_model_id)) @@ -14,27 +18,66 @@ class PointCartesian: self.point = None def create_point(self, x: float, y: float): + """ + Creates a point. + + Args: + x: x coordinate + y: y coordinate + + Returns: + Nothing. + """ if self.point is None: self.point = (x, y) else: raise RuntimeError("A PointCartesian model can contain at most 1 point.") def read_point(self): + """ + Reads point. + + Returns: + Textual representation of the point data. + """ if self.point is None: raise RuntimeError("No point found in model.") else: return f"(X = {self.point[0]}, Y = {self.point[1]})" def delete_point(self): + """ + Deletes point. + + Returns: + Nothing. + """ self.point = None def apply_movement(self, delta_x: float, delta_y: float): + """ + Moves point. + + Args: + delta_x: change in x dimension + delta_y: change in y dimension + + Returns: + Nothing. + """ if self.point is not None: self.point = (self.point[0] + delta_x, self.point[1] + delta_y) else: raise RuntimeError("No point found in model.") def to_bottom(self): + """ + Converts implementation specific model representation to + canonical representation. + + Returns: + Nothing. + """ bottom = Bottom(self.state) # clear residual model for element in bottom.read_outgoing_elements(self.model): @@ -69,6 +112,13 @@ class PointCartesian: bottom.create_edge(c2_link, ltm_point_link, "Morphism") def from_bottom(self): + """ + Converts canonical representation to + implementation specific model representation. + + Returns: + Nothing. + """ bottom = Bottom(self.state) keys = bottom.read_keys(self.model) x_key, = filter(lambda k: k.endswith(".c1"), keys) diff --git a/services/point/polar.py b/services/point/polar.py index 33bfc08..b48368c 100644 --- a/services/point/polar.py +++ b/services/point/polar.py @@ -7,6 +7,10 @@ import math class PointPolar: + """ + Implements services for the point polar LTM. + Implementation is done in terms of Python data structures + """ def __init__(self, model: UUID, state: State): type_model_id = state.read_dict(state.read_root(), "PointPolar") self.type_model = UUID(state.read_value(type_model_id)) @@ -16,27 +20,66 @@ class PointPolar: self.point = None def create_point(self, r: float, theta: float): + """ + Creates a point. + + Args: + r: distance from pole + theta: angle from polar axis + + Returns: + Nothing. + """ if self.point is None: self.point = (r, theta) else: raise RuntimeError("A PointPolar model can contain at most 1 point.") def read_point(self): + """ + Reads point. + + Returns: + Textual representation of the point data. + """ if self.point is None: raise RuntimeError("No point found in model.") else: return f"(r = {self.point[0]}, \u03B8 = {self.point[1]})" def delete_point(self): + """ + Deletes point. + + Returns: + Nothing. + """ self.point = None def apply_movement(self, delta_r: float, delta_theta: float): + """ + Moves point. + + Args: + delta_r: change in distance from pole + delta_theta: change in angle from polar axis + + Returns: + Nothing. + """ if self.point is not None: self.point = (self.point[0] + delta_r, self.point[1] + delta_theta) else: raise RuntimeError("No point found in model.") def to_bottom(self): + """ + Converts implementation specific model representation to + canonical representation. + + Returns: + Nothing. + """ x = self.point[0]*math.cos(self.point[1]) # x = r * cos(theta) y = self.point[0]*math.sin(self.point[1]) # y = r * sin(theta) bottom = Bottom(self.state) @@ -73,6 +116,13 @@ class PointPolar: bottom.create_edge(c2_link, ltm_point_link, "Morphism") def from_bottom(self): + """ + Converts canonical representation to + implementation specific model representation. + + Returns: + Nothing. + """ bottom = Bottom(self.state) keys = bottom.read_keys(self.model) x_key, = filter(lambda k: k.endswith(".c1"), keys)