tnfr 4.1.0__py3-none-any.whl → 4.5.0__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.

Potentially problematic release.


This version of tnfr might be problematic. Click here for more details.

tnfr/node.py ADDED
@@ -0,0 +1,202 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass, field
3
+ from typing import Deque, Dict, Iterable, List, Optional, Protocol
4
+ from collections import deque
5
+
6
+ from .constants import DEFAULTS
7
+ from .helpers import push_glifo
8
+
9
+
10
+ class NodoProtocol(Protocol):
11
+ """Protocolo mínimo para nodos TNFR."""
12
+
13
+ EPI: float
14
+ vf: float
15
+ theta: float
16
+ Si: float
17
+ epi_kind: str
18
+ dnfr: float
19
+ d2EPI: float
20
+ graph: Dict[str, object]
21
+
22
+ def neighbors(self) -> Iterable["NodoProtocol"]:
23
+ ...
24
+
25
+ def push_glifo(self, glifo: str, window: int) -> None:
26
+ ...
27
+
28
+ def has_edge(self, other: "NodoProtocol") -> bool:
29
+ ...
30
+
31
+ def add_edge(self, other: "NodoProtocol", weight: float) -> None:
32
+ ...
33
+
34
+ def offset(self) -> int:
35
+ ...
36
+
37
+ def all_nodes(self) -> Iterable["NodoProtocol"]:
38
+ ...
39
+
40
+
41
+ @dataclass
42
+ class NodoTNFR:
43
+ """Representa un nodo TNFR autónomo."""
44
+
45
+ EPI: float = 0.0
46
+ vf: float = 0.0
47
+ theta: float = 0.0
48
+ Si: float = 0.0
49
+ epi_kind: str = ""
50
+ dnfr: float = 0.0
51
+ d2EPI: float = 0.0
52
+ graph: Dict[str, object] = field(default_factory=dict)
53
+ _neighbors: List["NodoTNFR"] = field(default_factory=list)
54
+ _hist_glifos: Deque[str] = field(default_factory=lambda: deque(maxlen=DEFAULTS.get("GLYPH_HYSTERESIS_WINDOW", 7)))
55
+
56
+ def neighbors(self) -> Iterable["NodoTNFR"]:
57
+ return list(self._neighbors)
58
+
59
+ def has_edge(self, other: "NodoTNFR") -> bool:
60
+ return other in self._neighbors
61
+
62
+ def add_edge(self, other: "NodoTNFR", weight: float = 1.0) -> None:
63
+ if other not in self._neighbors:
64
+ self._neighbors.append(other)
65
+ other._neighbors.append(self)
66
+
67
+ def push_glifo(self, glifo: str, window: int) -> None:
68
+ self._hist_glifos.append(glifo)
69
+ while len(self._hist_glifos) > window:
70
+ self._hist_glifos.popleft()
71
+ self.epi_kind = glifo
72
+
73
+ def offset(self) -> int:
74
+ return 0
75
+
76
+ def all_nodes(self) -> Iterable["NodoTNFR"]:
77
+ return list(getattr(self.graph, "_all_nodes", [self]))
78
+
79
+ def aplicar_glifo(self, glifo: str, window: Optional[int] = None) -> None:
80
+ from .operators import aplicar_glifo_obj
81
+ aplicar_glifo_obj(self, glifo, window=window)
82
+
83
+ def integrar(self, dt: float) -> None:
84
+ self.EPI += self.dnfr * dt
85
+
86
+
87
+ class NodoNX(NodoProtocol):
88
+ """Adaptador para nodos ``networkx``."""
89
+
90
+ def __init__(self, G, n):
91
+ self.G = G
92
+ self.n = n
93
+ self.graph = G.graph
94
+
95
+ @property
96
+ def EPI(self) -> float:
97
+ from .helpers import _get_attr
98
+ from .constants import ALIAS_EPI
99
+ return float(_get_attr(self.G.nodes[self.n], ALIAS_EPI, 0.0))
100
+
101
+ @EPI.setter
102
+ def EPI(self, v: float) -> None:
103
+ from .helpers import _set_attr
104
+ from .constants import ALIAS_EPI
105
+ _set_attr(self.G.nodes[self.n], ALIAS_EPI, float(v))
106
+
107
+ @property
108
+ def vf(self) -> float:
109
+ from .helpers import _get_attr
110
+ from .constants import ALIAS_VF
111
+ return float(_get_attr(self.G.nodes[self.n], ALIAS_VF, 0.0))
112
+
113
+ @vf.setter
114
+ def vf(self, v: float) -> None:
115
+ from .helpers import _set_attr
116
+ from .constants import ALIAS_VF
117
+ _set_attr(self.G.nodes[self.n], ALIAS_VF, float(v))
118
+
119
+ @property
120
+ def theta(self) -> float:
121
+ from .helpers import _get_attr
122
+ from .constants import ALIAS_THETA
123
+ return float(_get_attr(self.G.nodes[self.n], ALIAS_THETA, 0.0))
124
+
125
+ @theta.setter
126
+ def theta(self, v: float) -> None:
127
+ from .helpers import _set_attr
128
+ from .constants import ALIAS_THETA
129
+ _set_attr(self.G.nodes[self.n], ALIAS_THETA, float(v))
130
+
131
+ @property
132
+ def Si(self) -> float:
133
+ from .helpers import _get_attr
134
+ from .constants import ALIAS_SI
135
+ return float(_get_attr(self.G.nodes[self.n], ALIAS_SI, 0.0))
136
+
137
+ @Si.setter
138
+ def Si(self, v: float) -> None:
139
+ from .helpers import _set_attr
140
+ from .constants import ALIAS_SI
141
+ _set_attr(self.G.nodes[self.n], ALIAS_SI, float(v))
142
+
143
+ @property
144
+ def epi_kind(self) -> str:
145
+ from .helpers import _get_attr_str
146
+ from .constants import ALIAS_EPI_KIND
147
+ return _get_attr_str(self.G.nodes[self.n], ALIAS_EPI_KIND, "")
148
+
149
+ @epi_kind.setter
150
+ def epi_kind(self, v: str) -> None:
151
+ from .helpers import _set_attr_str
152
+ from .constants import ALIAS_EPI_KIND
153
+ _set_attr_str(self.G.nodes[self.n], ALIAS_EPI_KIND, str(v))
154
+
155
+ @property
156
+ def dnfr(self) -> float:
157
+ from .helpers import _get_attr
158
+ from .constants import ALIAS_DNFR
159
+ return float(_get_attr(self.G.nodes[self.n], ALIAS_DNFR, 0.0))
160
+
161
+ @dnfr.setter
162
+ def dnfr(self, v: float) -> None:
163
+ from .helpers import _set_attr
164
+ from .constants import ALIAS_DNFR
165
+ _set_attr(self.G.nodes[self.n], ALIAS_DNFR, float(v))
166
+
167
+ @property
168
+ def d2EPI(self) -> float:
169
+ from .helpers import _get_attr
170
+ from .constants import ALIAS_D2EPI
171
+ return float(_get_attr(self.G.nodes[self.n], ALIAS_D2EPI, 0.0))
172
+
173
+ @d2EPI.setter
174
+ def d2EPI(self, v: float) -> None:
175
+ from .helpers import _set_attr
176
+ from .constants import ALIAS_D2EPI
177
+ _set_attr(self.G.nodes[self.n], ALIAS_D2EPI, float(v))
178
+
179
+ def neighbors(self) -> Iterable[NodoProtocol]:
180
+ return [NodoNX(self.G, v) for v in self.G.neighbors(self.n)]
181
+
182
+ def push_glifo(self, glifo: str, window: int) -> None:
183
+ push_glifo(self.G.nodes[self.n], glifo, window)
184
+ self.epi_kind = glifo
185
+
186
+ def has_edge(self, other: NodoProtocol) -> bool:
187
+ if isinstance(other, NodoNX):
188
+ return self.G.has_edge(self.n, other.n)
189
+ raise NotImplementedError
190
+
191
+ def add_edge(self, other: NodoProtocol, weight: float) -> None:
192
+ if isinstance(other, NodoNX):
193
+ self.G.add_edge(self.n, other.n, weight=float(weight))
194
+ else:
195
+ raise NotImplementedError
196
+
197
+ def offset(self) -> int:
198
+ from .operators import _node_offset
199
+ return _node_offset(self.G, self.n)
200
+
201
+ def all_nodes(self) -> Iterable[NodoProtocol]:
202
+ return [NodoNX(self.G, v) for v in self.G.nodes()]