lex-cognitive-plasticity 0.1.0
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.
- checksums.yaml +7 -0
- data/.github/workflows/ci.yml +16 -0
- data/.gitignore +2 -0
- data/.rspec +4 -0
- data/.rubocop.yml +40 -0
- data/CLAUDE.md +107 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +78 -0
- data/README.md +58 -0
- data/lex-cognitive-plasticity.gemspec +31 -0
- data/lib/legion/extensions/cognitive_plasticity/client.rb +11 -0
- data/lib/legion/extensions/cognitive_plasticity/helpers/constants.rb +41 -0
- data/lib/legion/extensions/cognitive_plasticity/helpers/neural_pathway.rb +81 -0
- data/lib/legion/extensions/cognitive_plasticity/helpers/plasticity_engine.rb +126 -0
- data/lib/legion/extensions/cognitive_plasticity/runners/cognitive_plasticity.rb +81 -0
- data/lib/legion/extensions/cognitive_plasticity/version.rb +9 -0
- data/lib/legion/extensions/cognitive_plasticity.rb +15 -0
- metadata +77 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: '016298c044c5cdd55e761d9af284fb994ee3cb4adbdb2e0a8f5050fd8e7d4c14'
|
|
4
|
+
data.tar.gz: 6c1010c7408ceb038e29963d73e158d13d2b6f2bd2b1f8805d67dfa76c7be193
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: b68984844be5a42fea305de489fe52251f74daf4c1df035e220ecd3ed7d1c660f4d57fd8958e5e7b99b89e8a0712a5f0e1ad61c2b1c5e3bff17f0c964b642923
|
|
7
|
+
data.tar.gz: b488f7ae088c2d60db6cabab31e0886394fddc5c7803fceea2b5d2b2bf7808ee8a4e509e08653b0721b8080fc3bf5e53356894044399f5fee445c1c5c3129dfe
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [main]
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
ci:
|
|
9
|
+
uses: LegionIO/.github/.github/workflows/ci.yml@main
|
|
10
|
+
|
|
11
|
+
release:
|
|
12
|
+
needs: ci
|
|
13
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
14
|
+
uses: LegionIO/.github/.github/workflows/release.yml@main
|
|
15
|
+
secrets:
|
|
16
|
+
rubygems-api-key: ${{ secrets.RUBYGEMS_API_KEY }}
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
NewCops: enable
|
|
3
|
+
TargetRubyVersion: 3.4
|
|
4
|
+
|
|
5
|
+
Style/Documentation:
|
|
6
|
+
Enabled: false
|
|
7
|
+
|
|
8
|
+
Naming/PredicateMethod:
|
|
9
|
+
Enabled: false
|
|
10
|
+
|
|
11
|
+
Metrics/ClassLength:
|
|
12
|
+
Max: 150
|
|
13
|
+
|
|
14
|
+
Metrics/MethodLength:
|
|
15
|
+
Max: 25
|
|
16
|
+
|
|
17
|
+
Metrics/AbcSize:
|
|
18
|
+
Max: 25
|
|
19
|
+
|
|
20
|
+
Metrics/ParameterLists:
|
|
21
|
+
Max: 8
|
|
22
|
+
MaxOptionalParameters: 8
|
|
23
|
+
|
|
24
|
+
Layout/HashAlignment:
|
|
25
|
+
EnforcedColonStyle: table
|
|
26
|
+
EnforcedHashRocketStyle: table
|
|
27
|
+
|
|
28
|
+
Metrics/BlockLength:
|
|
29
|
+
Exclude:
|
|
30
|
+
- 'spec/**/*'
|
|
31
|
+
|
|
32
|
+
Style/FrozenStringLiteralComment:
|
|
33
|
+
Enabled: true
|
|
34
|
+
|
|
35
|
+
Style/StringLiterals:
|
|
36
|
+
EnforcedStyle: single_quotes
|
|
37
|
+
|
|
38
|
+
Style/OneClassPerFile:
|
|
39
|
+
Exclude:
|
|
40
|
+
- 'spec/spec_helper.rb'
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# lex-cognitive-plasticity
|
|
2
|
+
|
|
3
|
+
**Level 3 Leaf Documentation**
|
|
4
|
+
- **Parent**: `/Users/miverso2/rubymine/legion/extensions-agentic/CLAUDE.md`
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
|
|
8
|
+
Neural plasticity model for adaptive learning. Neural pathways have strength (how established the connection is) and plasticity (how receptive to change). Strengthening increases strength scaled by both amount and current plasticity; plasticity itself decreases (matures) as a pathway is activated — established pathways become harder to change. Critical period mode applies a 2.5× multiplier to all strengthening, modeling sensitive developmental windows. Weak pathways (below `PRUNING_THRESHOLD = 0.15`) are pruning candidates.
|
|
9
|
+
|
|
10
|
+
## Gem Info
|
|
11
|
+
|
|
12
|
+
- **Gem name**: `lex-cognitive-plasticity`
|
|
13
|
+
- **Module**: `Legion::Extensions::CognitivePlasticity`
|
|
14
|
+
- **Version**: `0.1.0`
|
|
15
|
+
- **Ruby**: `>= 3.4`
|
|
16
|
+
- **License**: MIT
|
|
17
|
+
|
|
18
|
+
## File Structure
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
lib/legion/extensions/cognitive_plasticity/
|
|
22
|
+
version.rb
|
|
23
|
+
client.rb
|
|
24
|
+
helpers/
|
|
25
|
+
constants.rb
|
|
26
|
+
neural_pathway.rb
|
|
27
|
+
plasticity_engine.rb
|
|
28
|
+
runners/
|
|
29
|
+
cognitive_plasticity.rb
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Key Constants
|
|
33
|
+
|
|
34
|
+
| Constant | Value | Purpose |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| `MAX_PATHWAYS` | `300` | Per-engine pathway capacity (auto-prunes weakest on overflow) |
|
|
37
|
+
| `MAX_EVENTS` | `500` | Activation event ring buffer |
|
|
38
|
+
| `DEFAULT_LEARNING_RATE` | `0.5` | Initial plasticity for new pathways |
|
|
39
|
+
| `STRENGTHENING_RATE` | `0.08` | Default amount per strengthen call |
|
|
40
|
+
| `PRUNING_THRESHOLD` | `0.15` | Strength below which pathway is a prune candidate |
|
|
41
|
+
| `CRITICAL_PERIOD_MULTIPLIER` | `2.5` | Strengthening boost during critical period |
|
|
42
|
+
| `MATURATION_RATE` | `0.01` | Plasticity reduction per activation |
|
|
43
|
+
| `PLASTICITY_LABELS` | range hash | From `:crystallized` to `:highly_plastic` |
|
|
44
|
+
| `STRENGTH_LABELS` | range hash | From `:nascent` to `:robust` |
|
|
45
|
+
| `PATHWAY_TYPES` | `%i[synaptic structural functional homeostatic metaplastic]` | Valid pathway types |
|
|
46
|
+
|
|
47
|
+
## Helpers
|
|
48
|
+
|
|
49
|
+
### `Helpers::NeuralPathway`
|
|
50
|
+
Individual pathway. Has `id`, `label`, `pathway_type`, `strength` (0.0–1.0), `plasticity` (0.1–1.0), and `activation_count`.
|
|
51
|
+
|
|
52
|
+
- `strengthen!(amount:, critical_period:)` — effective amount = `amount * multiplier * plasticity`; increments `activation_count`; calls `mature!`
|
|
53
|
+
- `weaken!(amount:)` — effective amount = `amount * plasticity`
|
|
54
|
+
- `prune_candidate?` — `strength < PRUNING_THRESHOLD`
|
|
55
|
+
- `mature!` — reduces plasticity by `MATURATION_RATE` (floor 0.1); called automatically on strengthen
|
|
56
|
+
- `rejuvenate!(amount:)` — increases plasticity (re-opens the pathway to change)
|
|
57
|
+
- `strength_label` / `plasticity_label`
|
|
58
|
+
- `to_h`
|
|
59
|
+
|
|
60
|
+
### `Helpers::PlasticityEngine`
|
|
61
|
+
Multi-pathway manager with critical period state.
|
|
62
|
+
|
|
63
|
+
- `create_pathway(label:, pathway_type:, initial_strength:)` → pathway (auto-prunes weakest if at `MAX_PATHWAYS`)
|
|
64
|
+
- `strengthen_pathway(pathway_id:, amount:)` → updated pathway (applies critical_period from engine state)
|
|
65
|
+
- `weaken_pathway(pathway_id:, amount:)` → updated pathway
|
|
66
|
+
- `rejuvenate_pathway(pathway_id:, amount:)` → updated pathway
|
|
67
|
+
- `enter_critical_period!` / `exit_critical_period!` / `critical_period?` — engine-wide mode flag
|
|
68
|
+
- `prune_weak_pathways!` → count of pruned pathways
|
|
69
|
+
- `pathways_by_type(pathway_type:)` → filtered list
|
|
70
|
+
- `strongest_pathways(limit:)` → top N by strength
|
|
71
|
+
- `weakest_pathways(limit:)` → bottom N by strength
|
|
72
|
+
- `average_strength` / `average_plasticity`
|
|
73
|
+
- `prune_candidates_count`
|
|
74
|
+
- `plasticity_report` → aggregate stats hash
|
|
75
|
+
|
|
76
|
+
## Runners
|
|
77
|
+
|
|
78
|
+
Module: `Runners::CognitivePlasticity`
|
|
79
|
+
|
|
80
|
+
| Runner Method | Description |
|
|
81
|
+
|---|---|
|
|
82
|
+
| `create_pathway(label:, pathway_type:, initial_strength:)` | Register a new pathway |
|
|
83
|
+
| `strengthen_pathway(pathway_id:, amount:)` | Strengthen (respects critical period) |
|
|
84
|
+
| `weaken_pathway(pathway_id:, amount:)` | Weaken a pathway |
|
|
85
|
+
| `rejuvenate_pathway(pathway_id:, amount:)` | Re-open pathway to change |
|
|
86
|
+
| `enter_critical_period` | Enable 2.5× strengthening multiplier |
|
|
87
|
+
| `exit_critical_period` | Disable critical period |
|
|
88
|
+
| `prune_weak_pathways` | Remove prune-candidate pathways |
|
|
89
|
+
| `strongest_pathways(limit:)` | Top N pathways by strength |
|
|
90
|
+
| `plasticity_report` | Aggregate stats |
|
|
91
|
+
|
|
92
|
+
All runners return `{success: true/false, ...}` hashes.
|
|
93
|
+
|
|
94
|
+
## Integration Points
|
|
95
|
+
|
|
96
|
+
- `lex-coldstart` imprint window = critical period: `enter_critical_period` at imprint_window start, `exit_critical_period` at continuous_learning transition
|
|
97
|
+
- `lex-memory`: neural pathways are the underlying substrate for memory trace Hebbian links
|
|
98
|
+
- `lex-tick` dormant phases: `prune_weak_pathways` is a natural dormant maintenance operation
|
|
99
|
+
- `lex-emotion`: high-arousal emotional events can trigger strengthening of associated pathways
|
|
100
|
+
|
|
101
|
+
## Development Notes
|
|
102
|
+
|
|
103
|
+
- `Client` instantiates `@default_engine = Helpers::PlasticityEngine.new` via runner memoization
|
|
104
|
+
- Effective strengthening = `amount * multiplier * plasticity`: a pathway with plasticity = 0.1 only strengthens at 10% efficiency
|
|
105
|
+
- Critical period multiplier (2.5×) is applied by the engine, not the pathway — the engine knows its own state
|
|
106
|
+
- `MAX_PATHWAYS = 300` enforces auto-pruning at creation time: weakest pathway is removed to make room
|
|
107
|
+
- Plasticity floor is 0.1 (not 0.0): pathways never become completely unmodifiable — they just become very resistant to change
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
lex-cognitive-plasticity (0.1.0)
|
|
5
|
+
|
|
6
|
+
GEM
|
|
7
|
+
remote: https://rubygems.org/
|
|
8
|
+
specs:
|
|
9
|
+
addressable (2.8.9)
|
|
10
|
+
public_suffix (>= 2.0.2, < 8.0)
|
|
11
|
+
ast (2.4.3)
|
|
12
|
+
bigdecimal (4.0.1)
|
|
13
|
+
diff-lcs (1.6.2)
|
|
14
|
+
json (2.19.1)
|
|
15
|
+
json-schema (6.2.0)
|
|
16
|
+
addressable (~> 2.8)
|
|
17
|
+
bigdecimal (>= 3.1, < 5)
|
|
18
|
+
language_server-protocol (3.17.0.5)
|
|
19
|
+
lint_roller (1.1.0)
|
|
20
|
+
mcp (0.8.0)
|
|
21
|
+
json-schema (>= 4.1)
|
|
22
|
+
parallel (1.27.0)
|
|
23
|
+
parser (3.3.10.2)
|
|
24
|
+
ast (~> 2.4.1)
|
|
25
|
+
racc
|
|
26
|
+
prism (1.9.0)
|
|
27
|
+
public_suffix (7.0.5)
|
|
28
|
+
racc (1.8.1)
|
|
29
|
+
rainbow (3.1.1)
|
|
30
|
+
regexp_parser (2.11.3)
|
|
31
|
+
rspec (3.13.2)
|
|
32
|
+
rspec-core (~> 3.13.0)
|
|
33
|
+
rspec-expectations (~> 3.13.0)
|
|
34
|
+
rspec-mocks (~> 3.13.0)
|
|
35
|
+
rspec-core (3.13.6)
|
|
36
|
+
rspec-support (~> 3.13.0)
|
|
37
|
+
rspec-expectations (3.13.5)
|
|
38
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
39
|
+
rspec-support (~> 3.13.0)
|
|
40
|
+
rspec-mocks (3.13.8)
|
|
41
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
42
|
+
rspec-support (~> 3.13.0)
|
|
43
|
+
rspec-support (3.13.7)
|
|
44
|
+
rubocop (1.85.1)
|
|
45
|
+
json (~> 2.3)
|
|
46
|
+
language_server-protocol (~> 3.17.0.2)
|
|
47
|
+
lint_roller (~> 1.1.0)
|
|
48
|
+
mcp (~> 0.6)
|
|
49
|
+
parallel (~> 1.10)
|
|
50
|
+
parser (>= 3.3.0.2)
|
|
51
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
52
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
53
|
+
rubocop-ast (>= 1.49.0, < 2.0)
|
|
54
|
+
ruby-progressbar (~> 1.7)
|
|
55
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
56
|
+
rubocop-ast (1.49.1)
|
|
57
|
+
parser (>= 3.3.7.2)
|
|
58
|
+
prism (~> 1.7)
|
|
59
|
+
rubocop-rspec (3.9.0)
|
|
60
|
+
lint_roller (~> 1.1)
|
|
61
|
+
rubocop (~> 1.81)
|
|
62
|
+
ruby-progressbar (1.13.0)
|
|
63
|
+
unicode-display_width (3.2.0)
|
|
64
|
+
unicode-emoji (~> 4.1)
|
|
65
|
+
unicode-emoji (4.2.0)
|
|
66
|
+
|
|
67
|
+
PLATFORMS
|
|
68
|
+
arm64-darwin-25
|
|
69
|
+
ruby
|
|
70
|
+
|
|
71
|
+
DEPENDENCIES
|
|
72
|
+
lex-cognitive-plasticity!
|
|
73
|
+
rspec (~> 3.13)
|
|
74
|
+
rubocop (~> 1.75)
|
|
75
|
+
rubocop-rspec
|
|
76
|
+
|
|
77
|
+
BUNDLED WITH
|
|
78
|
+
2.6.9
|
data/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# lex-cognitive-plasticity
|
|
2
|
+
|
|
3
|
+
Neural plasticity model for LegionIO cognitive agents. Pathways have strength and plasticity; strengthening is scaled by current plasticity, which itself decreases as pathways mature. Critical period mode applies a 2.5× multiplier for accelerated learning.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
- Five pathway types: `synaptic`, `structural`, `functional`, `homeostatic`, `metaplastic`
|
|
8
|
+
- Strength: how established the pathway is (0.0–1.0)
|
|
9
|
+
- Plasticity: how receptive to change (0.1–1.0, decays with each activation)
|
|
10
|
+
- `strengthen_pathway`: effective gain = amount × plasticity (× 2.5 in critical period)
|
|
11
|
+
- `weaken_pathway`: effective reduction = amount × plasticity
|
|
12
|
+
- `rejuvenate_pathway`: re-open a mature pathway to change
|
|
13
|
+
- Critical period: engine-wide 2.5× boost on all strengthening
|
|
14
|
+
- Auto-prune: weakest pathway removed when capacity (300) is reached
|
|
15
|
+
- `prune_weak_pathways`: explicit pruning of pathways below strength threshold (0.15)
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
# Create a pathway
|
|
21
|
+
result = runner.create_pathway(label: 'pattern_recognition_loop',
|
|
22
|
+
pathway_type: :synaptic, initial_strength: 0.3)
|
|
23
|
+
pid = result[:pathway][:id]
|
|
24
|
+
|
|
25
|
+
# Enter critical period (imprint window)
|
|
26
|
+
runner.enter_critical_period
|
|
27
|
+
# => { success: true, critical_period: true }
|
|
28
|
+
|
|
29
|
+
# Strengthen with 2.5× boost
|
|
30
|
+
runner.strengthen_pathway(pathway_id: pid, amount: 0.08)
|
|
31
|
+
# => { success: true, pathway: { strength: 0.40, plasticity: 0.49, activation_count: 1, ... } }
|
|
32
|
+
|
|
33
|
+
# Exit critical period
|
|
34
|
+
runner.exit_critical_period
|
|
35
|
+
|
|
36
|
+
# Rejuvenate a mature pathway to re-open it to change
|
|
37
|
+
runner.rejuvenate_pathway(pathway_id: pid, amount: 0.1)
|
|
38
|
+
|
|
39
|
+
# Prune weak pathways
|
|
40
|
+
runner.prune_weak_pathways
|
|
41
|
+
# => { success: true, pruned_count: 0 }
|
|
42
|
+
|
|
43
|
+
# Report
|
|
44
|
+
runner.plasticity_report
|
|
45
|
+
# => { success: true, report: { total_pathways: 1, critical_period: false, average_strength: 0.4, ... } }
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Development
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
bundle install
|
|
52
|
+
bundle exec rspec
|
|
53
|
+
bundle exec rubocop
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## License
|
|
57
|
+
|
|
58
|
+
MIT
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/legion/extensions/cognitive_plasticity/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'lex-cognitive-plasticity'
|
|
7
|
+
spec.version = Legion::Extensions::CognitivePlasticity::VERSION
|
|
8
|
+
spec.authors = ['Esity']
|
|
9
|
+
spec.email = ['matthewdiverson@gmail.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'Neural plasticity modeling for LegionIO'
|
|
12
|
+
spec.description = 'Models synaptic plasticity with critical periods, pathway strengthening, and pruning'
|
|
13
|
+
spec.homepage = 'https://github.com/LegionIO/lex-cognitive-plasticity'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
|
+
spec.required_ruby_version = '>= 3.4'
|
|
16
|
+
|
|
17
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
18
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
|
19
|
+
spec.metadata['documentation_uri'] = "#{spec.homepage}/blob/main/README.md"
|
|
20
|
+
spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/main/CHANGELOG.md"
|
|
21
|
+
spec.metadata['bug_tracker_uri'] = "#{spec.homepage}/issues"
|
|
22
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
23
|
+
|
|
24
|
+
spec.files = Dir.chdir(__dir__) do
|
|
25
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
26
|
+
f.match(%r{\A(?:test|spec|features)/})
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
spec.require_paths = ['lib']
|
|
30
|
+
spec.add_development_dependency 'legion-gaia'
|
|
31
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitivePlasticity
|
|
6
|
+
module Helpers
|
|
7
|
+
module Constants
|
|
8
|
+
MAX_PATHWAYS = 300
|
|
9
|
+
MAX_EVENTS = 500
|
|
10
|
+
|
|
11
|
+
DEFAULT_LEARNING_RATE = 0.5
|
|
12
|
+
STRENGTHENING_RATE = 0.08
|
|
13
|
+
PRUNING_THRESHOLD = 0.15
|
|
14
|
+
CRITICAL_PERIOD_MULTIPLIER = 2.5
|
|
15
|
+
MATURATION_RATE = 0.01
|
|
16
|
+
|
|
17
|
+
PLASTICITY_LABELS = {
|
|
18
|
+
(0.8..) => :highly_plastic,
|
|
19
|
+
(0.6...0.8) => :plastic,
|
|
20
|
+
(0.4...0.6) => :moderate,
|
|
21
|
+
(0.2...0.4) => :rigid,
|
|
22
|
+
(..0.2) => :crystallized
|
|
23
|
+
}.freeze
|
|
24
|
+
|
|
25
|
+
STRENGTH_LABELS = {
|
|
26
|
+
(0.8..) => :robust,
|
|
27
|
+
(0.6...0.8) => :strong,
|
|
28
|
+
(0.4...0.6) => :moderate,
|
|
29
|
+
(0.2...0.4) => :weak,
|
|
30
|
+
(..0.2) => :nascent
|
|
31
|
+
}.freeze
|
|
32
|
+
|
|
33
|
+
PATHWAY_TYPES = %i[
|
|
34
|
+
synaptic structural functional
|
|
35
|
+
homeostatic metaplastic
|
|
36
|
+
].freeze
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module CognitivePlasticity
|
|
8
|
+
module Helpers
|
|
9
|
+
class NeuralPathway
|
|
10
|
+
include Constants
|
|
11
|
+
|
|
12
|
+
attr_reader :id, :label, :pathway_type, :strength, :plasticity,
|
|
13
|
+
:activation_count, :created_at
|
|
14
|
+
|
|
15
|
+
def initialize(label:, pathway_type: :synaptic, initial_strength: 0.3)
|
|
16
|
+
@id = SecureRandom.uuid
|
|
17
|
+
@label = label
|
|
18
|
+
@pathway_type = pathway_type.to_sym
|
|
19
|
+
@strength = initial_strength.to_f.clamp(0.0, 1.0)
|
|
20
|
+
@plasticity = DEFAULT_LEARNING_RATE
|
|
21
|
+
@activation_count = 0
|
|
22
|
+
@created_at = Time.now.utc
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def strengthen!(amount: STRENGTHENING_RATE, critical_period: false)
|
|
26
|
+
multiplier = critical_period ? CRITICAL_PERIOD_MULTIPLIER : 1.0
|
|
27
|
+
effective = (amount * multiplier * @plasticity).round(10)
|
|
28
|
+
@strength = (@strength + effective).clamp(0.0, 1.0).round(10)
|
|
29
|
+
@activation_count += 1
|
|
30
|
+
mature!
|
|
31
|
+
self
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def weaken!(amount: STRENGTHENING_RATE)
|
|
35
|
+
effective = (amount * @plasticity).round(10)
|
|
36
|
+
@strength = (@strength - effective).clamp(0.0, 1.0).round(10)
|
|
37
|
+
self
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def prune_candidate?
|
|
41
|
+
@strength < PRUNING_THRESHOLD
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def mature!
|
|
45
|
+
@plasticity = (@plasticity - MATURATION_RATE).clamp(0.1, 1.0).round(10)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def rejuvenate!(amount: 0.1)
|
|
49
|
+
@plasticity = (@plasticity + amount).clamp(0.1, 1.0).round(10)
|
|
50
|
+
self
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def strength_label
|
|
54
|
+
match = STRENGTH_LABELS.find { |range, _| range.cover?(@strength) }
|
|
55
|
+
match ? match.last : :nascent
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def plasticity_label
|
|
59
|
+
match = PLASTICITY_LABELS.find { |range, _| range.cover?(@plasticity) }
|
|
60
|
+
match ? match.last : :crystallized
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def to_h
|
|
64
|
+
{
|
|
65
|
+
id: @id,
|
|
66
|
+
label: @label,
|
|
67
|
+
pathway_type: @pathway_type,
|
|
68
|
+
strength: @strength,
|
|
69
|
+
strength_label: strength_label,
|
|
70
|
+
plasticity: @plasticity,
|
|
71
|
+
plasticity_label: plasticity_label,
|
|
72
|
+
activation_count: @activation_count,
|
|
73
|
+
prune_candidate: prune_candidate?,
|
|
74
|
+
created_at: @created_at
|
|
75
|
+
}
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitivePlasticity
|
|
6
|
+
module Helpers
|
|
7
|
+
class PlasticityEngine
|
|
8
|
+
include Constants
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@pathways = {}
|
|
12
|
+
@critical_period = false
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def create_pathway(label:, pathway_type: :synaptic, initial_strength: 0.3)
|
|
16
|
+
prune_if_needed
|
|
17
|
+
pathway = NeuralPathway.new(label: label, pathway_type: pathway_type,
|
|
18
|
+
initial_strength: initial_strength)
|
|
19
|
+
@pathways[pathway.id] = pathway
|
|
20
|
+
pathway
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def strengthen_pathway(pathway_id:, amount: STRENGTHENING_RATE)
|
|
24
|
+
pathway = @pathways[pathway_id]
|
|
25
|
+
return nil unless pathway
|
|
26
|
+
|
|
27
|
+
pathway.strengthen!(amount: amount, critical_period: @critical_period)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def weaken_pathway(pathway_id:, amount: STRENGTHENING_RATE)
|
|
31
|
+
pathway = @pathways[pathway_id]
|
|
32
|
+
return nil unless pathway
|
|
33
|
+
|
|
34
|
+
pathway.weaken!(amount: amount)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def rejuvenate_pathway(pathway_id:, amount: 0.1)
|
|
38
|
+
pathway = @pathways[pathway_id]
|
|
39
|
+
return nil unless pathway
|
|
40
|
+
|
|
41
|
+
pathway.rejuvenate!(amount: amount)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def enter_critical_period!
|
|
45
|
+
@critical_period = true
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def exit_critical_period!
|
|
49
|
+
@critical_period = false
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def critical_period?
|
|
53
|
+
@critical_period
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def prune_weak_pathways!
|
|
57
|
+
candidates = @pathways.values.select(&:prune_candidate?)
|
|
58
|
+
candidates.each { |p| @pathways.delete(p.id) }
|
|
59
|
+
candidates.size
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def pathways_by_type(pathway_type:)
|
|
63
|
+
pt = pathway_type.to_sym
|
|
64
|
+
@pathways.values.select { |p| p.pathway_type == pt }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def strongest_pathways(limit: 5)
|
|
68
|
+
@pathways.values.sort_by { |p| -p.strength }.first(limit)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def weakest_pathways(limit: 5)
|
|
72
|
+
@pathways.values.sort_by(&:strength).first(limit)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def average_strength
|
|
76
|
+
return 0.0 if @pathways.empty?
|
|
77
|
+
|
|
78
|
+
strengths = @pathways.values.map(&:strength)
|
|
79
|
+
(strengths.sum / strengths.size).round(10)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def average_plasticity
|
|
83
|
+
return DEFAULT_LEARNING_RATE if @pathways.empty?
|
|
84
|
+
|
|
85
|
+
plasticities = @pathways.values.map(&:plasticity)
|
|
86
|
+
(plasticities.sum / plasticities.size).round(10)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def prune_candidates_count
|
|
90
|
+
@pathways.values.count(&:prune_candidate?)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def plasticity_report
|
|
94
|
+
{
|
|
95
|
+
total_pathways: @pathways.size,
|
|
96
|
+
critical_period: @critical_period,
|
|
97
|
+
average_strength: average_strength,
|
|
98
|
+
average_plasticity: average_plasticity,
|
|
99
|
+
prune_candidates: prune_candidates_count,
|
|
100
|
+
strongest: strongest_pathways(limit: 3).map(&:to_h)
|
|
101
|
+
}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def to_h
|
|
105
|
+
{
|
|
106
|
+
total_pathways: @pathways.size,
|
|
107
|
+
critical_period: @critical_period,
|
|
108
|
+
average_strength: average_strength,
|
|
109
|
+
average_plasticity: average_plasticity,
|
|
110
|
+
prune_candidates: prune_candidates_count
|
|
111
|
+
}
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
private
|
|
115
|
+
|
|
116
|
+
def prune_if_needed
|
|
117
|
+
return if @pathways.size < MAX_PATHWAYS
|
|
118
|
+
|
|
119
|
+
weakest = @pathways.values.min_by(&:strength)
|
|
120
|
+
@pathways.delete(weakest.id) if weakest
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitivePlasticity
|
|
6
|
+
module Runners
|
|
7
|
+
module CognitivePlasticity
|
|
8
|
+
include Helpers::Constants
|
|
9
|
+
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
|
|
11
|
+
|
|
12
|
+
def create_pathway(label:, engine: nil, pathway_type: :synaptic, initial_strength: 0.3, **)
|
|
13
|
+
eng = engine || default_engine
|
|
14
|
+
pathway = eng.create_pathway(label: label, pathway_type: pathway_type,
|
|
15
|
+
initial_strength: initial_strength)
|
|
16
|
+
{ success: true, pathway: pathway.to_h }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def strengthen_pathway(pathway_id:, engine: nil, amount: STRENGTHENING_RATE, **)
|
|
20
|
+
eng = engine || default_engine
|
|
21
|
+
result = eng.strengthen_pathway(pathway_id: pathway_id, amount: amount)
|
|
22
|
+
return { success: false, error: 'pathway not found' } unless result
|
|
23
|
+
|
|
24
|
+
{ success: true, pathway: result.to_h }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def weaken_pathway(pathway_id:, engine: nil, amount: STRENGTHENING_RATE, **)
|
|
28
|
+
eng = engine || default_engine
|
|
29
|
+
result = eng.weaken_pathway(pathway_id: pathway_id, amount: amount)
|
|
30
|
+
return { success: false, error: 'pathway not found' } unless result
|
|
31
|
+
|
|
32
|
+
{ success: true, pathway: result.to_h }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def rejuvenate_pathway(pathway_id:, engine: nil, amount: 0.1, **)
|
|
36
|
+
eng = engine || default_engine
|
|
37
|
+
result = eng.rejuvenate_pathway(pathway_id: pathway_id, amount: amount)
|
|
38
|
+
return { success: false, error: 'pathway not found' } unless result
|
|
39
|
+
|
|
40
|
+
{ success: true, pathway: result.to_h }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def enter_critical_period(engine: nil, **)
|
|
44
|
+
eng = engine || default_engine
|
|
45
|
+
eng.enter_critical_period!
|
|
46
|
+
{ success: true, critical_period: true }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def exit_critical_period(engine: nil, **)
|
|
50
|
+
eng = engine || default_engine
|
|
51
|
+
eng.exit_critical_period!
|
|
52
|
+
{ success: true, critical_period: false }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def prune_weak_pathways(engine: nil, **)
|
|
56
|
+
eng = engine || default_engine
|
|
57
|
+
pruned = eng.prune_weak_pathways!
|
|
58
|
+
{ success: true, pruned_count: pruned }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def strongest_pathways(engine: nil, limit: 5, **)
|
|
62
|
+
eng = engine || default_engine
|
|
63
|
+
pathways = eng.strongest_pathways(limit: limit).map(&:to_h)
|
|
64
|
+
{ success: true, pathways: pathways, count: pathways.size }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def plasticity_report(engine: nil, **)
|
|
68
|
+
eng = engine || default_engine
|
|
69
|
+
{ success: true, report: eng.plasticity_report }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
def default_engine
|
|
75
|
+
@default_engine ||= Helpers::PlasticityEngine.new
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'cognitive_plasticity/version'
|
|
4
|
+
require_relative 'cognitive_plasticity/helpers/constants'
|
|
5
|
+
require_relative 'cognitive_plasticity/helpers/neural_pathway'
|
|
6
|
+
require_relative 'cognitive_plasticity/helpers/plasticity_engine'
|
|
7
|
+
require_relative 'cognitive_plasticity/runners/cognitive_plasticity'
|
|
8
|
+
require_relative 'cognitive_plasticity/client'
|
|
9
|
+
|
|
10
|
+
module Legion
|
|
11
|
+
module Extensions
|
|
12
|
+
module CognitivePlasticity
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lex-cognitive-plasticity
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Esity
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: legion-gaia
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
description: Models synaptic plasticity with critical periods, pathway strengthening,
|
|
27
|
+
and pruning
|
|
28
|
+
email:
|
|
29
|
+
- matthewdiverson@gmail.com
|
|
30
|
+
executables: []
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- ".github/workflows/ci.yml"
|
|
35
|
+
- ".gitignore"
|
|
36
|
+
- ".rspec"
|
|
37
|
+
- ".rubocop.yml"
|
|
38
|
+
- CLAUDE.md
|
|
39
|
+
- Gemfile
|
|
40
|
+
- Gemfile.lock
|
|
41
|
+
- README.md
|
|
42
|
+
- lex-cognitive-plasticity.gemspec
|
|
43
|
+
- lib/legion/extensions/cognitive_plasticity.rb
|
|
44
|
+
- lib/legion/extensions/cognitive_plasticity/client.rb
|
|
45
|
+
- lib/legion/extensions/cognitive_plasticity/helpers/constants.rb
|
|
46
|
+
- lib/legion/extensions/cognitive_plasticity/helpers/neural_pathway.rb
|
|
47
|
+
- lib/legion/extensions/cognitive_plasticity/helpers/plasticity_engine.rb
|
|
48
|
+
- lib/legion/extensions/cognitive_plasticity/runners/cognitive_plasticity.rb
|
|
49
|
+
- lib/legion/extensions/cognitive_plasticity/version.rb
|
|
50
|
+
homepage: https://github.com/LegionIO/lex-cognitive-plasticity
|
|
51
|
+
licenses:
|
|
52
|
+
- MIT
|
|
53
|
+
metadata:
|
|
54
|
+
homepage_uri: https://github.com/LegionIO/lex-cognitive-plasticity
|
|
55
|
+
source_code_uri: https://github.com/LegionIO/lex-cognitive-plasticity
|
|
56
|
+
documentation_uri: https://github.com/LegionIO/lex-cognitive-plasticity/blob/main/README.md
|
|
57
|
+
changelog_uri: https://github.com/LegionIO/lex-cognitive-plasticity/blob/main/CHANGELOG.md
|
|
58
|
+
bug_tracker_uri: https://github.com/LegionIO/lex-cognitive-plasticity/issues
|
|
59
|
+
rubygems_mfa_required: 'true'
|
|
60
|
+
rdoc_options: []
|
|
61
|
+
require_paths:
|
|
62
|
+
- lib
|
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '3.4'
|
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
69
|
+
requirements:
|
|
70
|
+
- - ">="
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: '0'
|
|
73
|
+
requirements: []
|
|
74
|
+
rubygems_version: 3.6.9
|
|
75
|
+
specification_version: 4
|
|
76
|
+
summary: Neural plasticity modeling for LegionIO
|
|
77
|
+
test_files: []
|