evonet 0.1.0.dev12__tar.gz → 0.1.0.dev14__tar.gz

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.
Files changed (27) hide show
  1. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/PKG-INFO +1 -1
  2. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/evonet/core.py +7 -6
  3. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/evonet/enums.py +18 -0
  4. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/evonet/mutation.py +38 -11
  5. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/evonet.egg-info/PKG-INFO +1 -1
  6. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/pyproject.toml +1 -1
  7. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/LICENSE +0 -0
  8. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/README.md +0 -0
  9. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/evonet/__init__.py +0 -0
  10. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/evonet/activation.py +0 -0
  11. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/evonet/connection.py +0 -0
  12. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/evonet/core_mit_plot_simple.py +0 -0
  13. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/evonet/io.py +0 -0
  14. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/evonet/layer.py +0 -0
  15. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/evonet/neuron.py +0 -0
  16. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/evonet/serialization.py +0 -0
  17. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/evonet/utils.py +0 -0
  18. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/evonet/visualize.py +0 -0
  19. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/evonet.egg-info/SOURCES.txt +0 -0
  20. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/evonet.egg-info/dependency_links.txt +0 -0
  21. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/evonet.egg-info/requires.txt +0 -0
  22. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/evonet.egg-info/top_level.txt +0 -0
  23. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/setup.cfg +0 -0
  24. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/tests/test_activation.py +0 -0
  25. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/tests/test_core.py +0 -0
  26. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/tests/test_nnet_io_and_forward.py +0 -0
  27. {evonet-0.1.0.dev12 → evonet-0.1.0.dev14}/tests/test_recurrent_dynamics.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: evonet
3
- Version: 0.1.0.dev12
3
+ Version: 0.1.0.dev14
4
4
  Summary: Evolvable neural network core for integration with EvoLib
5
5
  Author-email: EvoLib <evolib@dismail.de>
6
6
  License: MIT License
@@ -102,7 +102,7 @@ class Nnet:
102
102
  label: str = "",
103
103
  role: NeuronRole = NeuronRole.HIDDEN,
104
104
  count: int = 1,
105
- connection_init: Literal["random", "zero", "none"] = "random",
105
+ connection_init: Literal["random", "zero", "near_zero", "none"] = "zero",
106
106
  recurrent: Optional[set[RecurrentKind]] = None,
107
107
  ) -> list[Neuron]:
108
108
  """
@@ -116,9 +116,10 @@ class Nnet:
116
116
  role: Role of the neuron (INPUT, HIDDEN, OUTPUT).
117
117
  count: Number of neurons to add (default: 1).
118
118
  connection_init:
119
- "random" – connect with random weights (feedforward + recurrent)
120
- "zero" – connect with weight 0.0 (feedforward + recurrent)
121
- "none" – do not create connections (feedforward + recurrent)
119
+ "random" - connect with random weights (feedforward + recurrent)
120
+ "zero" - connect with weight 0.0 (feedforward + recurrent)
121
+ "near_zero" – connect with small random weights (-0.05, 0.05)
122
+ "none" - do not create connections (feedforward + recurrent)
122
123
  recurrent: Optional recurrent connection types.
123
124
 
124
125
  Returns:
@@ -230,12 +231,12 @@ class Nnet:
230
231
  Args:
231
232
  source (Neuron): Source neuron.
232
233
  target (Neuron): Target neuron.
233
- weight (float | None): Initial weight. If None, random value is used.
234
+ weight (float | None): Initial weight. If None, 0.0 is used.
234
235
  conn_type (ConnectionType): Type of connection (e.g. standard, recurrent).
235
236
  """
236
237
 
237
238
  if weight is None:
238
- weight = np.random.randn() * 0.5
239
+ weight = 0.0
239
240
 
240
241
  conn = Connection(source, target, weight=weight, conn_type=conn_type)
241
242
  source.outgoing.append(conn)
@@ -48,3 +48,21 @@ class RecurrentKind(str, Enum):
48
48
  DIRECT = "direct" # src == dst
49
49
  LATERAL = "lateral" # same layer, src != dst
50
50
  INDIRECT = "indirect" # src_layer > dst_layer (back edge)
