Skip to content

Commit

Permalink
[WIP]
Browse files Browse the repository at this point in the history
  • Loading branch information
agebhar1 committed Sep 26, 2023
1 parent c8b380d commit 4dedad9
Show file tree
Hide file tree
Showing 3 changed files with 897 additions and 4 deletions.
6 changes: 6 additions & 0 deletions graph/planner/direct_acyclic_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ def _topsort(self):
result.reverse()
self._topological_order = result

def has_node(self, node) -> bool:
return node in self._g

def nodes(self) -> set[str]:
return {item[0] for item in self._g.items()}

Expand All @@ -90,6 +93,9 @@ def topological_order(self) -> list[str]:
def inverse(self) -> dict[str, list[AdjacentEdge]]:
return self._g_inverse

def dependent_edge_types(self, node) -> set[EdgeType]:
return {adjacent[1] for adjacent in self._g_inverse[node]}

def childs(
self,
node: str,
Expand Down
121 changes: 120 additions & 1 deletion graph/planner/planner.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
from typing import Union, Tuple, List
from dataclasses import dataclass, field
from typing import Union

from direct_acyclic_graph import DirectAcyclicGraph, EdgeType


@dataclass
class NodeState:
user_selected: bool = True
primary_action: None | str = None
transitive_action: None | str = None
state: set[str] = field(default_factory=set)
transitive_state: set[str] = field(default_factory=set)
dependent_edge_types: set[EdgeType] = field(default_factory=set)


class Planner:
_state: DirectAcyclicGraph
_target: DirectAcyclicGraph
Expand All @@ -24,6 +35,114 @@ def __init__(
self._unhealthy = unhealthy or []
self._selected = selected

def propagate(self) -> tuple[dict[str, NodeState], list[str]]:
nodes_state = self._state.nodes()
nodes_target = self._target.nodes()

nodes_add = (nodes_target - nodes_state).intersection(
(nodes_target - nodes_state)
if self._selected == "*"
else {node for node in self._selected if not node.startswith("-")}
)
nodes_delete = (
(nodes_state - nodes_target)
if self._selected == "*"
else {node[1:] for node in self._selected if node.startswith("-")}
)
nodes_selected = (
nodes_state.union(nodes_target)
if self._selected == "*"
else {
node if not node.startswith("-") else node[1:]
for node in self._selected
}
)

nodes_state = {
node: NodeState(
user_selected=node in nodes_selected,
primary_action=(
"add"
if node in nodes_add
else "delete"
if node in nodes_delete
else None
),
state=({"modified"} if node in self._modified else set()).union(
{"unhealthy"} if node in self._unhealthy else set()
),
dependent_edge_types=(
self._state.dependent_edge_types(node)
if self._state.has_node(node)
else set()
).union(
self._target.dependent_edge_types(node)
if self._target.has_node(node)
else set()
),
)
for node in (nodes_state.union(nodes_target))
}

for node in nodes_delete:
childs_transitive = self._state.childs_transitive(
node,
accept=lambda adjacent: adjacent[1] != EdgeType.TOOL,
)
for node_transitive_delete in childs_transitive:
# if nodes[node_transitive_delete].primary_action != "delete":
nodes_state[node_transitive_delete].transitive_action = "delete"

unhealthy_adjacent_tool_edge_nodes = set()
for key, value in nodes_state.items():
node = key
state = value.state
if "unhealthy" in state:
# propagate 'unhealthy' state to children != EdgeType.TOOL
childs_transitive = self._state.childs_transitive(
node,
accept=lambda adjacent: adjacent[1] != EdgeType.TOOL,
)
for node_transitive_state in childs_transitive:
nodes_state[node_transitive_state].transitive_state = nodes_state[
node_transitive_state
].transitive_state.union({"unhealthy"})

# collect nodes ('unhealthy')' w/ EdgeType.TOOL in reverse graph ~> incoming edge(s)
if EdgeType.TOOL in value.dependent_edge_types:
unhealthy_adjacent_tool_edge_nodes.add(node)

operations = []
nodes_re_add_modified_or_unhealthy = []
if len(unhealthy_adjacent_tool_edge_nodes) > 0:
for node in reversed(self._state.topological_order()):
if node in unhealthy_adjacent_tool_edge_nodes:
operations.append(f"-{node}")
for node in self._state.topological_order():
if node in unhealthy_adjacent_tool_edge_nodes:
operations.append(f"+{node}")

# for node in self._state.topological_order():
# value = nodes_state[node]
#
# if node not in unhealthy_adjacent_tool_edge_nodes:
# modified = "modified" in value.state and value.user_selected
# unhealthy = (
# "unhealthy" in value.state and value.user_selected
# ) or "unhealthy" in value.transitive_state
# if modified or unhealthy:
# operations.append(f"-{node}")
# nodes_re_add_modified_or_unhealthy.append(node)
#
# for node in reversed(self._state.topological_order()):
# value = nodes_state[node]
#
# if node not in unhealthy_adjacent_tool_edge_nodes:
# if node in nodes_re_add_modified_or_unhealthy:
# operations.append(f"+{node}")

return nodes_state, operations

def apply(self) -> list[str]:
nodes_state = self._state.nodes()
nodes_target = self._target.nodes()
Expand Down
Loading

0 comments on commit 4dedad9

Please sign in to comment.