natural-agi-common 0.1.33__py3-none-any.whl → 0.1.35__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
common/model/point.py CHANGED
@@ -6,6 +6,8 @@ class Point:
6
6
  id: str
7
7
  x: float
8
8
  y: float
9
+ normalized_x: float
10
+ normalized_y: float
9
11
 
10
12
  @classmethod
11
13
  def from_node_data(cls, node_data: dict) -> "Point":
@@ -13,6 +15,8 @@ class Point:
13
15
  x=node_data["x"],
14
16
  y=node_data["y"],
15
17
  id=node_data["id"],
18
+ normalized_x=node_data["normalized_x"],
19
+ normalized_y=node_data["normalized_y"],
16
20
  )
17
21
 
18
22
  def __hash__(self):
@@ -1,10 +1,18 @@
1
- from typing import Generator, Any, Tuple, Optional
1
+ from typing import Generator, Any, Tuple, Optional, List
2
+ from dataclasses import dataclass
2
3
  import networkx as nx
3
4
  import logging
4
5
  from ..model.point import Point
5
6
  from ..model.vector import Vector
6
7
 
7
8
 
9
+ @dataclass
10
+ class TraversalSequence:
11
+ start_point: Point
12
+ vector: Vector
13
+ end_point: Point
14
+
15
+
8
16
  class GraphTraversal:
9
17
  def __init__(self, graph: nx.Graph):
10
18
  self.graph = graph
@@ -12,38 +20,51 @@ class GraphTraversal:
12
20
 
13
21
  def dfs_traversal(
14
22
  self, start_node: Any
15
- ) -> Generator[Tuple[Point, Optional[Vector]], None, None]:
16
- visited_vector = set()
17
- for edge in nx.dfs_edges(self.graph, start_node):
18
- self.logger.info(f"Visiting edge: {edge}")
19
- source_node, target_node = edge
20
- if source_node in visited_vector or target_node in visited_vector:
21
- self.logger.info(f"Skipping edge: {edge} because vector was already visited")
22
- continue
23
-
24
- # Convert to your Point and Vector objects
25
- source_data = self.graph.nodes[source_node]
26
- target_data = self.graph.nodes[target_node]
27
-
28
- point = None
29
- vector = None
30
-
31
- if self._is_point(source_data):
32
- point = Point.from_node_data(source_data)
33
- elif self._is_vector(source_data):
34
- vector = Vector.from_node_data(source_data)
35
- visited_vector.add(source_node)
36
-
37
- if self._is_point(target_data):
38
- point = Point.from_node_data(target_data)
39
- elif self._is_vector(target_data):
40
- vector = Vector.from_node_data(target_data)
41
- visited_vector.add(target_node)
42
-
43
- if point is None and vector is None:
44
- raise ValueError(f"Invalid node data: {source_data} or {target_data}")
45
-
46
- yield point, vector
23
+ ) -> Generator[TraversalSequence, None, None]:
24
+ visited_vectors = set()
25
+ visited_nodes = set()
26
+
27
+ def dfs_recursive(current_node: Any, path: List[Any]) -> None:
28
+ if current_node in visited_nodes:
29
+ return
30
+
31
+ visited_nodes.add(current_node)
32
+ path.append(current_node)
33
+
34
+ # If we have a sequence of 3 nodes, check if it follows point-vector-point pattern
35
+ if len(path) >= 3:
36
+ start_node_id = path[-3]
37
+ vector_node_id = path[-2]
38
+ end_node_id = path[-1]
39
+
40
+ start_data = self.graph.nodes[start_node_id]
41
+ vector_data = self.graph.nodes[vector_node_id]
42
+ end_data = self.graph.nodes[end_node_id]
43
+
44
+ # Check if sequence follows point-vector-point pattern
45
+ if (
46
+ self._is_point(start_data)
47
+ and self._is_vector(vector_data)
48
+ and self._is_point(end_data)
49
+ and vector_node_id not in visited_vectors
50
+ ):
51
+ self.logger.info(
52
+ f"Found sequence: {start_node_id} -> {vector_node_id} -> {end_node_id}"
53
+ )
54
+ visited_vectors.add(vector_node_id)
55
+
56
+ start_point = Point.from_node_data(start_data)
57
+ vector = Vector.from_node_data(vector_data)
58
+ end_point = Point.from_node_data(end_data)
59
+
60
+ yield TraversalSequence(start_point, vector, end_point)
61
+
62
+ # Continue DFS to neighbors
63
+ for neighbor in self.graph.neighbors(current_node):
64
+ if neighbor not in visited_nodes:
65
+ yield from dfs_recursive(neighbor, path.copy())
66
+
67
+ yield from dfs_recursive(start_node, [])
47
68
 