51
+
52
+
53
+ # Neutral activation functions
54
+ # These functions satisfy f(0) ≈ 0 and are safe for zero-weight initialization.
55
+ NEUTRAL_ACTIVATIONS: list[str] = [
56
+ "tanh",
57
+ "relu",
58
+ "relu_max1",
59
+ "leaky_relu",
60
+ "elu",
61
+ "selu",
62
+ "linear",
63
+ "linear_max1",
64
+ "invert",
65
+ "swish",
66
+ "mish",
67
+ "softsign",
68
+ ]
@@ -152,21 +152,44 @@ def mutate_biases(net: Nnet, probability: float = 1.0, std: float = 0.1) -> None
152
152
  def add_random_connection(
153
153
  net: Nnet,
154
154
  allowed_recurrent: Optional[Collection[RecurrentKind | str]] = None,
155
+ connection_init: Literal["zero", "random", "near_zero"] = "zero",
155
156
  ) -> bool:
156
157
  """
157
158
  Add a valid connection between two randomly chosen neurons.
158
159
 
159
160
  Rules:
160
- - disallow connections into INPUT neurons
161
- - disallow duplicate (source, target) pairs
162
- - classify connection type by layer order:
163
- * src_layer < dst_layer -> STANDARD
164
- * src_layer >= dst_layer -> RECURRENT
165
-
166
- Recurrent edges are filtered by allowed_recurrent
167
- (list of 'direct' | 'lateral' | 'indirect').
161
+ - Disallow connections into INPUT neurons.
162
+ - Disallow duplicate (source, target) pairs.
163
+ - Classify connection type by layer order:
164
+ * src_layer < dst_layer -> STANDARD
165
+ * src_layer >= dst_layer -> RECURRENT
166
+ - Recurrent edges are filtered by `allowed_recurrent`
167
+ (list of 'direct' | 'lateral' | 'indirect').
168
+
169
+ Args:
170
+ net (Nnet): Target network to modify.
171
+ allowed_recurrent (Collection[RecurrentKind | str] | None):
172
+ Allowed recurrent connection kinds. Default: None (no recurrent edges).
173
+ connection_init (Literal["zero", "random", "near_zero"]):
174
+ Weight initialization mode for the new connection.
175
+ - "zero": Weight = 0.0 (neutral; ideal with HELI)
176
+ - "random": Weight ~ N(0, 0.5)
177
+ - "near_zero": Weight ~ U(-0.05, 0.05)
178
+
179
+ Returns:
180
+ bool: True if a connection was added, False otherwise.
168
181
  """
169
182
 
183
+ # Weight initialization
184
+ if connection_init == "zero":
185
+ weight = 0.0
186
+ elif connection_init == "random":
187
+ weight = np.random.randn() * 0.5
188
+ elif connection_init == "near_zero":
189
+ weight = np.random.uniform(-0.05, 0.05)
190
+ else:
191
+ raise ValueError(f"Unknown init mode: {connection_init}")
192
+
170
193
  # normalize to set[RecurrentKind]
171
194
  kinds: set[RecurrentKind] = set()
172
195
  if allowed_recurrent:
@@ -223,7 +246,7 @@ def add_random_connection(
223
246
  else ConnectionType.RECURRENT
224
247
  )
225
248
 
226
- net.add_connection(src, dst, conn_type=conn_type)
249
+ net.add_connection(src, dst, weight=weight, conn_type=conn_type)
227
250
  return True
228
251
 
229
252
 
@@ -242,7 +265,11 @@ def remove_random_connection(net: Nnet) -> None:
242
265
  conn.target.incoming.remove(conn)
243
266
 
244
267
 
245
- def add_random_neuron(net: Nnet, activations: list[str] | None = None) -> None:
268
+ def add_random_neuron(
269
+ net: Nnet,
270
+ activations: list[str] | None = None,
271
+ connection_init: Literal["zero", "random", "near_zero", "none"] = "zero",
272
+ ) -> None:
246
273
  """
247
274
  Insert a new hidden neuron into a random layer.
248
275
 
@@ -270,7 +297,7 @@ def add_random_neuron(net: Nnet, activations: list[str] | None = None) -> None:
270
297
  layer_idx=net.layers.index(layer),
271
298
  activation=random_function_name(activations),
272
299
  role=NeuronRole.HIDDEN,
273
- connection_init="random",
300
+ connection_init=connection_init,
274
301
  )
275
302
 
276
303
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: evonet
3
- Version: 0.1.0.dev12
3
+ Version: 0.1.0.dev14
4
4
  Summary: Evolvable neural network core for integration with EvoLib
5
5
  Author-email: EvoLib <evolib@dismail.de>
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "evonet"
7
- version = "0.1.0.dev12"
7
+ version = "0.1.0.dev14"
8
8
  description = "Evolvable neural network core for integration with EvoLib"
9
9
  authors = [
10
10
  { name = "EvoLib", email = "evolib@dismail.de" }
File without changes
File without changes
File without changes
File without changes