@reicek/neataptic-ts 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.
Files changed (272) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +27 -0
  3. package/.github/PULL_REQUEST_TEMPLATE.md +28 -0
  4. package/.github/workflows/ci.yml +41 -0
  5. package/.github/workflows/deploy-pages.yml +29 -0
  6. package/.github/workflows/manual_release_pipeline.yml +62 -0
  7. package/.github/workflows/publish.yml +85 -0
  8. package/.github/workflows/release_dispatch.yml +38 -0
  9. package/.travis.yml +5 -0
  10. package/CONTRIBUTING.md +92 -0
  11. package/LICENSE +24 -0
  12. package/ONNX_EXPORT.md +87 -0
  13. package/README.md +1173 -0
  14. package/RELEASE.md +54 -0
  15. package/dist-docs/package.json +1 -0
  16. package/dist-docs/scripts/generate-docs.d.ts +2 -0
  17. package/dist-docs/scripts/generate-docs.d.ts.map +1 -0
  18. package/dist-docs/scripts/generate-docs.js +536 -0
  19. package/dist-docs/scripts/generate-docs.js.map +1 -0
  20. package/dist-docs/scripts/render-docs-html.d.ts +2 -0
  21. package/dist-docs/scripts/render-docs-html.d.ts.map +1 -0
  22. package/dist-docs/scripts/render-docs-html.js +148 -0
  23. package/dist-docs/scripts/render-docs-html.js.map +1 -0
  24. package/docs/FOLDERS.md +14 -0
  25. package/docs/README.md +1173 -0
  26. package/docs/architecture/README.md +1391 -0
  27. package/docs/architecture/index.html +938 -0
  28. package/docs/architecture/network/README.md +1210 -0
  29. package/docs/architecture/network/index.html +908 -0
  30. package/docs/assets/ascii-maze.bundle.js +16542 -0
  31. package/docs/assets/ascii-maze.bundle.js.map +7 -0
  32. package/docs/index.html +1419 -0
  33. package/docs/methods/README.md +670 -0
  34. package/docs/methods/index.html +477 -0
  35. package/docs/multithreading/README.md +274 -0
  36. package/docs/multithreading/index.html +215 -0
  37. package/docs/multithreading/workers/README.md +23 -0
  38. package/docs/multithreading/workers/browser/README.md +39 -0
  39. package/docs/multithreading/workers/browser/index.html +70 -0
  40. package/docs/multithreading/workers/index.html +57 -0
  41. package/docs/multithreading/workers/node/README.md +33 -0
  42. package/docs/multithreading/workers/node/index.html +66 -0
  43. package/docs/neat/README.md +1284 -0
  44. package/docs/neat/index.html +906 -0
  45. package/docs/src/README.md +2659 -0
  46. package/docs/src/index.html +1579 -0
  47. package/jest.config.ts +32 -0
  48. package/package.json +99 -0
  49. package/plans/HyperMorphoNEAT.md +293 -0
  50. package/plans/ONNX_EXPORT_PLAN.md +46 -0
  51. package/scripts/generate-docs.ts +486 -0
  52. package/scripts/render-docs-html.ts +138 -0
  53. package/scripts/types.d.ts +2 -0
  54. package/src/README.md +2659 -0
  55. package/src/architecture/README.md +1391 -0
  56. package/src/architecture/activationArrayPool.ts +135 -0
  57. package/src/architecture/architect.ts +635 -0
  58. package/src/architecture/connection.ts +148 -0
  59. package/src/architecture/group.ts +406 -0
  60. package/src/architecture/layer.ts +804 -0
  61. package/src/architecture/network/README.md +1210 -0
  62. package/src/architecture/network/network.activate.ts +223 -0
  63. package/src/architecture/network/network.connect.ts +157 -0
  64. package/src/architecture/network/network.deterministic.ts +167 -0
  65. package/src/architecture/network/network.evolve.ts +426 -0
  66. package/src/architecture/network/network.gating.ts +186 -0
  67. package/src/architecture/network/network.genetic.ts +247 -0
  68. package/src/architecture/network/network.mutate.ts +624 -0
  69. package/src/architecture/network/network.onnx.ts +463 -0
  70. package/src/architecture/network/network.prune.ts +216 -0
  71. package/src/architecture/network/network.remove.ts +96 -0
  72. package/src/architecture/network/network.serialize.ts +309 -0
  73. package/src/architecture/network/network.slab.ts +262 -0
  74. package/src/architecture/network/network.standalone.ts +246 -0
  75. package/src/architecture/network/network.stats.ts +59 -0
  76. package/src/architecture/network/network.topology.ts +86 -0
  77. package/src/architecture/network/network.training.ts +1278 -0
  78. package/src/architecture/network.ts +1302 -0
  79. package/src/architecture/node.ts +1288 -0
  80. package/src/architecture/onnx.ts +3 -0
  81. package/src/config.ts +83 -0
  82. package/src/methods/README.md +670 -0
  83. package/src/methods/activation.ts +372 -0
  84. package/src/methods/connection.ts +31 -0
  85. package/src/methods/cost.ts +347 -0
  86. package/src/methods/crossover.ts +63 -0
  87. package/src/methods/gating.ts +43 -0
  88. package/src/methods/methods.ts +8 -0
  89. package/src/methods/mutation.ts +300 -0
  90. package/src/methods/rate.ts +257 -0
  91. package/src/methods/selection.ts +65 -0
  92. package/src/multithreading/README.md +274 -0
  93. package/src/multithreading/multi.ts +339 -0
  94. package/src/multithreading/workers/README.md +23 -0
  95. package/src/multithreading/workers/browser/README.md +39 -0
  96. package/src/multithreading/workers/browser/testworker.ts +99 -0
  97. package/src/multithreading/workers/node/README.md +33 -0
  98. package/src/multithreading/workers/node/testworker.ts +72 -0
  99. package/src/multithreading/workers/node/worker.ts +70 -0
  100. package/src/multithreading/workers/workers.ts +22 -0
  101. package/src/neat/README.md +1284 -0
  102. package/src/neat/neat.adaptive.ts +544 -0
  103. package/src/neat/neat.compat.ts +164 -0
  104. package/src/neat/neat.constants.ts +20 -0
  105. package/src/neat/neat.diversity.ts +217 -0
  106. package/src/neat/neat.evaluate.ts +328 -0
  107. package/src/neat/neat.evolve.ts +1026 -0
  108. package/src/neat/neat.export.ts +249 -0
  109. package/src/neat/neat.helpers.ts +235 -0
  110. package/src/neat/neat.lineage.ts +220 -0
  111. package/src/neat/neat.multiobjective.ts +260 -0
  112. package/src/neat/neat.mutation.ts +718 -0
  113. package/src/neat/neat.objectives.ts +157 -0
  114. package/src/neat/neat.pruning.ts +190 -0
  115. package/src/neat/neat.selection.ts +269 -0
  116. package/src/neat/neat.speciation.ts +460 -0
  117. package/src/neat/neat.species.ts +151 -0
  118. package/src/neat/neat.telemetry.exports.ts +469 -0
  119. package/src/neat/neat.telemetry.ts +933 -0
  120. package/src/neat/neat.types.ts +275 -0
  121. package/src/neat.ts +1042 -0
  122. package/src/neataptic.ts +10 -0
  123. package/test/architecture/activationArrayPool.capacity.test.ts +19 -0
  124. package/test/architecture/activationArrayPool.test.ts +46 -0
  125. package/test/architecture/connection.test.ts +290 -0
  126. package/test/architecture/group.test.ts +950 -0
  127. package/test/architecture/layer.test.ts +1535 -0
  128. package/test/architecture/network.pruning.test.ts +65 -0
  129. package/test/architecture/node.test.ts +1602 -0
  130. package/test/examples/asciiMaze/asciiMaze.e2e.test.ts +499 -0
  131. package/test/examples/asciiMaze/asciiMaze.ts +41 -0
  132. package/test/examples/asciiMaze/browser-entry.ts +164 -0
  133. package/test/examples/asciiMaze/browserLogger.ts +221 -0
  134. package/test/examples/asciiMaze/browserTerminalUtility.ts +48 -0
  135. package/test/examples/asciiMaze/colors.ts +119 -0
  136. package/test/examples/asciiMaze/dashboardManager.ts +968 -0
  137. package/test/examples/asciiMaze/evolutionEngine.ts +1248 -0
  138. package/test/examples/asciiMaze/fitness.ts +136 -0
  139. package/test/examples/asciiMaze/index.html +128 -0
  140. package/test/examples/asciiMaze/index.ts +26 -0
  141. package/test/examples/asciiMaze/interfaces.ts +235 -0
  142. package/test/examples/asciiMaze/mazeMovement.ts +996 -0
  143. package/test/examples/asciiMaze/mazeUtils.ts +278 -0
  144. package/test/examples/asciiMaze/mazeVision.ts +402 -0
  145. package/test/examples/asciiMaze/mazeVisualization.ts +585 -0
  146. package/test/examples/asciiMaze/mazes.ts +245 -0
  147. package/test/examples/asciiMaze/networkRefinement.ts +76 -0
  148. package/test/examples/asciiMaze/networkVisualization.ts +901 -0
  149. package/test/examples/asciiMaze/terminalUtility.ts +73 -0
  150. package/test/methods/activation.test.ts +1142 -0
  151. package/test/methods/connection.test.ts +146 -0
  152. package/test/methods/cost.test.ts +1123 -0
  153. package/test/methods/crossover.test.ts +202 -0
  154. package/test/methods/gating.test.ts +144 -0
  155. package/test/methods/mutation.test.ts +451 -0
  156. package/test/methods/optimizers.advanced.test.ts +80 -0
  157. package/test/methods/optimizers.behavior.test.ts +105 -0
  158. package/test/methods/optimizers.formula.test.ts +89 -0
  159. package/test/methods/rate.cosineWarmRestarts.test.ts +44 -0
  160. package/test/methods/rate.linearWarmupDecay.test.ts +41 -0
  161. package/test/methods/rate.reduceOnPlateau.test.ts +45 -0
  162. package/test/methods/rate.test.ts +684 -0
  163. package/test/methods/selection.test.ts +245 -0
  164. package/test/multithreading/activations.functions.test.ts +54 -0
  165. package/test/multithreading/multi.test.ts +290 -0
  166. package/test/multithreading/worker.node.process.test.ts +39 -0
  167. package/test/multithreading/workers.coverage.test.ts +36 -0
  168. package/test/multithreading/workers.dynamic.import.test.ts +8 -0
  169. package/test/neat/neat.adaptive.complexityBudget.test.ts +34 -0
  170. package/test/neat/neat.adaptive.criterion.complexity.test.ts +50 -0
  171. package/test/neat/neat.adaptive.mutation.strategy.test.ts +37 -0
  172. package/test/neat/neat.adaptive.operator.decay.test.ts +31 -0
  173. package/test/neat/neat.adaptive.phasedComplexity.test.ts +25 -0
  174. package/test/neat/neat.adaptive.pruning.test.ts +25 -0
  175. package/test/neat/neat.adaptive.targetSpecies.test.ts +43 -0
  176. package/test/neat/neat.additional.coverage.test.ts +126 -0
  177. package/test/neat/neat.advanced.enhancements.test.ts +85 -0
  178. package/test/neat/neat.advanced.test.ts +589 -0
  179. package/test/neat/neat.diversity.autocompat.test.ts +47 -0
  180. package/test/neat/neat.diversity.metrics.test.ts +21 -0
  181. package/test/neat/neat.diversity.stats.test.ts +44 -0
  182. package/test/neat/neat.enhancements.test.ts +79 -0
  183. package/test/neat/neat.entropy.ancestorAdaptive.test.ts +133 -0
  184. package/test/neat/neat.entropy.compat.csv.test.ts +108 -0
  185. package/test/neat/neat.evolution.pruning.test.ts +39 -0
  186. package/test/neat/neat.fastmode.autotune.test.ts +42 -0
  187. package/test/neat/neat.innovation.test.ts +134 -0
  188. package/test/neat/neat.lineage.antibreeding.test.ts +35 -0
  189. package/test/neat/neat.lineage.entropy.test.ts +56 -0
  190. package/test/neat/neat.lineage.inbreeding.test.ts +49 -0
  191. package/test/neat/neat.lineage.pressure.test.ts +29 -0
  192. package/test/neat/neat.multiobjective.adaptive.test.ts +57 -0
  193. package/test/neat/neat.multiobjective.dynamic.schedule.test.ts +46 -0
  194. package/test/neat/neat.multiobjective.dynamic.test.ts +31 -0
  195. package/test/neat/neat.multiobjective.fastsort.delegation.test.ts +51 -0
  196. package/test/neat/neat.multiobjective.prune.test.ts +39 -0
  197. package/test/neat/neat.multiobjective.test.ts +21 -0
  198. package/test/neat/neat.mutation.undefined.pool.test.ts +24 -0
  199. package/test/neat/neat.objective.events.test.ts +26 -0
  200. package/test/neat/neat.objective.importance.test.ts +21 -0
  201. package/test/neat/neat.objective.lifetimes.test.ts +33 -0
  202. package/test/neat/neat.offspring.allocation.test.ts +22 -0
  203. package/test/neat/neat.operator.bandit.test.ts +17 -0
  204. package/test/neat/neat.operator.phases.test.ts +38 -0
  205. package/test/neat/neat.pruneInactive.behavior.test.ts +54 -0
  206. package/test/neat/neat.reenable.adaptation.test.ts +18 -0
  207. package/test/neat/neat.rng.state.test.ts +22 -0
  208. package/test/neat/neat.spawn.add.test.ts +123 -0
  209. package/test/neat/neat.speciation.test.ts +96 -0
  210. package/test/neat/neat.species.allocation.telemetry.test.ts +26 -0
  211. package/test/neat/neat.species.history.csv.test.ts +24 -0
  212. package/test/neat/neat.telemetry.advanced.test.ts +226 -0
  213. package/test/neat/neat.telemetry.csv.lineage.test.ts +19 -0
  214. package/test/neat/neat.telemetry.parity.test.ts +42 -0
  215. package/test/neat/neat.telemetry.stream.test.ts +19 -0
  216. package/test/neat/neat.telemetry.test.ts +16 -0
  217. package/test/neat/neat.test.ts +422 -0
  218. package/test/neat/neat.utilities.test.ts +44 -0
  219. package/test/network/__suppress_console.ts +9 -0
  220. package/test/network/acyclic.topoorder.test.ts +17 -0
  221. package/test/network/checkpoint.metricshook.test.ts +36 -0
  222. package/test/network/error.handling.test.ts +581 -0
  223. package/test/network/evolution.test.ts +285 -0
  224. package/test/network/genetic.test.ts +208 -0
  225. package/test/network/learning.capability.test.ts +244 -0
  226. package/test/network/mutation.effects.test.ts +492 -0
  227. package/test/network/network.activate.test.ts +115 -0
  228. package/test/network/network.activateBatch.test.ts +30 -0
  229. package/test/network/network.deterministic.test.ts +64 -0
  230. package/test/network/network.evolve.branches.test.ts +75 -0
  231. package/test/network/network.evolve.multithread.branches.test.ts +83 -0
  232. package/test/network/network.evolve.test.ts +100 -0
  233. package/test/network/network.gating.removal.test.ts +93 -0
  234. package/test/network/network.mutate.additional.test.ts +145 -0
  235. package/test/network/network.mutate.edgecases.test.ts +101 -0
  236. package/test/network/network.mutate.test.ts +101 -0
  237. package/test/network/network.prune.earlyexit.test.ts +38 -0
  238. package/test/network/network.remove.errors.test.ts +45 -0
  239. package/test/network/network.slab.fallbacks.test.ts +22 -0
  240. package/test/network/network.stats.test.ts +45 -0
  241. package/test/network/network.training.advanced.test.ts +149 -0
  242. package/test/network/network.training.basic.test.ts +228 -0
  243. package/test/network/network.training.helpers.test.ts +183 -0
  244. package/test/network/onnx.export.test.ts +310 -0
  245. package/test/network/onnx.import.test.ts +129 -0
  246. package/test/network/pruning.topology.test.ts +282 -0
  247. package/test/network/regularization.determinism.test.ts +83 -0
  248. package/test/network/regularization.dropconnect.test.ts +17 -0
  249. package/test/network/regularization.dropconnect.validation.test.ts +18 -0
  250. package/test/network/regularization.stochasticdepth.test.ts +27 -0
  251. package/test/network/regularization.test.ts +843 -0
  252. package/test/network/regularization.weightnoise.test.ts +30 -0
  253. package/test/network/setupTests.ts +2 -0
  254. package/test/network/standalone.test.ts +332 -0
  255. package/test/network/structure.serialization.test.ts +660 -0
  256. package/test/training/training.determinism.mixed-precision.test.ts +134 -0
  257. package/test/training/training.earlystopping.test.ts +91 -0
  258. package/test/training/training.edge-cases.test.ts +91 -0
  259. package/test/training/training.extensions.test.ts +47 -0
  260. package/test/training/training.gradient.features.test.ts +110 -0
  261. package/test/training/training.gradient.refinements.test.ts +170 -0
  262. package/test/training/training.gradient.separate-bias.test.ts +41 -0
  263. package/test/training/training.optimizer.test.ts +48 -0
  264. package/test/training/training.plateau.smoothing.test.ts +58 -0
  265. package/test/training/training.smoothing.types.test.ts +174 -0
  266. package/test/training/training.train.options.coverage.test.ts +52 -0
  267. package/test/utils/console-helper.ts +76 -0
  268. package/test/utils/jest-setup.ts +60 -0
  269. package/test/utils/test-helpers.ts +175 -0
  270. package/tsconfig.docs.json +12 -0
  271. package/tsconfig.json +21 -0
  272. package/webpack.config.js +49 -0