48
69
  def _is_vector(self, node_data: dict) -> bool:
49
70
  return "Vector" in node_data["labels"]
@@ -29,8 +29,8 @@ class AngleVisitor(Visitor):
29
29
  return {"angles": angles, "point_id": point.id}
30
30
  return None
31
31
 
32
- def visit_line(self, line: Vector) -> Dict[str, Any]:
33
- angle_with_ox = self._calculate_angle_with_ox(line)
32
+ def visit_line(self, line: Vector, start_point: Point) -> Dict[str, Any]:
33
+ angle_with_ox = self._calculate_angle_with_ox(line, start_point)
34
34
  self.line_angles[line.id] = angle_with_ox
35
35
  self.graph.nodes[line.id]["angle_with_ox"] = angle_with_ox
36
36
  return {"angle_with_ox": angle_with_ox, "line_id": line.id}
@@ -159,8 +159,14 @@ class AngleVisitor(Visitor):
159
159
  angle2 = round(angle2 / 10) * 10
160
160
  return [angle1, angle2]
161
161
 
162
- def _calculate_angle_with_ox(self, line: Vector) -> float:
163
- vector = (line.x2 - line.x1, line.y2 - line.y1)
162
+ def _calculate_angle_with_ox(self, line: Vector, start_point: Point) -> float:
163
+ start_coords = (start_point.x, start_point.y)
164
+ end_coords = (
165
+ (line.x2, line.y2)
166
+ if line.x1 == start_point.x and line.y1 == start_point.y
167
+ else (line.x1, line.y1)
168
+ )
169
+ vector = (end_coords[0] - start_coords[0], end_coords[1] - start_coords[1])
164
170
  dot_product = vector[0] * 1 + vector[1] * 0
165
171
  magnitude = math.sqrt(vector[0] ** 2 + vector[1] ** 2)
166
172
  cos_angle = dot_product / magnitude
@@ -53,10 +53,16 @@ class DirectionVisitor(Visitor):
53
53
  # No specific operation for points in this visitor
54
54
  return None
55
55
 
56
- def visit_line(self, line: Vector) -> Dict[str, Any]:
56
+ def visit_line(self, line: Vector, start_point: Point) -> Dict[str, Any]:
57
57
  # Extract direction information
58
+ start_coords = (start_point.x, start_point.y)
59
+ end_coords = (
60
+ (line.x2, line.y2)
61
+ if line.x1 == start_point.x and line.y1 == start_point.y
62
+ else (line.x1, line.y1)
63
+ )
58
64
  h_direction, v_direction = self.calculate_direction(
59
- line.x1, line.y1, line.x2, line.y2
65
+ start_coords[0], start_coords[1], end_coords[0], end_coords[1]
60
66
  )
61
67
  line.horizontal_direction = h_direction
62
68
  line.vertical_direction = v_direction
@@ -2,6 +2,7 @@ from typing import Dict, Any, List
2
2
 
3
3
  from neo4j import ManagedTransaction
4
4
  from .visitor import Visitor
5
+ from ...model.point import Point
5
6
  from ...model.vector import Vector
6
7
  from ...model.length_comparison_result import LengthComparisonResult
7
8
 