@@ -0,0 +1,684 @@
1
+ import Rate from '../../src/methods/rate';
2
+
3
+ describe('Rate', () => {
4
+ const baseRate = 0.1;
5
+
6
+ describe('fixed()', () => {
7
+ const fixedRateFn = Rate.fixed();
8
+
9
+ describe('Scenario: At iteration 0', () => {
10
+ it('should return the base rate', () => {
11
+ // Act
12
+ const rate = fixedRateFn(baseRate, 0);
13
+ // Assert
14
+ expect(rate).toBe(baseRate);
15
+ });
16
+ it('should be non-negative', () => {
17
+ // Act
18
+ const rate = fixedRateFn(baseRate, 0);
19
+ // Assert
20
+ expect(rate).toBeGreaterThanOrEqual(0);
21
+ });
22
+ });
23
+
24
+ describe('Scenario: At iteration 100', () => {
25
+ it('should return the base rate', () => {
26
+ // Act
27
+ const rate = fixedRateFn(baseRate, 100);
28
+ // Assert
29
+ expect(rate).toBe(baseRate);
30
+ });
31
+ it('should be non-negative', () => {
32
+ // Act
33
+ const rate = fixedRateFn(baseRate, 100);
34
+ // Assert
35
+ expect(rate).toBeGreaterThanOrEqual(0);
36
+ });
37
+ });
38
+ });
39
+
40
+ describe('step()', () => {
41
+ const gamma = 0.9;
42
+ const stepSize = 10;
43
+ const stepRateFnCustom = Rate.step(gamma, stepSize);
44
+ const stepRateFnDefault = Rate.step();
45
+
46
+ describe('Custom parameters', () => {
47
+ it('should return the base rate before the first step', () => {
48
+ // Act
49
+ const rate = stepRateFnCustom(baseRate, 9);
50
+ // Assert
51
+ expect(rate).toBe(baseRate);
52
+ });
53
+ it('should be non-negative before the first step', () => {
54
+ // Act
55
+ const rate = stepRateFnCustom(baseRate, 9);
56
+ // Assert
57
+ expect(rate).toBeGreaterThanOrEqual(0);
58
+ });
59
+ it('should return the decayed rate at the first step', () => {
60
+ // Act
61
+ const rate = stepRateFnCustom(baseRate, 10);
62
+ // Assert
63
+ expect(rate).toBeCloseTo(baseRate * Math.pow(gamma, 1));
64
+ });
65
+ it('should be non-negative at the first step', () => {
66
+ // Act
67
+ const rate = stepRateFnCustom(baseRate, 10);
68
+ // Assert
69
+ expect(rate).toBeGreaterThanOrEqual(0);
70
+ });
71
+ it('should be less than or equal to baseRate at the first step', () => {
72
+ // Act
73
+ const rate = stepRateFnCustom(baseRate, 10);
74
+ // Assert
75
+ expect(rate).toBeLessThanOrEqual(baseRate);
76
+ });
77
+ it('should return the decayed rate after multiple steps', () => {
78
+ // Act
79
+ const rate = stepRateFnCustom(baseRate, 25);
80
+ // Assert
81
+ expect(rate).toBeCloseTo(baseRate * Math.pow(gamma, 2));
82
+ });
83
+ it('should be non-negative after multiple steps', () => {
84
+ // Act
85
+ const rate = stepRateFnCustom(baseRate, 25);
86
+ // Assert
87
+ expect(rate).toBeGreaterThanOrEqual(0);
88
+ });
89
+ it('should be less than or equal to baseRate after multiple steps', () => {
90
+ // Act
91
+ const rate = stepRateFnCustom(baseRate, 25);
92
+ // Assert
93
+ expect(rate).toBeLessThanOrEqual(baseRate);
94
+ });
95
+ });
96
+
97
+ describe('Default parameters', () => {
98
+ it('should return the base rate before the first step', () => {
99
+ // Act
100
+ const rate = stepRateFnDefault(baseRate, 99);
101
+ // Assert
102
+ expect(rate).toBe(baseRate);
103
+ });
104
+ it('should be non-negative before the first step', () => {
105
+ // Act
106
+ const rate = stepRateFnDefault(baseRate, 99);
107
+ // Assert
108
+ expect(rate).toBeGreaterThanOrEqual(0);
109
+ });
110
+ it('should return the decayed rate at the first step', () => {
111
+ // Act
112
+ const rate = stepRateFnDefault(baseRate, 100);
113
+ // Assert
114
+ expect(rate).toBeCloseTo(baseRate * Math.pow(0.9, 1));
115
+ });
116
+ it('should be non-negative at the first step', () => {
117
+ // Act
118
+ const rate = stepRateFnDefault(baseRate, 100);
119
+ // Assert
120
+ expect(rate).toBeGreaterThanOrEqual(0);
121
+ });
122
+ it('should be less than or equal to baseRate at the first step', () => {
123
+ // Act
124
+ const rate = stepRateFnDefault(baseRate, 100);
125
+ // Assert
126
+ expect(rate).toBeLessThanOrEqual(baseRate);
127
+ });
128
+ });
129
+ });
130
+
131
+ describe('exp()', () => {
132
+ const gamma = 0.95;
133
+ const expRateFnCustom = Rate.exp(gamma);
134
+ const expRateFnDefault = Rate.exp();
135
+
136
+ describe('Custom gamma', () => {
137
+ it('should return the base rate at iteration 0', () => {
138
+ // Act
139
+ const rate = expRateFnCustom(baseRate, 0);
140
+ // Assert
141
+ expect(rate).toBe(baseRate);
142
+ });
143
+ it('should be non-negative at iteration 0', () => {
144
+ // Act
145
+ const rate = expRateFnCustom(baseRate, 0);
146
+ // Assert
147
+ expect(rate).toBeGreaterThanOrEqual(0);
148
+ });
149
+ it('should return the decayed rate at iteration 1', () => {
150
+ // Act
151
+ const rate = expRateFnCustom(baseRate, 1);
152
+ // Assert
153
+ expect(rate).toBeCloseTo(baseRate * Math.pow(gamma, 1));
154
+ });
155
+ it('should be non-negative at iteration 1', () => {
156
+ // Act
157
+ const rate = expRateFnCustom(baseRate, 1);
158
+ // Assert
159
+ expect(rate).toBeGreaterThanOrEqual(0);
160
+ });
161
+ it('should be less than or equal to baseRate at iteration 1', () => {
162
+ // Act
163
+ const rate = expRateFnCustom(baseRate, 1);
164
+ // Assert
165
+ expect(rate).toBeLessThanOrEqual(baseRate);
166
+ });
167
+ it('should return the decayed rate at iteration 10', () => {
168
+ // Act
169
+ const rate = expRateFnCustom(baseRate, 10);
170
+ // Assert
171
+ expect(rate).toBeCloseTo(baseRate * Math.pow(gamma, 10));
172
+ });
173
+ it('should be non-negative at iteration 10', () => {
174
+ // Act
175
+ const rate = expRateFnCustom(baseRate, 10);
176
+ // Assert
177
+ expect(rate).toBeGreaterThanOrEqual(0);
178
+ });
179
+ it('should be less than or equal to baseRate at iteration 10', () => {
180
+ // Act
181
+ const rate = expRateFnCustom(baseRate, 10);
182
+ // Assert
183
+ expect(rate).toBeLessThanOrEqual(baseRate);
184
+ });
185
+ });
186
+
187
+ describe('Default gamma', () => {
188
+ it('should return the base rate at iteration 0', () => {
189
+ // Act
190
+ const rate = expRateFnDefault(baseRate, 0);
191
+ // Assert
192
+ expect(rate).toBe(baseRate);
193
+ });
194
+ it('should be non-negative at iteration 0', () => {
195
+ // Act
196
+ const rate = expRateFnDefault(baseRate, 0);
197
+ // Assert
198
+ expect(rate).toBeGreaterThanOrEqual(0);
199
+ });
200
+ it('should return the decayed rate at iteration 10', () => {
201
+ // Act
202
+ const rate = expRateFnDefault(baseRate, 10);
203
+ // Assert
204
+ expect(rate).toBeCloseTo(baseRate * Math.pow(0.999, 10));
205
+ });
206
+ it('should be non-negative at iteration 10', () => {
207
+ // Act
208
+ const rate = expRateFnDefault(baseRate, 10);
209
+ // Assert
210
+ expect(rate).toBeGreaterThanOrEqual(0);
211
+ });
212
+ it('should be less than or equal to baseRate at iteration 10', () => {
213
+ // Act
214
+ const rate = expRateFnDefault(baseRate, 10);
215
+ // Assert
216
+ expect(rate).toBeLessThanOrEqual(baseRate);
217
+ });
218
+ });
219
+ });
220
+
221
+ describe('inv()', () => {
222
+ const gamma = 0.01;
223
+ const power = 1.5;
224
+ const invRateFnCustom = Rate.inv(gamma, power);
225
+ const invRateFnDefault = Rate.inv();
226
+
227
+ describe('Custom parameters', () => {
228
+ it('should return the base rate at iteration 0', () => {
229
+ // Act
230
+ const rate = invRateFnCustom(baseRate, 0);
231
+ // Assert
232
+ expect(rate).toBeCloseTo(baseRate, 5);
233
+ });
234
+
235
+ it('should be non-negative at iteration 0', () => {
236
+ // Act
237
+ const rate = invRateFnCustom(baseRate, 0);
238
+ // Assert
239
+ expect(rate).toBeGreaterThanOrEqual(0);
240
+ });
241
+
242
+ it('should return the decayed rate at iteration 1', () => {
243
+ // Act
244
+ const rate = invRateFnCustom(baseRate, 1);
245
+ const expected = baseRate / (1 + gamma * Math.pow(1, power));
246
+ // Assert
247
+ expect(rate).toBeCloseTo(expected, 5);
248
+ });
249
+
250
+ it('should be non-negative at iteration 1', () => {
251
+ // Act
252
+ const rate = invRateFnCustom(baseRate, 1);
253
+ // Assert
254
+ expect(rate).toBeGreaterThanOrEqual(0);
255
+ });
256
+
257
+ it('should be less than or equal to baseRate at iteration 1', () => {
258
+ // Act
259
+ const rate = invRateFnCustom(baseRate, 1);
260
+ // Assert
261
+ expect(rate).toBeLessThanOrEqual(baseRate);
262
+ });
263
+
264
+ it('should return the decayed rate at iteration 10', () => {
265
+ // Act
266
+ const rate = invRateFnCustom(baseRate, 10);
267
+ const expected = baseRate / (1 + gamma * Math.pow(10, power));
268
+ // Assert
269
+ expect(rate).toBeCloseTo(expected, 5);
270
+ });
271
+
272
+ it('should be non-negative at iteration 10', () => {
273
+ // Act
274
+ const rate = invRateFnCustom(baseRate, 10);
275
+ // Assert
276
+ expect(rate).toBeGreaterThanOrEqual(0);
277
+ });
278
+
279
+ it('should be less than or equal to baseRate at iteration 10', () => {
280
+ // Act
281
+ const rate = invRateFnCustom(baseRate, 10);
282
+ // Assert
283
+ expect(rate).toBeLessThanOrEqual(baseRate);
284
+ });
285
+ });
286
+
287
+ describe('Default parameters', () => {
288
+ it('should return the base rate at iteration 0', () => {
289
+ // Act
290
+ const rate = invRateFnDefault(baseRate, 0);
291
+ // Assert
292
+ expect(rate).toBeCloseTo(baseRate, 5);
293
+ });
294
+
295
+ it('should be non-negative at iteration 0', () => {
296
+ // Act
297
+ const rate = invRateFnDefault(baseRate, 0);
298
+ // Assert
299
+ expect(rate).toBeGreaterThanOrEqual(0);
300
+ });
301
+
302
+ it('should return the decayed rate at iteration 10', () => {
303
+ // Act
304
+ const rate = invRateFnDefault(baseRate, 10);
305
+ const expected = baseRate / (1 + 0.001 * Math.pow(10, 2));
306
+ // Assert
307
+ expect(rate).toBeCloseTo(expected, 5);
308
+ });
309
+
310
+ it('should be non-negative at iteration 10', () => {
311
+ // Act
312
+ const rate = invRateFnDefault(baseRate, 10);
313
+ // Assert
314
+ expect(rate).toBeGreaterThanOrEqual(0);
315
+ });
316
+
317
+ it('should be less than or equal to baseRate at iteration 10', () => {
318
+ // Act
319
+ const rate = invRateFnDefault(baseRate, 10);
320
+ // Assert
321
+ expect(rate).toBeLessThanOrEqual(baseRate);
322
+ });
323
+ });
324
+ });
325
+
326
+ describe('cosineAnnealing()', () => {
327
+ const period = 100;
328
+ const minRate = 0.01;
329
+ const cosineFnCustom = Rate.cosineAnnealing(period, minRate);
330
+ const cosineFnDefault = Rate.cosineAnnealing();
331
+
332
+ describe('Custom parameters', () => {
333
+ describe('At the start of the cycle', () => {
334
+ it('should return the base rate', () => {
335
+ // Arrange
336
+ // Act
337
+ const rate = cosineFnCustom(baseRate, 0);
338
+ // Assert
339
+ expect(rate).toBeCloseTo(baseRate);
340
+ });
341
+ it('should be greater than or equal to minRate', () => {
342
+ // Arrange
343
+ // Act
344
+ const rate = cosineFnCustom(baseRate, 0);
345
+ // Assert
346
+ expect(rate).toBeGreaterThanOrEqual(minRate);
347
+ });
348
+ it('should be less than or equal to baseRate', () => {
349
+ // Arrange
350
+ // Act
351
+ const rate = cosineFnCustom(baseRate, 0);
352
+ // Assert
353
+ expect(rate).toBeLessThanOrEqual(baseRate);
354
+ });
355
+ });
356
+ describe('At the middle of the cycle', () => {
357
+ it('should return the average rate', () => {
358
+ // Arrange
359
+ // Act
360
+ const rate = cosineFnCustom(baseRate, period / 2);
361
+ // Assert
362
+ expect(rate).toBeCloseTo(minRate + (baseRate - minRate) * 0.5);
363
+ });
364
+ it('should be greater than or equal to minRate', () => {
365
+ // Arrange
366
+ // Act
367
+ const rate = cosineFnCustom(baseRate, period / 2);
368
+ // Assert
369
+ expect(rate).toBeGreaterThanOrEqual(minRate);
370
+ });
371
+ it('should be less than or equal to baseRate', () => {
372
+ // Arrange
373
+ // Act
374
+ const rate = cosineFnCustom(baseRate, period / 2);
375
+ // Assert
376
+ expect(rate).toBeLessThanOrEqual(baseRate);
377
+ });
378
+ });
379
+ describe('Near the end of the cycle', () => {
380
+ it('should return the min rate', () => {
381
+ // Arrange
382
+ // Act
383
+ const rate = cosineFnCustom(baseRate, period - 1);
384
+ // Assert
385
+ expect(rate).toBeCloseTo(minRate, 2);
386
+ });
387
+ it('should be greater than or equal to minRate', () => {
388
+ // Arrange
389
+ // Act
390
+ const rate = cosineFnCustom(baseRate, period - 1);
391
+ // Assert
392
+ expect(rate).toBeGreaterThanOrEqual(minRate);
393
+ });
394
+ it('should be less than or equal to baseRate', () => {
395
+ // Arrange
396
+ // Act
397
+ const rate = cosineFnCustom(baseRate, period - 1);
398
+ // Assert
399
+ expect(rate).toBeLessThanOrEqual(baseRate);
400
+ });
401
+ });
402
+ describe('At the start of the second cycle', () => {
403
+ it('should return the base rate', () => {
404
+ // Arrange
405
+ // Act
406
+ const rate = cosineFnCustom(baseRate, period);
407
+ // Assert
408
+ expect(rate).toBeCloseTo(baseRate);
409
+ });
410
+ it('should be greater than or equal to minRate', () => {
411
+ // Arrange
412
+ // Act
413
+ const rate = cosineFnCustom(baseRate, period);
414
+ // Assert
415
+ expect(rate).toBeGreaterThanOrEqual(minRate);
416
+ });
417
+ it('should be less than or equal to baseRate', () => {
418
+ // Arrange
419
+ // Act
420
+ const rate = cosineFnCustom(baseRate, period);
421
+ // Assert
422
+ expect(rate).toBeLessThanOrEqual(baseRate);
423
+ });
424
+ });
425
+ });
426
+ describe('Default parameters', () => {
427
+ describe('At the start of the cycle', () => {
428
+ it('should return the base rate', () => {
429
+ // Arrange
430
+ // Act
431
+ const rate = cosineFnDefault(baseRate, 0);
432
+ // Assert
433
+ expect(rate).toBeCloseTo(baseRate);
434
+ });
435
+ it('should be greater than or equal to 0', () => {
436
+ // Arrange
437
+ // Act
438
+ const rate = cosineFnDefault(baseRate, 0);
439
+ // Assert
440
+ expect(rate).toBeGreaterThanOrEqual(0);
441
+ });
442
+ it('should be less than or equal to baseRate', () => {
443
+ // Arrange
444
+ // Act
445
+ const rate = cosineFnDefault(baseRate, 0);
446
+ // Assert
447
+ expect(rate).toBeLessThanOrEqual(baseRate);
448
+ });
449
+ });
450
+ describe('At the middle of the cycle', () => {
451
+ it('should return half the base rate', () => {
452
+ // Arrange
453
+ // Act
454
+ const rate = cosineFnDefault(baseRate, 500);
455
+ // Assert
456
+ expect(rate).toBeCloseTo(baseRate * 0.5);
457
+ });
458
+ it('should be greater than or equal to 0', () => {
459
+ // Arrange
460
+ // Act
461
+ const rate = cosineFnDefault(baseRate, 500);
462
+ // Assert
463
+ expect(rate).toBeGreaterThanOrEqual(0);
464
+ });
465
+ it('should be less than or equal to baseRate', () => {
466
+ // Arrange
467
+ // Act
468
+ const rate = cosineFnDefault(baseRate, 500);
469
+ // Assert
470
+ expect(rate).toBeLessThanOrEqual(baseRate);
471
+ });
472
+ });
473
+ describe('Near the end of the cycle', () => {
474
+ it('should return close to zero', () => {
475
+ // Arrange
476
+ // Act
477
+ const rate = cosineFnDefault(baseRate, 999);
478
+ // Assert
479
+ expect(rate).toBeCloseTo(0, 2);
480
+ });
481
+ it('should be greater than or equal to 0', () => {
482
+ // Arrange
483
+ // Act
484
+ const rate = cosineFnDefault(baseRate, 999);
485
+ // Assert
486
+ expect(rate).toBeGreaterThanOrEqual(0);
487
+ });
488
+ it('should be less than or equal to baseRate', () => {
489
+ // Arrange
490
+ // Act
491
+ const rate = cosineFnDefault(baseRate, 999);
492
+ // Assert
493
+ expect(rate).toBeLessThanOrEqual(baseRate);
494
+ });
495
+ });
496
+ });
497
+ });
498
+
499
+ describe('Rate utility methods', () => {
500
+ describe('fixed()', () => {
501
+ it('should always return the base rate regardless of iteration', () => {
502
+ // Arrange
503
+ const fn = Rate.fixed();
504
+ // Act
505
+ const result1 = fn(0.5, 0);
506
+ const result2 = fn(0.5, 100);
507
+ // Assert
508
+ expect(result1).toBe(0.5);
509
+ expect(result2).toBe(0.5);
510
+ });
511
+ });
512
+ describe('step()', () => {
513
+ it('should decay at correct steps', () => {
514
+ // Arrange
515
+ const fn = Rate.step(0.5, 10);
516
+ // Act
517
+ const r0 = fn(1, 0);
518
+ const r10 = fn(1, 10);
519
+ const r20 = fn(1, 20);
520
+ // Assert
521
+ expect(r0).toBe(1);
522
+ expect(r10).toBeCloseTo(0.5);
523
+ expect(r20).toBeCloseTo(0.25);
524
+ });
525
+ });
526
+ describe('exp()', () => {
527
+ it('should decay exponentially', () => {
528
+ // Arrange
529
+ const fn = Rate.exp(0.5);
530
+ // Act
531
+ const r0 = fn(1, 0);
532
+ const r1 = fn(1, 1);
533
+ const r2 = fn(1, 2);
534
+ // Assert
535
+ expect(r0).toBe(1);
536
+ expect(r1).toBeCloseTo(0.5);
537
+ expect(r2).toBeCloseTo(0.25);
538
+ });
539
+ });
540
+ describe('inv()', () => {
541
+ it('should decay inversely', () => {
542
+ // Arrange
543
+ const fn = Rate.inv(1, 1);
544
+ // Act
545
+ const r0 = fn(1, 0);
546
+ const r1 = fn(1, 1);
547
+ const r2 = fn(1, 2);
548
+ // Assert
549
+ expect(r0).toBe(1);
550
+ expect(r1).toBeCloseTo(0.5);
551
+ expect(r2).toBeCloseTo(0.333333, 5);
552
+ });
553
+ });
554
+ describe('cosineAnnealing()', () => {
555
+ it('should cycle between baseRate and minRate', () => {
556
+ // Arrange
557
+ const fn = Rate.cosineAnnealing(4, 0);
558
+ // Act
559
+ const r0 = fn(1, 0);
560
+ const r2 = fn(1, 2);
561
+ const r4 = fn(1, 4);
562
+ // Assert
563
+ expect(r0).toBeCloseTo(1);
564
+ expect(r2).toBeCloseTo(0.5);
565
+ expect(r4).toBeCloseTo(1);
566
+ });
567
+ });
568
+ });
569
+
570
+ describe('Invalid and edge input scenarios', () => {
571
+ const period = 100;
572
+ const minRate = 0.01;
573
+ const cosineFnCustom = Rate.cosineAnnealing(period, minRate);
574
+ const stepFn = Rate.step(0.9, 10);
575
+ const expFn = Rate.exp(0.95);
576
+ const invFn = Rate.inv(0.01, 1.5);
577
+ const fixedFn = Rate.fixed();
578
+ it('should return a valid rate for negative iteration', () => {
579
+ // Arrange
580
+ // Act
581
+ const rate = cosineFnCustom(baseRate, -1);
582
+ // Assert
583
+ expect(typeof rate).toBe('number');
584
+ });
585
+ it('should return a valid rate for negative baseRate', () => {
586
+ // Arrange
587
+ // Act
588
+ const rate = cosineFnCustom(-0.1, 0);
589
+ // Assert
590
+ expect(typeof rate).toBe('number');
591
+ });
592
+ it('should return a valid rate for non-integer iteration', () => {
593
+ // Arrange
594
+ // Act
595
+ const rate = cosineFnCustom(baseRate, 1.5);
596
+ // Assert
597
+ expect(typeof rate).toBe('number');
598
+ });
599
+ it('step: should return a valid rate for negative iteration', () => {
600
+ // Arrange
601
+ // Act
602
+ const rate = stepFn(baseRate, -5);
603
+ // Assert
604
+ expect(typeof rate).toBe('number');
605
+ });
606
+ it('exp: should return a valid rate for negative iteration', () => {
607
+ // Arrange
608
+ // Act
609
+ const rate = expFn(baseRate, -5);
610
+ // Assert
611
+ expect(typeof rate).toBe('number');
612
+ });
613
+ it('inv: should return a valid rate for negative iteration', () => {
614
+ // Arrange
615
+ // Act
616
+ const rate = invFn(baseRate, -5);
617
+ // Assert
618
+ expect(typeof rate).toBe('number');
619
+ });
620
+ it('step: should return a valid rate for negative baseRate', () => {
621
+ // Arrange
622
+ // Act
623
+ const rate = stepFn(-0.1, 0);
624
+ // Assert
625
+ expect(typeof rate).toBe('number');
626
+ });
627
+ it('exp: should return a valid rate for negative baseRate', () => {
628
+ // Arrange
629
+ // Act
630
+ const rate = expFn(-0.1, 0);
631
+ // Assert
632
+ expect(typeof rate).toBe('number');
633
+ });
634
+ it('inv: should return a valid rate for negative baseRate', () => {
635
+ // Arrange
636
+ // Act
637
+ const rate = invFn(-0.1, 0);
638
+ // Assert
639
+ expect(typeof rate).toBe('number');
640
+ });
641
+ it('step: should return a valid rate for non-integer iteration', () => {
642
+ // Arrange
643
+ // Act
644
+ const rate = stepFn(baseRate, 1.5);
645
+ // Assert
646
+ expect(typeof rate).toBe('number');
647
+ });
648
+ it('exp: should return a valid rate for non-integer iteration', () => {
649
+ // Arrange
650
+ // Act
651
+ const rate = expFn(baseRate, 1.5);
652
+ // Assert
653
+ expect(typeof rate).toBe('number');
654
+ });
655
+ it('inv: should return a valid rate for non-integer iteration', () => {
656
+ // Arrange
657
+ // Act
658
+ const rate = invFn(baseRate, 1.5);
659
+ // Assert
660
+ expect(typeof rate).toBe('number');
661
+ });
662
+ it('fixed: should return the base rate for negative iteration', () => {
663
+ // Arrange
664
+ // Act
665
+ const rate = fixedFn(baseRate, -10);
666
+ // Assert
667
+ expect(rate).toBe(baseRate);
668
+ });
669
+ it('fixed: should return the base rate for negative baseRate', () => {
670
+ // Arrange
671
+ // Act
672
+ const rate = fixedFn(-0.1, 0);
673
+ // Assert
674
+ expect(rate).toBe(-0.1);
675
+ });
676
+ it('fixed: should return the base rate for non-integer iteration', () => {
677
+ // Arrange
678
+ // Act
679
+ const rate = fixedFn(baseRate, 1.5);
680
+ // Assert
681
+ expect(rate).toBe(baseRate);
682
+ });
683
+ });
684
+ });