@@ -16,7 +17,7 @@ class LengthComparisonVisitor(Visitor):
16
17
  # This visitor does not handle points
17
18
  return None
18
19
 
19
- def visit_line(self, line: Vector) -> Dict[str, Any]:
20
+ def visit_line(self, line: Vector, start_point: Point) -> Dict[str, Any]:
20
21
  comparison = LengthComparisonResult.N_A
21
22
  if self.previous_length:
22
23
  if line.length > self.previous_length:
@@ -13,8 +13,10 @@ class QuadrantVisitor(Visitor):
13
13
  self.quadrants: Dict[str, int] = {}
14
14
 
15
15
  def visit_point(self, point: Point) -> None:
16
- # Implementation for point-related operations
17
- return None
16
+ x = point.normalized_x
17
+ y = point.normalized_y
18
+ quadrant = self.determine_quadrant(x, y)
19
+ self.graph.nodes[point.id]["quadrant"] = quadrant
18
20
 
19
21
  def determine_vector_type(self, dx: float, dy: float) -> str:
20
22
  """Determine vector type based on relative dimensions.
@@ -37,9 +39,15 @@ class QuadrantVisitor(Visitor):
37
39
  else:
38
40
  return "VerticalVector"
39
41
 
40
- def visit_line(self, line: Vector) -> Dict[str, Any]:
41
- dx = line.x2 - line.x1
42
- dy = line.y2 - line.y1
42
+ def visit_line(self, line: Vector, start_point: Point) -> Dict[str, Any]:
43
+ start_coords = (start_point.x, start_point.y)
44
+ end_coords = (
45
+ (line.x2, line.y2)
46
+ if line.x1 == start_point.x and line.y1 == start_point.y
47
+ else (line.x1, line.y1)
48
+ )
49
+ dx = end_coords[0] - start_coords[0]
50
+ dy = end_coords[1] - start_coords[1]
43
51
  quadrant = self.determine_quadrant(dx, dy)
44
52
  vector_type = self.determine_vector_type(dx, dy)
45
53
 
@@ -16,7 +16,7 @@ class Visitor(ABC):
16
16
  pass
17
17
 
18
18
  @abstractmethod
19
- def visit_line(self, line: Vector) -> Any:
19
+ def visit_line(self, line: Vector, start_point: Point) -> Any:
20
20
  pass
21
21
 
22
22
  @abstractmethod
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: natural-agi-common
3
- Version: 0.1.33
3
+ Version: 0.1.35
4
4
  Requires-Dist: pydantic
5
5
  Requires-Dist: networkx
6
6
  Requires-Dist: neo4j
@@ -11,21 +11,21 @@ common/model/dlq.py,sha256=kzHcddbeOkj_YqBghldJOe9CjtO43xxC9Df3Tr5pKD4,111
11
11
  common/model/enums.py,sha256=rTJLjJ1AhLkUYRL8ZQvrMuCt46bZ24_tdGMoTgUjF5w,395
12
12
  common/model/half_plane.py,sha256=AEeY79Uot-mzwe-DgSKn39K-jCJPstXatxT9zN-IUXw,146
13
13
  common/model/length_comparison_result.py,sha256=PEU5QyqpAb9sO0K42cLHILhE_VUMEsNczYhwrFB6UeA,140
14
- common/model/point.py,sha256=nmvKknrimC5iGa6E5y0rKFYQW80H3XxOPeB_6_8rlUg,551
14
+ common/model/point.py,sha256=GlGTfku0K1Wfs4db7kYe6cHXyx8P9TNx0FoKZqfkspA,703
15
15
  common/model/vector.py,sha256=Gnoc-WUU_VCZ-BKO9QLj9a4uzIM81ZW5QZ3yhWpmmSY,651
16
16
  common/traversal/__init__.py,sha256=pkj_5-jsIbDoZbj2DyDePsuqICjuAJ2Rzahw-ezWqJk,149
17
- common/traversal/graph_traversal.py,sha256=BTb522ktmxO92TX9H5yEMdKlaAyS_leI4BZgCFx5a2M,1902
17
+ common/traversal/graph_traversal.py,sha256=F_QBFYPyVckWkxjU-_Jos3WKSSUqaSOg1TbsU27PUPE,2535
18
18
  common/traversal/start_point_selector.py,sha256=saW8G3X3bEiXmZ_aTSCtb8hbquzae4qcaicyvsQ_mVw,4608
19
19
  common/traversal/visitors/__init__.py,sha256=ROshdBY3CJXJ3tV4xdgGv0OBok8cO4LATqroGah8vjY,639
20
- common/traversal/visitors/angle_visitor.py,sha256=2p-by7eQ1SQ4mXkqoVMtLxskBodRzJJpsP4WDKySdvU,6394
21
- common/traversal/visitors/direction_visitor.py,sha256=5WZupy3JOIwrQYMF3-2DujQjq4E1OQifzeGKhC936DM,5673
20
+ common/traversal/visitors/angle_visitor.py,sha256=UX3Hs0xlBBkpGRazH3NasMHy4Xk-LL3kiH8HvGvxF5c,6698
21
+ common/traversal/visitors/direction_visitor.py,sha256=Dn4oPLmhEsL6EpWNC44X2FZU2sIoWMitEiQ5nBty2Po,5944
22
22
  common/traversal/visitors/half_plane_visitor.py,sha256=d1DUVtx4gH-dDhicTjN7lR69xvz2SXKQqaP6kzo3orM,2063
23
- common/traversal/visitors/length_comparison_visitor.py,sha256=gjGzLHtL2IlGgmnggYrcppq293We2DtfU36dNmVZef4,2766
24
- common/traversal/visitors/quadrant_visitor.py,sha256=DXi8DKAsMnV7QkFaAB57DtSOpJJZ2FkDlFrKWArQAXg,3237
23
+ common/traversal/visitors/length_comparison_visitor.py,sha256=hW56siLZodjsNWEFcyg9k0fclJLzT2ArneZCZZLVx9Y,2819
24
+ common/traversal/visitors/quadrant_visitor.py,sha256=N8Vb91FqtRYoQ2G9cK91KAfDaC7u2KbPeQ3sDNqgvcw,3603
25
25
  common/traversal/visitors/relative_position_visitor.py,sha256=3VfJWiuyvC9kc4C9F65LCJ7V4ecmbdz68KMahN2cOxc,7058
26
- common/traversal/visitors/visitor.py,sha256=n2e0mkvD76fqGaegsR48GEBzkbYIY0ZPs9J89ywzqLM,755
26
+ common/traversal/visitors/visitor.py,sha256=30J0GEqzgeQrOng-rjPncXlcLE16WE7sqLlJ7-8SuwU,775
27
27
  common/traversal/visitors/visitor_result_persistence_service.py,sha256=lpr6KzZt22tjTpBnepbTMZ2gi9eLLNrojEv9ABTbvhE,760
28
- natural_agi_common-0.1.33.dist-info/METADATA,sha256=HcW9HJBrCREplquv647JUwHIvVhOCuuQNzScXFGx_Yw,133
29
- natural_agi_common-0.1.33.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
30
- natural_agi_common-0.1.33.dist-info/top_level.txt,sha256=LOtYx8KZTmnxM_zLK4rwrcI3PRc40Ihwp5rgaQ-ceaI,7
31
- natural_agi_common-0.1.33.dist-info/RECORD,,
28
+ natural_agi_common-0.1.35.dist-info/METADATA,sha256=xQD5uBCX4sqV5FmFJEMFBccebMWIuu3xYNbE47gPQbY,133
29
+ natural_agi_common-0.1.35.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
30
+ natural_agi_common-0.1.35.dist-info/top_level.txt,sha256=LOtYx8KZTmnxM_zLK4rwrcI3PRc40Ihwp5rgaQ-ceaI,7
31
+ natural_agi_common-0.1.35.dist-info/RECORD,,