Compare commits
10 Commits
1ff10b89bd
...
ec48447670
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec48447670 | ||
|
|
7e872c7191 | ||
|
|
cc651bbd75 | ||
|
|
b9778dcf8b | ||
|
|
44be8fdc4f | ||
|
|
505556a214 | ||
|
|
79b3b4af1c | ||
|
|
4422cc613e | ||
|
|
7b2ae5c8a2 | ||
|
|
96923be0b5 |
37
README.md
37
README.md
@@ -1,9 +1,9 @@
|
||||
<h1 align="center">
|
||||
<a href="https://github.com/EMI-Group/evox">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="./imgs/evox_logo_dark.png">
|
||||
<source media="(prefers-color-scheme: light)" srcset="./imgs/evox_logo_light.png">
|
||||
<img alt="EvoX Logo" height="50" src="./imgs/evox_logo_light.png">
|
||||
<source media="(prefers-color-scheme: dark)" srcset="./imgs/evox_brand_light.svg">
|
||||
<source media="(prefers-color-scheme: light)" srcset="./imgs/evox_brand_dark.svg">
|
||||
<img alt="EvoX Logo" height="50" src="./imgs/evox_brand_light.svg">
|
||||
</picture>
|
||||
</a>
|
||||
<br>
|
||||
@@ -296,6 +296,15 @@ pip install git+https://github.com/EMI-Group/tensorneat.git
|
||||
## Multi-device and Distributed Acceleration
|
||||
TensorNEAT doesn't natively support multi-device or distributed execution, but these features can be accessed via the EvoX framework. EvoX is a high-performance, distributed, GPU-accelerated framework for Evolutionary Algorithms. For more details, visit: [EvoX GitHub](https://github.com/EMI-Group/evox/).
|
||||
|
||||
**Notice**: As the latest EvoX has been migrated to the PyTorch backend, we need to install the JAX-Version EvoX to run multi-device EvoX.
|
||||
The current JAX-Version Evox branch is [v0.9.1-dev](https://github.com/EMI-Group/evox/tree/v0.9.1-dev).
|
||||
|
||||
Use
|
||||
```bash
|
||||
pip install "git+https://github.com/EMI-Group/evox@v0.9.1-dev"
|
||||
```
|
||||
to install the JAX based EvoX.
|
||||
|
||||
TensorNEAT includes an EvoX Adaptor, which allows TensorNEAT algorithms to run within the EvoX framework. Additionally, TensorNEAT provides a monitor for use with EvoX.
|
||||
|
||||
Here is an example of creating an EvoX algorithm and monitor:
|
||||
@@ -410,17 +419,17 @@ We warmly welcome community developers to contribute to TensorNEAT and look forw
|
||||
|
||||
If you use TensorNEAT in your research and want to cite it in your work, please use:
|
||||
```
|
||||
@inproceedings{10.1145/3638529.3654210,
|
||||
@article{10.1145/3730406,
|
||||
author = {Wang, Lishuang and Zhao, Mengfei and Liu, Enyu and Sun, Kebin and Cheng, Ran},
|
||||
title = {Tensorized NeuroEvolution of Augmenting Topologies for GPU Acceleration},
|
||||
year = {2024},
|
||||
isbn = {9798400704949},
|
||||
doi = {10.1145/3638529.3654210},
|
||||
booktitle = {Proceedings of the Genetic and Evolutionary Computation Conference},
|
||||
pages = {1156–1164},
|
||||
numpages = {9},
|
||||
keywords = {neuroevolution, GPU acceleration, algorithm library},
|
||||
location = {Melbourne, VIC, Australia},
|
||||
series = {GECCO '24}
|
||||
title = {TensorNEAT: A GPU-accelerated Library for NeuroEvolution of Augmenting Topologies},
|
||||
year = {2025},
|
||||
publisher = {Association for Computing Machinery},
|
||||
address = {New York, NY, USA},
|
||||
url = {https://doi.org/10.1145/3730406},
|
||||
doi = {10.1145/3730406},
|
||||
journal = {ACM Trans. Evol. Learn. Optim.},
|
||||
month = apr,
|
||||
keywords = {Neuroevolution, GPU Acceleration, Algorithm Library}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
9
examples/with_evox/README.md
Normal file
9
examples/with_evox/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Notice
|
||||
This part is based on the JAX-Version EvoX.
|
||||
|
||||
To run this example, please install EvoX with the [jax-version branch: (v0.9.1-dev)](https://github.com/EMI-Group/evox/tree/v0.9.1-dev)
|
||||
|
||||
Use this command to install EvoX's JAX Version:
|
||||
```bash
|
||||
pip install "git+https://github.com/EMI-Group/evox@v0.9.1-dev"
|
||||
```
|
||||
54
imgs/evox_brand_dark.svg
Normal file
54
imgs/evox_brand_dark.svg
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Creator: CorelDRAW -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="6062.18mm" height="1250mm" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
|
||||
viewBox="0 0 625393.22 128953.89"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
|
||||
<defs>
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
.fil3 {fill:#373435}
|
||||
.fil4 {fill:#C8383C}
|
||||
.fil2 {fill:url(#id0)}
|
||||
.fil0 {fill:url(#id1)}
|
||||
.fil1 {fill:url(#id2)}
|
||||
]]>
|
||||
</style>
|
||||
<linearGradient id="id0" gradientUnits="userSpaceOnUse" x1="359566.17" y1="126101.11" x2="359566.17" y2="2853.49">
|
||||
<stop offset="0" style="stop-opacity:0.917647; stop-color:#373435"/>
|
||||
<stop offset="0.309804" style="stop-opacity:0.835294; stop-color:#373535"/>
|
||||
<stop offset="0.560784" style="stop-opacity:0.74902; stop-color:#373636"/>
|
||||
<stop offset="0.788235" style="stop-opacity:0.87451; stop-color:#302F30"/>
|
||||
<stop offset="1" style="stop-opacity:1; stop-color:#282829"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="id1" gradientUnits="userSpaceOnUse" xlink:href="#id0" x1="56326.49" y1="126101.11" x2="56326.49" y2="2853.49">
|
||||
</linearGradient>
|
||||
<linearGradient id="id2" gradientUnits="userSpaceOnUse" xlink:href="#id0" x1="199869.19" y1="126101.11" x2="199869.19" y2="2853.49">
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="圖層_x0020_1">
|
||||
<metadata id="CorelCorpID_0Corel-Layer"/>
|
||||
<path class="fil0" d="M111173.52 4085.97l-110434.04 0c-205.57,0 -390.44,81.83 -521.58,212.97l-4.93 4.93c-131.13,131.13 -212.97,316.01 -212.97,521.58l0 23170.55c0,202.13 83.81,387.49 217.9,521.58 131.14,136.07 316.01,217.91 521.58,217.91l111173.52 0c202.13,0 387.49,-83.81 521.58,-217.91 134.09,-134.09 217.9,-319.45 217.9,-521.58l0 -22431.06c0,-814.42 -664.55,-1478.97 -1478.97,-1478.97zm1478.97 73209.08l0 -24896.02c0,-814.42 -664.55,-1478.97 -1478.97,-1478.97l-110434.04 0c-205.57,0 -390.44,81.84 -521.58,212.97l-4.93 4.93c-131.13,131.14 -212.97,316.01 -212.97,521.58l0 72469.6c0,202.13 83.81,387.49 217.9,521.58 131.14,136.07 316.01,217.9 521.58,217.9l111173.52 0c202.13,0 387.49,-83.8 521.58,-217.9 134.09,-134.09 217.9,-319.45 217.9,-521.58l0 -22431.06c0,-814.42 -664.55,-1478.97 -1478.97,-1478.97l-80854.68 0c-879,0 -1680.1,-360.38 -2262.33,-942.11 -582.22,-577.29 -942.11,-1379.39 -942.11,-2262.34l0 -15775.69c0,-878.02 359.39,-1678.14 939.64,-2259.87l4.93 -4.93c581.73,-580.25 1381.85,-939.64 2259.86,-939.64l81594.16 0c202.13,0 387.49,-83.81 521.58,-217.9 134.09,-134.09 217.9,-319.45 217.9,-521.58z"/>
|
||||
<path class="fil1" d="M160583.37 4085.97l-25473.74 0c-135.08,0 -254.89,27.61 -352,77.89 -99.09,55.21 -188.81,138.04 -262.26,246.99 -76.42,109.44 -119.8,223.81 -131.14,333.26 -11.83,113.39 7.4,237.13 57.68,362.35l48201.05 119303.69c58.17,144.45 152.33,260.8 269.17,339.18 113.39,76.41 257.83,119.3 418.54,119.3l33473.97 0c161.2,0 305.16,-42.88 418.54,-119.3 116.84,-78.38 211,-194.73 269.17,-339.18l47792.35 -118291.1c189.8,-469.82 138.53,-960.84 -144.94,-1380.86 -283.46,-420.52 -719.26,-652.23 -1226.06,-652.23l-24381.27 0c-160.72,0 -305.17,42.88 -418.55,119.3 -116.83,78.39 -211.49,195.23 -269.17,339.18l-35807.78 88627.85c-247.97,616.24 -658.63,1117.62 -1174.3,1465.17 -517.64,349.03 -1135.36,543.28 -1794.98,543.28 -660.11,0 -1277.33,-194.25 -1794.98,-543.28 -515.66,-347.56 -926.32,-848.93 -1174.3,-1465.17l-35807.3 -88627.85c-57.68,-143.95 -152.33,-260.79 -269.17,-339.18 -113.39,-76.41 -257.34,-119.3 -418.54,-119.3z"/>
|
||||
<path class="fil2" d="M396465.92 4085.97l-73800 0c-8492.23,0 -16213.92,3475.58 -21812.31,9073.48 -5598.38,5598.9 -9073.46,13320.11 -9073.46,21812.36l0 59010.96c0,8492.25 3475.58,16213.96 9073.46,21812.36 5598.39,5597.91 13320.08,9073.48 21812.31,9073.48l73800 0c8492.23,0 16214.41,-3475.58 21812.31,-9073.98 5598.38,-5597.91 9073.96,-13319.62 9073.96,-21811.87l0 -59010.96c0,-8492.25 -3475.58,-16213.96 -9073.96,-21811.87 -5597.9,-5598.4 -13320.08,-9073.98 -21812.31,-9073.98zm-68834.62 24649.53l63869.72 0c3081.68,0 5883.34,1260.08 7912.49,3289.23 2029.14,2029.15 3289.22,4830.81 3289.22,7912.5l0 49079.66c0,3081.68 -1260.09,5883.35 -3289.22,7912.5 -2029.15,2029.15 -4830.81,3289.23 -7912.49,3289.23l-63869.72 0c-3081.67,0 -5883.33,-1260.09 -7912.48,-3289.23 -2029.15,-2029.15 -3289.22,-4830.82 -3289.22,-7912.5l0 -49079.66c0,-3081.69 1260.08,-5883.35 3289.22,-7912.5 2029.15,-2029.16 4830.81,-3289.23 7912.48,-3289.23z"/>
|
||||
<path class="fil3" d="M522115.89 82633.04l-14940.89 -15397.6c-51.58,-53.21 -115.75,-79.7 -189.87,-78.29 -74.03,1.42 -137.28,30.26 -186.84,85.3l-2352.65 2612.89c-93.82,104.17 -87.02,264.71 15.13,360.56l15613.97 14650.18c52.5,49.24 115.35,72.6 187.24,69.55 71.88,-3.04 132.61,-31.58 180.83,-84.99l1679.65 -1865.47c90.98,-101.03 88.04,-254.55 -6.59,-352.14z"/>
|
||||
<path class="fil3" d="M516827.35 88459.62l-16690.8 -13454.25c-106.71,-86 -261.77,-73.62 -353.45,28.23l-2891.52 3211.16c-50.87,56.55 -72.91,124.69 -64.68,200.33 8.13,75.55 44.28,137.49 106.01,181.75l17498.33 12557.38c107.23,76.96 253.65,61.12 341.99,-36.96l2083.87 -2314.37c49.24,-54.52 71.28,-119.71 65.49,-193.02 -5.89,-73.32 -38.08,-134.13 -95.24,-180.24z"/>
|
||||
<path class="fil3" d="M511534.04 94292.2l-18440.5 -11510.81c-107.02,-66.81 -243.69,-47.52 -328.17,46.2l-3424.7 3803.43c-54.73,60.82 -76.45,135.97 -62.44,216.49 13.91,80.62 59.61,144.18 131.59,182.97l19382.78 10464.45c106.01,57.27 233.44,35.23 314.06,-54.33l2482.52 -2757.17c52.8,-58.6 74.73,-130.27 63.66,-208.46 -10.97,-78.19 -51.78,-140.94 -118.8,-182.77z"/>
|
||||
<path class="fil3" d="M506237.6 100131.27l-20190.42 -9567.46c-104.59,-49.55 -224.6,-25.58 -302.07,60.41l-3952.69 4390.01c-58.28,64.79 -79.4,146.83 -59.3,231.61 20,84.99 75.34,148.96 156.47,180.84l21267.24 8371.65c102.05,40.11 212.72,14.11 286.13,-67.43l2875.88 -3194.1c56.25,-62.55 77.68,-140.63 61.23,-223.18 -16.44,-82.45 -66.41,-146.42 -142.46,-182.36z"/>
|
||||
<path class="fil3" d="M500939.21 105976.44l-21940.13 -7623.92c-100.11,-34.83 -205.41,-7.82 -276.28,70.98l-4476.23 4971.22c-61.73,68.53 -81.84,157.08 -55.74,245.41 26.09,88.44 90.88,151.91 179.82,176.07l23151.69 6278.53c96.16,26.1 192.41,-2.23 259.13,-76.35l3264.76 -3625.84c59.61,-66.2 80.32,-150.47 58.18,-236.78 -22.23,-86.21 -81.13,-150.08 -165.21,-179.32z"/>
|
||||
<path class="fil3" d="M495640.02 111827.39l-23689.94 -5680.77c-94.44,-22.54 -186.93,6.09 -251.81,78.28l-4995.4 5547.97c-64.68,71.88 -83.67,166.42 -51.79,257.6 31.89,91.29 105.61,153.42 200.95,169.37l25036.04 4185.62c89.46,15.03 173.43,-14.32 234.15,-81.74l3649.29 -4053.11c62.65,-69.45 82.45,-159.72 54.73,-248.97 -27.81,-89.35 -95.24,-152.52 -186.22,-174.24z"/>
|
||||
<path class="fil3" d="M490341.04 117683.01l-25439.87 -3737.32c-88.03,-12.9 -169.66,16.44 -229.17,82.55l-5511 6120.74c-67.31,74.83 -85.19,174.85 -47.83,268.27 37.37,93.52 119.11,153.63 219.53,161.44l26920.5 2092.82c82.55,6.49 156.26,-23.06 211.6,-84.58l4030.47 -4476.23c65.29,-72.49 84.08,-168.25 50.97,-260.04 -33.09,-91.68 -108.64,-153.52 -205.2,-167.64z"/>
|
||||
<path class="fil3" d="M485042.76 123542.4l-27189.77 -1793.88c-81.54,-5.39 -153.93,24.07 -208.56,84.79l-6023.87 6690.16c-69.66,77.37 -86.31,182.27 -43.97,277.51 42.44,95.04 131.49,152.92 235.57,152.92l28804.95 0c75.74,0 140.93,-29.04 191.71,-85.4l4408.59 -4896.18c67.73,-75.24 85.4,-175.86 47.32,-269.59 -38.08,-93.71 -121.04,-153.63 -221.97,-160.33z"/>
|
||||
<path class="fil4" d="M455586.23 0l23946.23 0c606.08,0 1127.69,232.22 1533.33,682.65l112395.09 124827.36c557.66,619.39 690.56,1458.5 351.63,2219.83 -338.93,761.34 -1051.53,1224.05 -1884.86,1224.05l-23946.32 0c-606.08,0 -1127.79,-232.32 -1533.33,-682.74l-112394.99 -124827.37c-557.65,-619.28 -690.56,-1458.4 -351.62,-2219.83 338.93,-761.23 1051.53,-1223.95 1884.85,-1223.95z"/>
|
||||
<path class="fil3" d="M546063.84 55728.5l-17150.76 -12698.51c-107.23,-79.4 -255.89,-64.37 -345.13,34.72l-3542.88 3934.72c-91.29,101.44 -87.94,255.88 7.72,353.25l14841.57 15109.54c51.28,52.29 114.74,78.28 188.06,77.17 73.2,-1.11 135.86,-29.14 185.51,-83.06l5852.07 -6345.75c51.38,-55.75 74.22,-123.57 67.11,-199.12 -7.2,-75.55 -42.34,-137.79 -103.26,-182.97z"/>
|
||||
<path class="fil3" d="M553805.64 48026.39l-20076.6 -10405.36c-105.7,-54.73 -230.69,-31.98 -310.3,56.46l-3337.36 3706.35c-51.68,57.47 -73.62,127.13 -64.38,203.79 9.35,76.66 47.42,139.01 111.4,182.27l17863.05 12103.08c102.35,69.36 235.87,57.58 324.52,-28.73l5550.91 -5404.09c61.23,-59.6 87.73,-137.89 75.24,-222.47 -12.49,-84.57 -60.52,-151.9 -136.46,-191.3z"/>
|
||||
<path class="fil3" d="M561723.31 40809.94l-23179.82 -8581.22c-101.13,-37.46 -208.97,-10.76 -281.16,69.36l-3126.37 3472.11c-56.35,62.65 -77.77,140.83 -61.12,223.48 16.55,82.55 66.61,146.42 142.86,182.36l20967.6 9879.29c95.64,45.08 202.87,29.55 281.77,-40.91l5338.48 -4770.28c69.36,-62.04 98.9,-148.96 81.54,-240.34 -17.27,-91.38 -76.57,-161.45 -163.78,-193.84z"/>
|
||||
<path class="fil3" d="M569965.29 33882.39l-26606.23 -7035.4c-95.86,-25.38 -191.31,3.05 -257.61,76.76l-2913.54 3235.73c-60.01,66.6 -80.62,151.69 -57.78,238.41 22.95,86.71 82.96,150.48 167.95,178.81l24313.19 8089.46c86.71,28.84 174.94,12.39 245.41,-45.69l5206.69 -4289.8c76.56,-63.05 109.05,-157.18 87.93,-254.14 -21.22,-96.87 -90.16,-168.86 -186.01,-194.14z"/>
|
||||
<path class="fil3" d="M578696.89 27121.04l-30520.74 -5649.4c-90.78,-16.86 -176.78,12.39 -238.52,81.02l-2700.82 2999.45c-62.74,69.66 -82.45,160.23 -54.32,249.79 28.02,89.45 96.06,152.61 187.33,173.83l28072.15 6551.78c77.27,18.07 151.08,2.33 214.34,-45.59l5149.43 -3901.82c83.26,-63.05 119.2,-163.37 95.14,-265.02 -24.06,-101.53 -101.23,-175.05 -203.98,-194.04z"/>
|
||||
<path class="fil3" d="M588128.6 20435.94l-35133.75 -4335.48c-86.1,-10.56 -165.1,18.88 -223.18,83.36l-2488.81 2764.08c-64.88,72.19 -83.87,167.13 -51.48,258.62 32.39,91.49 106.82,153.42 202.67,168.66l32447.23 5148.1c68.03,10.76 130.38,-3.45 187.03,-42.54l5175.31 -3576.7c89.76,-62.03 129.87,-167.64 103.87,-273.64 -26.1,-106.01 -110.58,-181.14 -218.91,-194.45z"/>
|
||||
<path class="fil3" d="M598567.77 13749.33l-40752.78 -3017.31c-82.24,-6.1 -155.55,23.35 -210.69,84.68l-2278.02 2529.94c-66.71,74.12 -84.88,172.61 -48.94,265.52 35.84,93.01 115.66,153.72 214.75,163.68l37715.35 3786.47c59,5.89 111.4,-6.29 161.76,-37.56l5315.54 -3299.09c96.46,-59.91 141.54,-170.28 114.43,-280.64 -27.11,-110.27 -118.09,-187.24 -231.41,-195.67z"/>
|
||||
<path class="fil3" d="M610537.63 6977.53l-47901.39 -1612.13c-78.8,-2.64 -147.64,26.61 -200.34,85.19l-2068.74 2297.51c-68.13,75.54 -85.49,177.08 -46.61,271.1 38.89,93.92 122.87,153.53 224.5,158.91l44316.99 2379.55c49.76,2.74 93.01,-7 136.77,-30.76l5653.05 -3065.04c103.77,-56.25 155.16,-170.99 128.05,-285.83 -27.11,-114.94 -124.29,-194.54 -242.28,-198.51z"/>
|
||||
<path class="fil3" d="M625135.21 0l-57676.8 0c-75.75,0 -140.94,29.04 -191.6,85.3l-1860.69 2066.41c-69.25,76.97 -86.11,180.84 -44.68,275.68 41.33,94.84 128.95,153.11 232.32,154.74l53096.1 819.1c39.4,0.61 73.41,-6.4 109.35,-22.54l6441.4 -2885.51c112.2,-50.26 172.41,-168.87 146.72,-289.19 -25.69,-120.32 -129.15,-203.99 -252.12,-203.99z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 11 KiB |
54
imgs/evox_brand_light.svg
Normal file
54
imgs/evox_brand_light.svg
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Creator: CorelDRAW -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="6062.18mm" height="1250mm" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
|
||||
viewBox="0 0 625393.22 128953.89"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
|
||||
<defs>
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
.fil3 {fill:#FEFEFE}
|
||||
.fil4 {fill:#C8383C}
|
||||
.fil2 {fill:url(#id0)}
|
||||
.fil0 {fill:url(#id1)}
|
||||
.fil1 {fill:url(#id2)}
|
||||
]]>
|
||||
</style>
|
||||
<linearGradient id="id0" gradientUnits="userSpaceOnUse" x1="359566.17" y1="126101.12" x2="359566.17" y2="2853.5">
|
||||
<stop offset="0" style="stop-opacity:0.917647; stop-color:#FEFEFE"/>
|
||||
<stop offset="0.309804" style="stop-opacity:0.835294; stop-color:#FEFEFE"/>
|
||||
<stop offset="0.560784" style="stop-opacity:0.74902; stop-color:#FEFEFE"/>
|
||||
<stop offset="0.788235" style="stop-opacity:0.87451; stop-color:#FEFEFE"/>
|
||||
<stop offset="1" style="stop-opacity:1; stop-color:#FEFEFE"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="id1" gradientUnits="userSpaceOnUse" xlink:href="#id0" x1="56326.49" y1="126101.12" x2="56326.49" y2="2853.5">
|
||||
</linearGradient>
|
||||
<linearGradient id="id2" gradientUnits="userSpaceOnUse" xlink:href="#id0" x1="199869.19" y1="126101.12" x2="199869.19" y2="2853.5">
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="圖層_x0020_1">
|
||||
<metadata id="CorelCorpID_0Corel-Layer"/>
|
||||
<path class="fil0" d="M111173.52 4085.98l-110434.04 0c-205.57,0 -390.44,81.84 -521.58,212.97l-4.93 4.93c-131.13,131.13 -212.97,316.01 -212.97,521.58l0 23170.56c0,202.12 83.81,387.48 217.9,521.58 131.14,136.06 316.01,217.9 521.58,217.9l111173.52 0c202.13,0 387.49,-83.81 521.58,-217.9 134.09,-134.1 217.9,-319.47 217.9,-521.58l0 -22431.08c0,-814.42 -664.55,-1478.97 -1478.97,-1478.97zm1478.97 73209.08l0 -24896.01c0,-814.42 -664.55,-1478.98 -1478.97,-1478.98l-110434.04 0c-205.57,0 -390.44,81.84 -521.58,212.97l-4.93 4.93c-131.13,131.14 -212.97,316.01 -212.97,521.58l0 72469.6c0,202.13 83.81,387.49 217.9,521.59 131.14,136.06 316.01,217.9 521.58,217.9l111173.52 0c202.13,0 387.49,-83.81 521.58,-217.9 134.09,-134.1 217.9,-319.47 217.9,-521.59l0 -22431.06c0,-814.42 -664.55,-1478.97 -1478.97,-1478.97l-80854.68 0c-879,0 -1680.1,-360.38 -2262.33,-942.11 -582.22,-577.29 -942.11,-1379.38 -942.11,-2262.34l0 -15775.69c0,-878.02 359.39,-1678.14 939.64,-2259.87l4.93 -4.93c581.73,-580.25 1381.85,-939.64 2259.86,-939.64l81594.16 0c202.13,0 387.49,-83.81 521.58,-217.9 134.09,-134.09 217.9,-319.45 217.9,-521.58z"/>
|
||||
<path class="fil1" d="M160583.37 4085.98l-25473.74 0c-135.08,0 -254.89,27.61 -352,77.89 -99.09,55.22 -188.81,138.04 -262.26,246.99 -76.42,109.45 -119.8,223.81 -131.14,333.26 -11.83,113.39 7.4,237.13 57.68,362.35l48201.05 119303.69c58.17,144.45 152.33,260.8 269.17,339.18 113.39,76.41 257.83,119.31 418.54,119.31l33473.97 0c161.2,0 305.16,-42.9 418.54,-119.31 116.84,-78.38 211,-194.73 269.17,-339.18l47792.35 -118291.1c189.8,-469.82 138.53,-960.83 -144.94,-1380.86 -283.46,-420.52 -719.26,-652.23 -1226.06,-652.23l-24381.27 0c-160.72,0 -305.17,42.88 -418.55,119.3 -116.83,78.39 -211.49,195.23 -269.17,339.18l-35807.78 88627.86c-247.97,616.23 -658.63,1117.61 -1174.3,1465.16 -517.64,349.04 -1135.36,543.28 -1794.98,543.28 -660.11,0 -1277.33,-194.24 -1794.98,-543.28 -515.66,-347.56 -926.32,-848.93 -1174.3,-1465.16l-35807.3 -88627.86c-57.68,-143.95 -152.33,-260.79 -269.17,-339.18 -113.39,-76.41 -257.34,-119.3 -418.54,-119.3z"/>
|
||||
<path class="fil2" d="M396465.92 4085.98l-73800 0c-8492.23,0 -16213.92,3475.59 -21812.31,9073.48 -5598.38,5598.9 -9073.46,13320.11 -9073.46,21812.36l0 59010.96c0,8492.25 3475.58,16213.97 9073.46,21812.36 5598.39,5597.91 13320.08,9073.49 21812.31,9073.49l73800 0c8492.23,0 16214.41,-3475.59 21812.31,-9073.99 5598.38,-5597.9 9073.96,-13319.62 9073.96,-21811.87l0 -59010.96c0,-8492.25 -3475.58,-16213.96 -9073.96,-21811.87 -5597.9,-5598.39 -13320.08,-9073.98 -21812.31,-9073.98zm-68834.62 24649.53l63869.72 0c3081.68,0 5883.34,1260.09 7912.49,3289.23 2029.14,2029.15 3289.22,4830.81 3289.22,7912.5l0 49079.66c0,3081.68 -1260.09,5883.35 -3289.22,7912.5 -2029.15,2029.15 -4830.81,3289.23 -7912.49,3289.23l-63869.72 0c-3081.67,0 -5883.33,-1260.09 -7912.48,-3289.23 -2029.15,-2029.15 -3289.22,-4830.82 -3289.22,-7912.5l0 -49079.66c0,-3081.69 1260.08,-5883.35 3289.22,-7912.5 2029.15,-2029.15 4830.81,-3289.23 7912.48,-3289.23z"/>
|
||||
<path class="fil3" d="M522115.89 82633.04l-14940.89 -15397.6c-51.58,-53.21 -115.75,-79.7 -189.87,-78.29 -74.03,1.42 -137.28,30.26 -186.84,85.3l-2352.65 2612.89c-93.82,104.17 -87.02,264.71 15.13,360.56l15613.97 14650.18c52.5,49.24 115.35,72.6 187.24,69.55 71.88,-3.04 132.61,-31.58 180.83,-84.99l1679.65 -1865.47c90.98,-101.03 88.04,-254.55 -6.59,-352.14z"/>
|
||||
<path class="fil3" d="M516827.35 88459.62l-16690.8 -13454.25c-106.71,-86 -261.77,-73.62 -353.45,28.23l-2891.52 3211.16c-50.87,56.55 -72.91,124.69 -64.68,200.33 8.13,75.55 44.28,137.49 106.01,181.75l17498.33 12557.38c107.23,76.96 253.65,61.12 341.99,-36.96l2083.87 -2314.37c49.24,-54.52 71.28,-119.71 65.49,-193.02 -5.89,-73.32 -38.08,-134.13 -95.24,-180.24z"/>
|
||||
<path class="fil3" d="M511534.04 94292.2l-18440.5 -11510.81c-107.02,-66.81 -243.69,-47.52 -328.17,46.2l-3424.7 3803.43c-54.73,60.82 -76.45,135.97 -62.44,216.49 13.91,80.62 59.61,144.18 131.59,182.97l19382.78 10464.45c106.01,57.27 233.44,35.23 314.06,-54.33l2482.52 -2757.17c52.8,-58.6 74.73,-130.27 63.66,-208.46 -10.97,-78.19 -51.78,-140.94 -118.8,-182.77z"/>
|
||||
<path class="fil3" d="M506237.6 100131.27l-20190.42 -9567.46c-104.59,-49.55 -224.6,-25.58 -302.07,60.41l-3952.69 4390.01c-58.28,64.79 -79.4,146.83 -59.3,231.61 20,84.99 75.34,148.96 156.47,180.84l21267.24 8371.65c102.05,40.11 212.72,14.11 286.13,-67.43l2875.88 -3194.1c56.25,-62.55 77.68,-140.63 61.23,-223.18 -16.44,-82.45 -66.41,-146.42 -142.46,-182.36z"/>
|
||||
<path class="fil3" d="M500939.21 105976.44l-21940.13 -7623.92c-100.11,-34.83 -205.41,-7.82 -276.28,70.98l-4476.23 4971.22c-61.73,68.53 -81.84,157.08 -55.74,245.41 26.09,88.44 90.88,151.91 179.82,176.07l23151.69 6278.53c96.16,26.1 192.41,-2.23 259.13,-76.35l3264.76 -3625.84c59.61,-66.2 80.32,-150.47 58.18,-236.78 -22.23,-86.21 -81.13,-150.08 -165.21,-179.32z"/>
|
||||
<path class="fil3" d="M495640.02 111827.39l-23689.94 -5680.77c-94.44,-22.54 -186.93,6.09 -251.81,78.28l-4995.4 5547.97c-64.68,71.88 -83.67,166.42 -51.79,257.6 31.89,91.29 105.61,153.42 200.95,169.37l25036.04 4185.62c89.46,15.03 173.43,-14.32 234.15,-81.74l3649.29 -4053.11c62.65,-69.45 82.45,-159.72 54.73,-248.97 -27.81,-89.35 -95.24,-152.52 -186.22,-174.24z"/>
|
||||
<path class="fil3" d="M490341.04 117683.01l-25439.87 -3737.32c-88.03,-12.9 -169.66,16.44 -229.17,82.55l-5511 6120.74c-67.31,74.83 -85.19,174.85 -47.83,268.27 37.37,93.52 119.11,153.63 219.53,161.44l26920.5 2092.82c82.55,6.49 156.26,-23.06 211.6,-84.58l4030.47 -4476.23c65.29,-72.49 84.08,-168.25 50.97,-260.04 -33.09,-91.68 -108.64,-153.52 -205.2,-167.64z"/>
|
||||
<path class="fil3" d="M485042.76 123542.4l-27189.77 -1793.88c-81.54,-5.39 -153.93,24.07 -208.56,84.79l-6023.87 6690.16c-69.66,77.37 -86.31,182.27 -43.97,277.51 42.44,95.04 131.49,152.92 235.57,152.92l28804.95 0c75.74,0 140.93,-29.04 191.71,-85.4l4408.59 -4896.18c67.73,-75.24 85.4,-175.86 47.32,-269.59 -38.08,-93.71 -121.04,-153.63 -221.97,-160.33z"/>
|
||||
<path class="fil4" d="M455586.23 0l23946.23 0c606.08,0 1127.69,232.22 1533.33,682.65l112395.09 124827.36c557.66,619.39 690.56,1458.5 351.63,2219.83 -338.93,761.34 -1051.53,1224.05 -1884.86,1224.05l-23946.32 0c-606.08,0 -1127.79,-232.32 -1533.33,-682.74l-112394.99 -124827.37c-557.65,-619.28 -690.56,-1458.4 -351.62,-2219.83 338.93,-761.23 1051.53,-1223.95 1884.85,-1223.95z"/>
|
||||
<path class="fil3" d="M546063.84 55728.5l-17150.76 -12698.51c-107.23,-79.4 -255.89,-64.37 -345.13,34.72l-3542.88 3934.72c-91.29,101.44 -87.94,255.88 7.72,353.25l14841.57 15109.54c51.28,52.29 114.74,78.28 188.06,77.17 73.2,-1.11 135.86,-29.14 185.51,-83.06l5852.07 -6345.75c51.38,-55.75 74.22,-123.57 67.11,-199.12 -7.2,-75.55 -42.34,-137.79 -103.26,-182.97z"/>
|
||||
<path class="fil3" d="M553805.64 48026.39l-20076.6 -10405.36c-105.7,-54.73 -230.69,-31.98 -310.3,56.46l-3337.36 3706.35c-51.68,57.47 -73.62,127.13 -64.38,203.79 9.35,76.66 47.42,139.01 111.4,182.27l17863.05 12103.08c102.35,69.36 235.87,57.58 324.52,-28.73l5550.91 -5404.09c61.23,-59.6 87.73,-137.89 75.24,-222.47 -12.49,-84.57 -60.52,-151.9 -136.46,-191.3z"/>
|
||||
<path class="fil3" d="M561723.31 40809.94l-23179.82 -8581.22c-101.13,-37.46 -208.97,-10.76 -281.16,69.36l-3126.37 3472.11c-56.35,62.65 -77.77,140.83 -61.12,223.48 16.55,82.55 66.61,146.42 142.86,182.36l20967.6 9879.29c95.64,45.08 202.87,29.55 281.77,-40.91l5338.48 -4770.28c69.36,-62.04 98.9,-148.96 81.54,-240.34 -17.27,-91.38 -76.57,-161.45 -163.78,-193.84z"/>
|
||||
<path class="fil3" d="M569965.29 33882.39l-26606.23 -7035.4c-95.86,-25.38 -191.31,3.05 -257.61,76.76l-2913.54 3235.73c-60.01,66.6 -80.62,151.69 -57.78,238.41 22.95,86.71 82.96,150.48 167.95,178.81l24313.19 8089.46c86.71,28.84 174.94,12.39 245.41,-45.69l5206.69 -4289.8c76.56,-63.05 109.05,-157.18 87.93,-254.14 -21.22,-96.87 -90.16,-168.86 -186.01,-194.14z"/>
|
||||
<path class="fil3" d="M578696.89 27121.04l-30520.74 -5649.4c-90.78,-16.86 -176.78,12.39 -238.52,81.02l-2700.82 2999.45c-62.74,69.66 -82.45,160.23 -54.32,249.79 28.02,89.45 96.06,152.61 187.33,173.83l28072.15 6551.78c77.27,18.07 151.08,2.33 214.34,-45.59l5149.43 -3901.82c83.26,-63.05 119.2,-163.37 95.14,-265.02 -24.06,-101.53 -101.23,-175.05 -203.98,-194.04z"/>
|
||||
<path class="fil3" d="M588128.6 20435.94l-35133.75 -4335.48c-86.1,-10.56 -165.1,18.88 -223.18,83.36l-2488.81 2764.08c-64.88,72.19 -83.87,167.13 -51.48,258.62 32.39,91.49 106.82,153.42 202.67,168.66l32447.23 5148.1c68.03,10.76 130.38,-3.45 187.03,-42.54l5175.31 -3576.7c89.76,-62.03 129.87,-167.64 103.87,-273.64 -26.1,-106.01 -110.58,-181.14 -218.91,-194.45z"/>
|
||||
<path class="fil3" d="M598567.77 13749.33l-40752.78 -3017.31c-82.24,-6.1 -155.55,23.35 -210.69,84.68l-2278.02 2529.94c-66.71,74.12 -84.88,172.61 -48.94,265.52 35.84,93.01 115.66,153.72 214.75,163.68l37715.35 3786.47c59,5.89 111.4,-6.29 161.76,-37.56l5315.54 -3299.09c96.46,-59.91 141.54,-170.28 114.43,-280.64 -27.11,-110.27 -118.09,-187.24 -231.41,-195.67z"/>
|
||||
<path class="fil3" d="M610537.63 6977.53l-47901.39 -1612.13c-78.8,-2.64 -147.64,26.61 -200.34,85.19l-2068.74 2297.51c-68.13,75.54 -85.49,177.08 -46.61,271.1 38.89,93.92 122.87,153.53 224.5,158.91l44316.99 2379.55c49.76,2.74 93.01,-7 136.77,-30.76l5653.05 -3065.04c103.77,-56.25 155.16,-170.99 128.05,-285.83 -27.11,-114.94 -124.29,-194.54 -242.28,-198.51z"/>
|
||||
<path class="fil3" d="M625135.21 0l-57676.8 0c-75.75,0 -140.94,29.04 -191.6,85.3l-1860.69 2066.41c-69.25,76.97 -86.11,180.84 -44.68,275.68 41.33,94.84 128.95,153.11 232.32,154.74l53096.1 819.1c39.4,0.61 73.41,-6.4 109.35,-22.54l6441.4 -2885.51c112.2,-50.26 172.41,-168.87 146.72,-289.19 -25.69,-120.32 -129.15,-203.99 -252.12,-203.99z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 95 KiB |
37
imgs/evox_logo_dark.svg
Normal file
37
imgs/evox_logo_dark.svg
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Creator: CorelDRAW -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="1685.1mm" height="1250mm" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
|
||||
viewBox="0 0 98668.67 73192.18"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
|
||||
<defs>
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
.fil0 {fill:#373435}
|
||||
.fil1 {fill:#C8383C}
|
||||
]]>
|
||||
</style>
|
||||
</defs>
|
||||
<g id="圖層_x0020_1">
|
||||
<metadata id="CorelCorpID_0Corel-Layer"/>
|
||||
<path class="fil0" d="M40050.09 46901.21l-8480.21 -8739.43c-29.28,-30.2 -65.7,-45.24 -107.77,-44.44 -42.02,0.81 -77.92,17.17 -106.05,48.41l-1335.32 1483.04c-53.25,59.13 -49.39,150.24 8.59,204.65l8862.24 8315.21c29.8,27.95 65.47,41.2 106.28,39.48 40.8,-1.73 75.26,-17.92 102.64,-48.24l953.34 -1058.81c51.64,-57.34 49.97,-144.48 -3.74,-199.87z"/>
|
||||
<path class="fil0" d="M37048.4 50208.28l-9473.43 -7636.42c-60.57,-48.81 -148.57,-41.78 -200.61,16.02l-1641.18 1822.6c-28.87,32.1 -41.38,70.77 -36.71,113.71 4.61,42.88 25.13,78.03 60.17,103.16l9931.78 7127.37c60.86,43.68 143.97,34.69 194.11,-20.98l1182.77 -1313.6c27.95,-30.95 40.45,-67.95 37.17,-109.55 -3.34,-41.61 -21.61,-76.13 -54.06,-102.3z"/>
|
||||
<path class="fil0" d="M34044 53518.76l-10466.54 -6533.35c-60.74,-37.92 -138.32,-26.97 -186.27,26.22l-1943.8 2158.77c-31.06,34.52 -43.39,77.17 -35.44,122.88 7.89,45.76 33.83,81.83 74.69,103.85l11001.36 5939.46c60.17,32.5 132.5,20 178.26,-30.83l1409.04 -1564.93c29.97,-33.26 42.42,-73.94 36.13,-118.32 -6.22,-44.38 -29.39,-80 -67.43,-103.74z"/>
|
||||
<path class="fil0" d="M31037.83 56832.92l-11459.76 -5430.34c-59.36,-28.12 -127.48,-14.52 -171.45,34.29l-2243.49 2491.7c-33.08,36.77 -45.07,83.34 -33.66,131.46 11.35,48.24 42.76,84.55 88.81,102.64l12070.95 4751.61c57.92,22.77 120.74,8.01 162.4,-38.27l1632.3 -1812.92c31.93,-35.5 44.09,-79.82 34.75,-126.68 -9.33,-46.8 -37.69,-83.11 -80.86,-103.51z"/>
|
||||
<path class="fil0" d="M28030.55 60150.55l-12452.87 -4327.22c-56.82,-19.77 -116.59,-4.44 -156.81,40.28l-2540.64 2821.59c-35.04,38.9 -46.45,89.15 -31.64,139.29 14.81,50.2 51.58,86.22 102.07,99.93l13140.53 3563.59c54.58,14.81 109.21,-1.26 147.08,-43.34l1853.03 -2057.97c33.83,-37.57 45.59,-85.41 33.02,-134.39 -12.62,-48.93 -46.05,-85.18 -93.77,-101.78z"/>
|
||||
<path class="fil0" d="M25022.81 63471.45l-13446.04 -3224.31c-53.6,-12.79 -106.1,3.45 -142.92,44.43l-2835.31 3148.94c-36.71,40.8 -47.49,94.46 -29.39,146.21 18.1,51.81 59.94,87.08 114.06,96.13l14210.06 2375.69c50.78,8.53 98.43,-8.13 132.9,-46.39l2071.28 -2300.48c35.56,-39.42 46.8,-90.65 31.06,-141.31 -15.79,-50.71 -54.06,-86.57 -105.7,-98.9z"/>
|
||||
<path class="fil0" d="M22015.19 66795.01l-14439.27 -2121.24c-49.96,-7.32 -96.3,9.33 -130.07,46.85l-3127.96 3474.03c-38.21,42.47 -48.35,99.24 -27.15,152.26 21.21,53.08 67.61,87.2 124.6,91.63l15279.65 1187.85c46.85,3.68 88.69,-13.09 120.1,-48.01l2287.63 -2540.64c37.06,-41.15 47.72,-95.5 28.93,-147.6 -18.78,-52.04 -61.66,-87.13 -116.47,-95.15z"/>
|
||||
<path class="fil0" d="M19007.97 70120.71l-15432.48 -1018.18c-46.28,-3.06 -87.37,13.66 -118.38,48.13l-3419.05 3797.23c-39.54,43.92 -48.99,103.45 -24.96,157.51 24.09,53.95 74.63,86.79 133.71,86.79l16349.23 0c42.99,0 79.99,-16.48 108.81,-48.47l2502.25 -2779c38.44,-42.7 48.47,-99.82 26.86,-153.01 -21.61,-53.19 -68.7,-87.2 -125.98,-91z"/>
|
||||
<path class="fil1" d="M2288.91 0l13591.5 0c344,0 640.06,131.8 870.3,387.46l63793.67 70850.03c316.52,351.56 391.95,827.82 199.58,1259.94 -192.37,432.13 -596.83,694.75 -1069.82,694.75l-13591.55 0c-344,0 -640.12,-131.86 -870.3,-387.51l-63793.62 -70850.03c-316.51,-351.49 -391.95,-827.76 -199.57,-1259.94 192.37,-432.06 596.83,-694.69 1069.81,-694.69z"/>
|
||||
<path class="fil0" d="M53642.57 31630.61l-9734.5 -7207.47c-60.86,-45.07 -145.24,-36.54 -195.89,19.71l-2010.88 2233.29c-51.81,57.58 -49.91,145.23 4.38,200.5l8423.84 8575.93c29.11,29.68 65.12,44.43 106.74,43.8 41.55,-0.63 77.11,-16.54 105.29,-47.14l3321.54 -3601.75c29.16,-31.64 42.12,-70.14 38.09,-113.01 -4.09,-42.88 -24.03,-78.21 -58.61,-103.85z"/>
|
||||
<path class="fil0" d="M58036.69 27259.02l-11395.16 -5905.92c-59.99,-31.06 -130.94,-18.15 -176.12,32.05l-1894.23 2103.67c-29.34,32.62 -41.78,72.16 -36.54,115.67 5.3,43.51 26.92,78.9 63.23,103.45l10138.79 6869.51c58.09,39.37 133.88,32.68 184.19,-16.31l3150.61 -3067.27c34.75,-33.83 49.79,-78.26 42.7,-126.27 -7.09,-48 -34.35,-86.21 -77.45,-108.58z"/>
|
||||
<path class="fil0" d="M62530.64 23163.08l-13156.5 -4870.57c-57.4,-21.26 -118.61,-6.11 -159.58,39.37l-1774.48 1970.71c-31.98,35.56 -44.14,79.93 -34.69,126.84 9.39,46.85 37.81,83.11 81.09,103.51l11900.88 5607.33c54.29,25.59 115.15,16.77 159.93,-23.22l3030.04 -2707.54c39.37,-35.21 56.14,-84.55 46.28,-136.41 -9.8,-51.87 -43.46,-91.64 -92.96,-110.02z"/>
|
||||
<path class="fil0" d="M67208.65 19231.11l-15101.27 -3993.18c-54.41,-14.4 -108.58,1.73 -146.21,43.57l-1653.68 1836.55c-34.06,37.8 -45.76,86.1 -32.8,135.32 13.03,49.21 47.09,85.41 95.33,101.49l13799.78 4591.45c49.21,16.37 99.3,7.03 139.29,-25.93l2955.24 -2434.82c43.45,-35.79 61.9,-89.21 49.91,-144.25 -12.04,-54.98 -51.18,-95.84 -105.58,-110.19z"/>
|
||||
<path class="fil0" d="M72164.57 15393.47l-17323.09 -3206.51c-51.53,-9.57 -100.34,7.03 -135.38,45.99l-1532.94 1702.44c-35.61,39.54 -46.8,90.95 -30.83,141.78 15.9,50.77 54.52,86.62 106.33,98.66l15933.31 3718.68c43.86,10.26 85.75,1.32 121.66,-25.87l2922.73 -2214.61c47.26,-35.79 67.66,-92.73 54,-150.42 -13.65,-57.63 -57.46,-99.35 -115.78,-110.13z"/>
|
||||
<path class="fil0" d="M77517.86 11599.12l-19941.36 -2460.75c-48.87,-6 -93.71,10.72 -126.68,47.31l-1412.61 1568.85c-36.82,40.98 -47.6,94.86 -29.22,146.79 18.39,51.93 60.63,87.08 115.03,95.73l18416.54 2921.98c38.61,6.11 74,-1.96 106.16,-24.15l2937.42 -2030.08c50.95,-35.21 73.71,-95.15 58.96,-155.31 -14.81,-60.17 -62.76,-102.81 -124.25,-110.37z"/>
|
||||
<path class="fil0" d="M83442.97 7803.9l-23130.63 -1712.58c-46.68,-3.46 -88.29,13.25 -119.58,48.06l-1292.97 1435.95c-37.86,42.07 -48.18,97.97 -27.78,150.71 20.34,52.79 65.64,87.25 121.89,92.9l21406.64 2149.14c33.49,3.34 63.23,-3.57 91.81,-21.32l3017.02 -1872.51c54.75,-34 80.34,-96.65 64.95,-159.29 -15.39,-62.59 -67.03,-106.28 -131.34,-111.06z"/>
|
||||
<path class="fil0" d="M90236.87 3960.34l-27188.07 -915.02c-44.72,-1.5 -83.8,15.1 -113.71,48.35l-1174.18 1304.03c-38.67,42.87 -48.52,100.51 -26.45,153.87 22.07,53.31 69.74,87.14 127.42,90.2l25153.62 1350.59c28.24,1.56 52.79,-3.98 77.63,-17.46l3208.58 -1739.67c58.9,-31.93 88.06,-97.05 72.68,-162.23 -15.39,-65.24 -70.55,-110.42 -137.51,-112.67z"/>
|
||||
<path class="fil0" d="M98522.23 0l-32736.44 0c-43,0 -80,16.48 -108.75,48.41l-1056.1 1172.86c-39.31,43.69 -48.87,102.64 -25.36,156.47 23.46,53.83 73.19,86.91 131.86,87.83l30136.51 464.91c22.36,0.35 41.67,-3.63 62.07,-12.79l3656.04 -1637.77c63.68,-28.53 97.86,-95.85 83.28,-164.14 -14.58,-68.29 -73.3,-115.78 -143.1,-115.78z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.9 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 91 KiB |
37
imgs/evox_logo_light.svg
Normal file
37
imgs/evox_logo_light.svg
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Creator: CorelDRAW -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="1685.1mm" height="1250mm" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
|
||||
viewBox="0 0 98668.67 73192.18"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
|
||||
<defs>
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
.fil0 {fill:#FEFEFE}
|
||||
.fil1 {fill:#C8383C}
|
||||
]]>
|
||||
</style>
|
||||
</defs>
|
||||
<g id="圖層_x0020_1">
|
||||
<metadata id="CorelCorpID_0Corel-Layer"/>
|
||||
<path class="fil0" d="M40050.09 46901.21l-8480.21 -8739.43c-29.28,-30.2 -65.7,-45.24 -107.77,-44.44 -42.02,0.81 -77.92,17.17 -106.05,48.41l-1335.32 1483.04c-53.25,59.13 -49.39,150.24 8.59,204.65l8862.24 8315.21c29.8,27.95 65.47,41.2 106.28,39.48 40.8,-1.73 75.26,-17.92 102.64,-48.24l953.34 -1058.81c51.64,-57.34 49.97,-144.48 -3.74,-199.87z"/>
|
||||
<path class="fil0" d="M37048.4 50208.28l-9473.43 -7636.42c-60.57,-48.81 -148.57,-41.78 -200.61,16.02l-1641.18 1822.6c-28.87,32.1 -41.38,70.77 -36.71,113.71 4.61,42.88 25.13,78.03 60.17,103.16l9931.78 7127.37c60.86,43.68 143.97,34.69 194.11,-20.98l1182.77 -1313.6c27.95,-30.95 40.45,-67.95 37.17,-109.55 -3.34,-41.61 -21.61,-76.13 -54.06,-102.3z"/>
|
||||
<path class="fil0" d="M34044 53518.76l-10466.54 -6533.35c-60.74,-37.92 -138.32,-26.97 -186.27,26.22l-1943.8 2158.77c-31.06,34.52 -43.39,77.17 -35.44,122.88 7.89,45.76 33.83,81.83 74.69,103.85l11001.36 5939.46c60.17,32.5 132.5,20 178.26,-30.83l1409.04 -1564.93c29.97,-33.26 42.42,-73.94 36.13,-118.32 -6.22,-44.38 -29.39,-80 -67.43,-103.74z"/>
|
||||
<path class="fil0" d="M31037.83 56832.92l-11459.76 -5430.34c-59.36,-28.12 -127.48,-14.52 -171.45,34.29l-2243.49 2491.7c-33.08,36.77 -45.07,83.34 -33.66,131.46 11.35,48.24 42.76,84.55 88.81,102.64l12070.95 4751.61c57.92,22.77 120.74,8.01 162.4,-38.27l1632.3 -1812.92c31.93,-35.5 44.09,-79.82 34.75,-126.68 -9.33,-46.8 -37.69,-83.11 -80.86,-103.51z"/>
|
||||
<path class="fil0" d="M28030.55 60150.55l-12452.87 -4327.22c-56.82,-19.77 -116.59,-4.44 -156.81,40.28l-2540.64 2821.59c-35.04,38.9 -46.45,89.15 -31.64,139.29 14.81,50.2 51.58,86.22 102.07,99.93l13140.53 3563.59c54.58,14.81 109.21,-1.26 147.08,-43.34l1853.03 -2057.97c33.83,-37.57 45.59,-85.41 33.02,-134.39 -12.62,-48.93 -46.05,-85.18 -93.77,-101.78z"/>
|
||||
<path class="fil0" d="M25022.81 63471.45l-13446.04 -3224.31c-53.6,-12.79 -106.1,3.45 -142.92,44.43l-2835.31 3148.94c-36.71,40.8 -47.49,94.46 -29.39,146.21 18.1,51.81 59.94,87.08 114.06,96.13l14210.06 2375.69c50.78,8.53 98.43,-8.13 132.9,-46.39l2071.28 -2300.48c35.56,-39.42 46.8,-90.65 31.06,-141.31 -15.79,-50.71 -54.06,-86.57 -105.7,-98.9z"/>
|
||||
<path class="fil0" d="M22015.19 66795.01l-14439.27 -2121.24c-49.96,-7.32 -96.3,9.33 -130.07,46.85l-3127.96 3474.03c-38.21,42.47 -48.35,99.24 -27.15,152.26 21.21,53.08 67.61,87.2 124.6,91.63l15279.65 1187.85c46.85,3.68 88.69,-13.09 120.1,-48.01l2287.63 -2540.64c37.06,-41.15 47.72,-95.5 28.93,-147.6 -18.78,-52.04 -61.66,-87.13 -116.47,-95.15z"/>
|
||||
<path class="fil0" d="M19007.97 70120.71l-15432.48 -1018.18c-46.28,-3.06 -87.37,13.66 -118.38,48.13l-3419.05 3797.23c-39.54,43.92 -48.99,103.45 -24.96,157.51 24.09,53.95 74.63,86.79 133.71,86.79l16349.23 0c42.99,0 79.99,-16.48 108.81,-48.47l2502.25 -2779c38.44,-42.7 48.47,-99.82 26.86,-153.01 -21.61,-53.19 -68.7,-87.2 -125.98,-91z"/>
|
||||
<path class="fil1" d="M2288.91 0l13591.5 0c344,0 640.06,131.8 870.3,387.46l63793.67 70850.03c316.52,351.56 391.95,827.82 199.58,1259.94 -192.37,432.13 -596.83,694.75 -1069.82,694.75l-13591.55 0c-344,0 -640.12,-131.86 -870.3,-387.51l-63793.62 -70850.03c-316.51,-351.49 -391.95,-827.76 -199.57,-1259.94 192.37,-432.06 596.83,-694.69 1069.81,-694.69z"/>
|
||||
<path class="fil0" d="M53642.57 31630.61l-9734.5 -7207.47c-60.86,-45.07 -145.24,-36.54 -195.89,19.71l-2010.88 2233.29c-51.81,57.58 -49.91,145.23 4.38,200.5l8423.84 8575.93c29.11,29.68 65.12,44.43 106.74,43.8 41.55,-0.63 77.11,-16.54 105.29,-47.14l3321.54 -3601.75c29.16,-31.64 42.12,-70.14 38.09,-113.01 -4.09,-42.88 -24.03,-78.21 -58.61,-103.85z"/>
|
||||
<path class="fil0" d="M58036.69 27259.02l-11395.16 -5905.92c-59.99,-31.06 -130.94,-18.15 -176.12,32.05l-1894.23 2103.67c-29.34,32.62 -41.78,72.16 -36.54,115.67 5.3,43.51 26.92,78.9 63.23,103.45l10138.79 6869.51c58.09,39.37 133.88,32.68 184.19,-16.31l3150.61 -3067.27c34.75,-33.83 49.79,-78.26 42.7,-126.27 -7.09,-48 -34.35,-86.21 -77.45,-108.58z"/>
|
||||
<path class="fil0" d="M62530.64 23163.08l-13156.5 -4870.57c-57.4,-21.26 -118.61,-6.11 -159.58,39.37l-1774.48 1970.71c-31.98,35.56 -44.14,79.93 -34.69,126.84 9.39,46.85 37.81,83.11 81.09,103.51l11900.88 5607.33c54.29,25.59 115.15,16.77 159.93,-23.22l3030.04 -2707.54c39.37,-35.21 56.14,-84.55 46.28,-136.41 -9.8,-51.87 -43.46,-91.64 -92.96,-110.02z"/>
|
||||
<path class="fil0" d="M67208.65 19231.11l-15101.27 -3993.18c-54.41,-14.4 -108.58,1.73 -146.21,43.57l-1653.68 1836.55c-34.06,37.8 -45.76,86.1 -32.8,135.32 13.03,49.21 47.09,85.41 95.33,101.49l13799.78 4591.45c49.21,16.37 99.3,7.03 139.29,-25.93l2955.24 -2434.82c43.45,-35.79 61.9,-89.21 49.91,-144.25 -12.04,-54.98 -51.18,-95.84 -105.58,-110.19z"/>
|
||||
<path class="fil0" d="M72164.57 15393.47l-17323.09 -3206.51c-51.53,-9.57 -100.34,7.03 -135.38,45.99l-1532.94 1702.44c-35.61,39.54 -46.8,90.95 -30.83,141.78 15.9,50.77 54.52,86.62 106.33,98.66l15933.31 3718.68c43.86,10.26 85.75,1.32 121.66,-25.87l2922.73 -2214.61c47.26,-35.79 67.66,-92.73 54,-150.42 -13.65,-57.63 -57.46,-99.35 -115.78,-110.13z"/>
|
||||
<path class="fil0" d="M77517.86 11599.12l-19941.36 -2460.75c-48.87,-6 -93.71,10.72 -126.68,47.31l-1412.61 1568.85c-36.82,40.98 -47.6,94.86 -29.22,146.79 18.39,51.93 60.63,87.08 115.03,95.73l18416.54 2921.98c38.61,6.11 74,-1.96 106.16,-24.15l2937.42 -2030.08c50.95,-35.21 73.71,-95.15 58.96,-155.31 -14.81,-60.17 -62.76,-102.81 -124.25,-110.37z"/>
|
||||
<path class="fil0" d="M83442.97 7803.9l-23130.63 -1712.58c-46.68,-3.46 -88.29,13.25 -119.58,48.06l-1292.97 1435.95c-37.86,42.07 -48.18,97.97 -27.78,150.71 20.34,52.79 65.64,87.25 121.89,92.9l21406.64 2149.14c33.49,3.34 63.23,-3.57 91.81,-21.32l3017.02 -1872.51c54.75,-34 80.34,-96.65 64.95,-159.29 -15.39,-62.59 -67.03,-106.28 -131.34,-111.06z"/>
|
||||
<path class="fil0" d="M90236.87 3960.34l-27188.07 -915.02c-44.72,-1.5 -83.8,15.1 -113.71,48.35l-1174.18 1304.03c-38.67,42.87 -48.52,100.51 -26.45,153.87 22.07,53.31 69.74,87.14 127.42,90.2l25153.62 1350.59c28.24,1.56 52.79,-3.98 77.63,-17.46l3208.58 -1739.67c58.9,-31.93 88.06,-97.05 72.68,-162.23 -15.39,-65.24 -70.55,-110.42 -137.51,-112.67z"/>
|
||||
<path class="fil0" d="M98522.23 0l-32736.44 0c-43,0 -80,16.48 -108.75,48.41l-1056.1 1172.86c-39.31,43.69 -48.87,102.64 -25.36,156.47 23.46,53.83 73.19,86.91 131.86,87.83l30136.51 464.91c22.36,0.35 41.67,-3.63 62.07,-12.79l3656.04 -1637.77c63.68,-28.53 97.86,-95.85 83.28,-164.14 -14.58,-68.29 -73.3,-115.78 -143.1,-115.78z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.9 KiB |
@@ -7,7 +7,12 @@ import sympy as sp
|
||||
|
||||
from .base import BaseGenome
|
||||
from .gene import DefaultNode, DefaultConn
|
||||
from .operations import DefaultMutation, DefaultCrossover, DefaultDistance
|
||||
from .operations import (
|
||||
DefaultMutation,
|
||||
DefaultCrossover,
|
||||
DefaultDistance,
|
||||
CombinedMutation,
|
||||
)
|
||||
from .utils import unflatten_conns, extract_gene_attrs, extract_gene_attrs
|
||||
|
||||
from tensorneat.common import (
|
||||
@@ -40,8 +45,12 @@ class DefaultGenome(BaseGenome):
|
||||
output_transform=None,
|
||||
input_transform=None,
|
||||
init_hidden_layers=(),
|
||||
duplication_rate: float = 0.0,
|
||||
):
|
||||
|
||||
# If a duplication_rate is specified, wrap the default mutation with the CombinedMutation
|
||||
if duplication_rate > 0.0:
|
||||
# Use CombinedMutation which includes standard mutation plus module duplication
|
||||
mutation = CombinedMutation(duplication_rate=duplication_rate)
|
||||
super().__init__(
|
||||
num_inputs,
|
||||
num_outputs,
|
||||
@@ -66,7 +75,6 @@ class DefaultGenome(BaseGenome):
|
||||
return seqs, nodes, conns, u_conns
|
||||
|
||||
def forward(self, state, transformed, inputs):
|
||||
|
||||
if self.input_transform is not None:
|
||||
inputs = self.input_transform(inputs)
|
||||
|
||||
@@ -133,9 +141,7 @@ class DefaultGenome(BaseGenome):
|
||||
network["topo_order"] = topo_order
|
||||
network["topo_layers"] = topo_layers
|
||||
network["useful_nodes"] = find_useful_nodes(
|
||||
set(network["nodes"]),
|
||||
set(network["conns"]),
|
||||
set(self.output_idx)
|
||||
set(network["nodes"]), set(network["conns"]), set(self.output_idx)
|
||||
)
|
||||
return network
|
||||
|
||||
@@ -147,7 +153,6 @@ class DefaultGenome(BaseGenome):
|
||||
sympy_output_transform=None,
|
||||
backend="jax",
|
||||
):
|
||||
|
||||
assert backend in ["jax", "numpy"], "backend should be 'jax' or 'numpy'"
|
||||
|
||||
if sympy_input_transform is None and self.input_transform is not None:
|
||||
@@ -187,7 +192,6 @@ class DefaultGenome(BaseGenome):
|
||||
nodes_exprs = {}
|
||||
args_symbols = {}
|
||||
for i in order:
|
||||
|
||||
if i in input_idx:
|
||||
nodes_exprs[symbols[-i - 1]] = symbols[
|
||||
-i - 1
|
||||
@@ -258,7 +262,7 @@ class DefaultGenome(BaseGenome):
|
||||
output_exprs,
|
||||
forward_func,
|
||||
network["topo_order"],
|
||||
network["useful_nodes"]
|
||||
network["useful_nodes"],
|
||||
)
|
||||
|
||||
def visualize(
|
||||
@@ -298,7 +302,7 @@ class DefaultGenome(BaseGenome):
|
||||
nodes_y = []
|
||||
for node in nodes:
|
||||
node_y = 0
|
||||
for y, last_node in enumerate(topo_layers[layer-1]):
|
||||
for y, last_node in enumerate(topo_layers[layer - 1]):
|
||||
if (last_node, node) in conns_list:
|
||||
node_y += y
|
||||
nodes_y.append(node_y)
|
||||
@@ -395,7 +399,7 @@ class DefaultGenome(BaseGenome):
|
||||
edgecolors=edgecolors,
|
||||
arrowstyle=arrowstyle,
|
||||
arrowsize=arrowsize,
|
||||
edge_color=edge_color
|
||||
edge_color=edge_color,
|
||||
)
|
||||
plt.savefig(save_path, dpi=save_dpi)
|
||||
plt.close()
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
from .crossover import BaseCrossover, DefaultCrossover
|
||||
from .mutation import BaseMutation, DefaultMutation
|
||||
from .mutation import BaseMutation, DefaultMutation, CombinedMutation, ModuleDuplication
|
||||
from .distance import BaseDistance, DefaultDistance
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
from .base import BaseMutation
|
||||
from .default import DefaultMutation
|
||||
from .module_duplication import CombinedMutation, ModuleDuplication
|
||||
|
||||
141
src/tensorneat/genome/operations/mutation/module_duplication.py
Normal file
141
src/tensorneat/genome/operations/mutation/module_duplication.py
Normal file
@@ -0,0 +1,141 @@
|
||||
"""Module Duplication Mutation
|
||||
|
||||
Implements the MEND *module duplication* operator. It duplicates a hidden
|
||||
module (a hidden node together with all its incoming and outgoing connections).
|
||||
The operator fires with probability ``duplication_rate``.
|
||||
"""
|
||||
|
||||
import jax
|
||||
import jax.numpy as jnp
|
||||
from .base import BaseMutation
|
||||
from .default import DefaultMutation
|
||||
from ...utils import add_node, add_conn, extract_gene_attrs
|
||||
from tensorneat.common import I_INF
|
||||
|
||||
|
||||
class ModuleDuplication(BaseMutation):
|
||||
"""Duplicate a hidden module (node + its connections).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
duplication_rate: float, optional
|
||||
Probability that the duplication operator fires during a mutation
|
||||
step. Must be in ``[0, 1]``. Default ``0.0`` (disabled).
|
||||
"""
|
||||
|
||||
def __init__(self, duplication_rate: float = 0.0):
|
||||
self.duplication_rate = duplication_rate
|
||||
self._helper = DefaultMutation()
|
||||
|
||||
def _choose_node_key(self, key, nodes, input_idx, output_idx):
|
||||
return self._helper.choose_node_key(
|
||||
key,
|
||||
nodes,
|
||||
input_idx,
|
||||
output_idx,
|
||||
allow_input_keys=False,
|
||||
allow_output_keys=False,
|
||||
)
|
||||
|
||||
def __call__(
|
||||
self, state, genome, randkey, nodes, conns, new_node_key, new_conn_key
|
||||
):
|
||||
"""Apply module duplication.
|
||||
|
||||
If the random draw is lower than ``duplication_rate`` a hidden node is
|
||||
selected and duplicated (its connections are copied). Otherwise the genome
|
||||
is returned unchanged.
|
||||
"""
|
||||
fire = jax.random.uniform(randkey) < self.duplication_rate
|
||||
|
||||
n_fixed = len(genome.conn_gene.fixed_attrs)
|
||||
|
||||
def duplicate(_):
|
||||
node_key, node_idx = self._choose_node_key(
|
||||
randkey, nodes, genome.input_idx, genome.output_idx
|
||||
)
|
||||
|
||||
def no_node():
|
||||
return nodes, conns
|
||||
|
||||
def do_dup():
|
||||
# Add a new hidden node with identity attributes.
|
||||
new_nodes = add_node(
|
||||
nodes,
|
||||
jnp.array([new_node_key]),
|
||||
genome.node_gene.new_identity_attrs(state),
|
||||
)
|
||||
|
||||
# Use jax.lax.scan to iterate over all connections and
|
||||
# conditionally copy incoming ones (target == node_key).
|
||||
def copy_incoming(carry, conn):
|
||||
conns_acc = carry
|
||||
is_incoming = (conn[1] == node_key) & ~jnp.isnan(conn[0])
|
||||
attrs = conn[n_fixed:]
|
||||
src = conn[0]
|
||||
fix = jnp.array([src, new_node_key])
|
||||
new_conn = jnp.concatenate((fix, attrs))
|
||||
pos = jnp.argmax(jnp.isnan(conns_acc[:, 0]))
|
||||
has_space = jnp.isnan(conns_acc[pos, 0])
|
||||
should_add = is_incoming & has_space
|
||||
conns_acc = jnp.where(
|
||||
should_add,
|
||||
conns_acc.at[pos].set(new_conn),
|
||||
conns_acc,
|
||||
)
|
||||
return conns_acc, None
|
||||
|
||||
new_conns, _ = jax.lax.scan(copy_incoming, conns, conns)
|
||||
|
||||
# Copy outgoing connections (source == node_key).
|
||||
def copy_outgoing(carry, conn):
|
||||
conns_acc = carry
|
||||
is_outgoing = (conn[0] == node_key) & ~jnp.isnan(conn[0])
|
||||
attrs = conn[n_fixed:]
|
||||
tgt = conn[1]
|
||||
fix = jnp.array([new_node_key, tgt])
|
||||
new_conn = jnp.concatenate((fix, attrs))
|
||||
pos = jnp.argmax(jnp.isnan(conns_acc[:, 0]))
|
||||
has_space = jnp.isnan(conns_acc[pos, 0])
|
||||
should_add = is_outgoing & has_space
|
||||
conns_acc = jnp.where(
|
||||
should_add,
|
||||
conns_acc.at[pos].set(new_conn),
|
||||
conns_acc,
|
||||
)
|
||||
return conns_acc, None
|
||||
|
||||
# Scan over the ORIGINAL conns for outgoing check, but
|
||||
# accumulate into the already-updated new_conns.
|
||||
new_conns, _ = jax.lax.scan(copy_outgoing, new_conns, conns)
|
||||
|
||||
return new_nodes, new_conns
|
||||
|
||||
return jax.lax.cond(node_idx == I_INF, no_node, do_dup)
|
||||
|
||||
return jax.lax.cond(fire, duplicate, lambda _: (nodes, conns), operand=None)
|
||||
|
||||
|
||||
class CombinedMutation(BaseMutation):
|
||||
"""Combine ``DefaultMutation`` with optional ``ModuleDuplication``.
|
||||
|
||||
The combined mutation first runs the standard NEAT structural/value
|
||||
mutations and then (with the configured ``duplication_rate``) may duplicate a
|
||||
module.
|
||||
"""
|
||||
|
||||
def __init__(self, duplication_rate: float = 0.0, **default_kwargs):
|
||||
self.default_mut = DefaultMutation(**default_kwargs)
|
||||
self.dup_mut = ModuleDuplication(duplication_rate)
|
||||
|
||||
def __call__(
|
||||
self, state, genome, randkey, nodes, conns, new_node_key, new_conn_key
|
||||
):
|
||||
k1, k2 = jax.random.split(randkey)
|
||||
nodes, conns = self.default_mut(
|
||||
state, genome, k1, nodes, conns, new_node_key, new_conn_key
|
||||
)
|
||||
nodes, conns = self.dup_mut(
|
||||
state, genome, k2, nodes, conns, new_node_key, new_conn_key
|
||||
)
|
||||
return nodes, conns
|
||||
298
src/tensorneat/genome/operations/mutation/recurrent.py
Normal file
298
src/tensorneat/genome/operations/mutation/recurrent.py
Normal file
@@ -0,0 +1,298 @@
|
||||
# recurrent_mutation.py
|
||||
import jax
|
||||
import jax.numpy as jnp
|
||||
|
||||
# same helpers as DefaultMutation
|
||||
from tensorneat.common import fetch_first, I_INF, check_cycles, fetch_random
|
||||
from tensorneat.genome.operations.mutation.default import DefaultMutation
|
||||
from tensorneat.genome.utils import (
|
||||
extract_gene_attrs,
|
||||
add_conn,
|
||||
add_node,
|
||||
unflatten_conns,
|
||||
delete_conn_by_pos,
|
||||
delete_node_by_pos,
|
||||
set_gene_attrs,
|
||||
)
|
||||
|
||||
class RecurrentMutation(DefaultMutation):
|
||||
"""
|
||||
A DefaultMutation variant that *biases* (not forces) evolution toward
|
||||
recurrent connections, controlled by the parameter "p_recur".
|
||||
|
||||
Applies add/delete node and delete connection mutations identically to
|
||||
the user's original implementation provided, but uses an optimized
|
||||
add-connection strategy with cycle bias and retries.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p_recur : float, default 0.1
|
||||
Probability (0 to 1) that any single *successful* add-connection
|
||||
mutation *must* result in forming a cycle in the graph.
|
||||
max_conn_tries : int, default 20
|
||||
Maximum number of distinct (source, target) node pairs to sample
|
||||
when attempting the add-connection mutation before giving up for
|
||||
this genome in this generation.
|
||||
conn_add : float
|
||||
Probability of attempting connection addition. Inherited from
|
||||
DefaultMutation.
|
||||
conn_delete : float
|
||||
Probability of attempting connection deletion. Inherited from
|
||||
DefaultMutation.
|
||||
node_add : float
|
||||
Probability of attempting node addition. Inherited from DefaultMutation.
|
||||
node_delete : float
|
||||
Probability of attempting node deletion. Inherited from DefaultMutation.
|
||||
kwargs : Other arguments accepted by DefaultMutation.__init__
|
||||
"""
|
||||
# constructor
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
p_recur: float = 0.1,
|
||||
max_conn_tries: int = 20,
|
||||
**kwargs # Pass conn_add, conn_delete etc. through to base class
|
||||
):
|
||||
# Initialize base class probabilities from DefaultMutation
|
||||
super().__init__(**kwargs)
|
||||
|
||||
if not 0.0 <= p_recur <= 1.0:
|
||||
raise ValueError("p_recur must be in [0, 1]")
|
||||
if max_conn_tries < 1:
|
||||
raise ValueError("max_conn_tries must be >= 1")
|
||||
|
||||
self.p_recur = float(p_recur)
|
||||
self.max_conn_tries = int(max_conn_tries)
|
||||
|
||||
# structural mutation (all value‑mutation logic is inherited intact)
|
||||
def mutate_structure(
|
||||
self, state, genome, randkey, nodes, conns, new_node_key, new_conn_key
|
||||
):
|
||||
"""
|
||||
Apply ONE structural mutation (node-add/del, conn-add/del) chosen
|
||||
according to the probabilities stored in this object.
|
||||
Uses the custom `_mutate_add_conn_recurrent_optimized`.
|
||||
Uses user's original implementations for add_node, delete_node,
|
||||
delete_conn.
|
||||
"""
|
||||
# Helper functions (kept as per user request, structure preserved
|
||||
def mutate_add_node(key_, nodes_, conns_):
|
||||
remain_node_space = jnp.isnan(nodes_[:, 0]).sum()
|
||||
remain_conn_space = jnp.isnan(conns_[:, 0]).sum()
|
||||
|
||||
i_key, o_key, idx = self.choose_connection_key(key_, conns_)
|
||||
|
||||
def successful_add_node():
|
||||
# remove the original connection and record its attrs
|
||||
original_attrs = extract_gene_attrs(
|
||||
genome.conn_gene, conns_[idx]
|
||||
)
|
||||
new_conns = delete_conn_by_pos(conns_, idx)
|
||||
|
||||
# add a new node with identity attrs
|
||||
new_nodes = add_node(
|
||||
nodes_,
|
||||
jnp.array([new_node_key]),
|
||||
genome.node_gene.new_identity_attrs(state)
|
||||
)
|
||||
|
||||
# build two replacement connections
|
||||
if "historical_marker" in genome.conn_gene.fixed_attrs:
|
||||
f1 = jnp.array([i_key, new_node_key, new_conn_key[0]])
|
||||
f2 = jnp.array([new_node_key, o_key, new_conn_key[1]])
|
||||
else:
|
||||
f1 = jnp.array([i_key, new_node_key])
|
||||
f2 = jnp.array([new_node_key, o_key])
|
||||
|
||||
new_conns = add_conn(
|
||||
new_conns,
|
||||
f1,
|
||||
genome.conn_gene.new_identity_attrs(state)
|
||||
)
|
||||
new_conns = add_conn(new_conns, f2, original_attrs)
|
||||
return new_nodes, new_conns
|
||||
|
||||
cond_do_nothing = (idx == I_INF) | \
|
||||
(remain_node_space < 1) | \
|
||||
(remain_conn_space < 2)
|
||||
return jax.lax.cond(
|
||||
cond_do_nothing, # condition for doing nothing
|
||||
lambda: (nodes_, conns_), # do nothing branch (if cond is true)
|
||||
successful_add_node # do add branch (if cond is false)
|
||||
)
|
||||
|
||||
def mutate_delete_node(key_, nodes_, conns_):
|
||||
k, idx = self.choose_node_key(
|
||||
key_, nodes_, genome.input_idx, genome.output_idx,
|
||||
allow_input_keys=False, allow_output_keys=False,
|
||||
)
|
||||
|
||||
def do():
|
||||
# delete the node
|
||||
new_nodes = delete_node_by_pos(nodes_, idx)
|
||||
|
||||
# delete all connections
|
||||
new_conns = jnp.where(
|
||||
((conns_[:, 0] == k) | (conns_[:, 1] == k))[:, None],
|
||||
jnp.nan, conns_
|
||||
)
|
||||
return new_nodes, new_conns
|
||||
|
||||
return jax.lax.cond(
|
||||
idx == I_INF, # cond to determine "doing nothing"
|
||||
lambda: (nodes_, conns_), # Do nothing branch
|
||||
do # do delete branch
|
||||
)
|
||||
|
||||
# NEW biased add‑connection with optimizations and p_recur bias
|
||||
def _mutate_add_conn_recurrent_optimized(key_, nodes_, conns_):
|
||||
"""
|
||||
Optimized: Attempts to insert one connection with recurrent bias.
|
||||
Makes up to "self.max_conn_tries" draws.
|
||||
Computes graph structure once before vmap.
|
||||
Checks prerequisites before cycle check.
|
||||
"""
|
||||
remain_conn_space = jnp.isnan(conns_[:, 0]).sum()
|
||||
space_available = remain_conn_space >= 1
|
||||
|
||||
# Optimization: Calculate graph structure ONCE before vmap
|
||||
u_conns = unflatten_conns(nodes_, conns_)
|
||||
conns_exist_matrix = u_conns != I_INF
|
||||
|
||||
# Function for a single attempt
|
||||
def attempt(k_triplet):
|
||||
"""One sampling attempt; returns (accept?, i_key, o_key)."""
|
||||
k1_node, k2_node, k_recur = jax.random.split(k_triplet, 3)
|
||||
|
||||
# 1. Sample endpoints
|
||||
i_key, from_idx = self.choose_node_key(
|
||||
k1_node, nodes_, genome.input_idx, genome.output_idx,
|
||||
allow_input_keys=True, allow_output_keys=True,
|
||||
)
|
||||
o_key, to_idx = self.choose_node_key(
|
||||
k2_node, nodes_, genome.input_idx, genome.output_idx,
|
||||
allow_input_keys=False, allow_output_keys=True,
|
||||
)
|
||||
|
||||
# 2. Basic checks: nodes selected? space available?
|
||||
nodes_chosen = (from_idx != I_INF) & (to_idx != I_INF)
|
||||
prereqs_met = nodes_chosen & space_available
|
||||
|
||||
# --- Nested conditional logic for efficiency ---
|
||||
def check_existence_and_cycle():
|
||||
# 3. Duplicate check (only if prereqs met)
|
||||
exists = fetch_first(
|
||||
(conns_[:, 0] == i_key) & (conns_[:, 1] == o_key)
|
||||
) != I_INF
|
||||
not_duplicate = ~exists
|
||||
|
||||
def check_cycle_logic():
|
||||
# 4. Cycle check (only if valid, non-duplicate candidate)
|
||||
forms_cy = check_cycles(
|
||||
nodes_,
|
||||
conns_exist_matrix,
|
||||
from_idx, to_idx
|
||||
)
|
||||
|
||||
# 5. Decide if we *require* a cycle
|
||||
force_recur = jax.random.uniform(k_recur) < self.p_recur
|
||||
|
||||
# 6. Final check: cycle requirement satisfaction
|
||||
cycle_req_satisfied = (force_recur & forms_cy) | \
|
||||
(~force_recur)
|
||||
|
||||
# Attempt is valid if cycle requirement is met
|
||||
is_valid = cycle_req_satisfied
|
||||
return is_valid, i_key, o_key
|
||||
|
||||
# If not duplicate, check cycle logic, else invalid
|
||||
is_valid, final_i_key, final_o_key = jax.lax.cond(
|
||||
not_duplicate,
|
||||
check_cycle_logic,
|
||||
lambda: (jnp.array(False), jnp.nan, jnp.nan) # is_valid=False if duplicate
|
||||
)
|
||||
return is_valid, final_i_key, final_o_key
|
||||
|
||||
# If basic prereqs met, check existence/cycle, else invalid
|
||||
is_valid_attempt, i_key_attempt, o_key_attempt = jax.lax.cond(
|
||||
prereqs_met,
|
||||
check_existence_and_cycle,
|
||||
lambda: (jnp.array(False), jnp.nan, jnp.nan) # is_valid=False if prereqs not met
|
||||
)
|
||||
|
||||
return is_valid_attempt, i_key_attempt, o_key_attempt # bool, float, float
|
||||
|
||||
# Vectorize attempts and find first success
|
||||
keys = jax.random.split(key_, self.max_conn_tries)
|
||||
accept_flags, i_keys_all, o_keys_all = jax.vmap(attempt)(keys)
|
||||
|
||||
# find FIRST successful draw (if any)
|
||||
first_success_idx = fetch_first(accept_flags)
|
||||
found_valid_candidate = first_success_idx != I_INF
|
||||
|
||||
# Conditionally add the connection
|
||||
def do_accept():
|
||||
# Get the keys from the first successful attempt
|
||||
i_key_chosen = i_keys_all[first_success_idx]
|
||||
o_key_chosen = o_keys_all[first_success_idx]
|
||||
|
||||
# Create fixed attributes (using 3rd marker for add_conn)
|
||||
if "historical_marker" in genome.conn_gene.fixed_attrs:
|
||||
fix = jnp.array([i_key_chosen, o_key_chosen, new_conn_key[2]])
|
||||
else:
|
||||
fix = jnp.array([i_key_chosen, o_key_chosen])
|
||||
|
||||
# Add the connection
|
||||
new_conns = add_conn(
|
||||
conns_,
|
||||
fix,
|
||||
genome.conn_gene.new_zero_attrs(state) # Add with zero/default attrs
|
||||
)
|
||||
|
||||
return nodes_, new_conns
|
||||
|
||||
# If a valid candidate was found, add it; otherwise return original
|
||||
# arrays
|
||||
return jax.lax.cond(
|
||||
found_valid_candidate, # Condition is True if we should accept
|
||||
do_accept, # Do accept branch (if cond is true)
|
||||
lambda: (nodes_, conns_) # Do nothing branch (if cond is false)
|
||||
)
|
||||
|
||||
def mutate_delete_conn(key_, nodes_, conns_):
|
||||
i_key, o_key, idx = self.choose_connection_key(key_, conns_)
|
||||
return jax.lax.cond(
|
||||
idx == I_INF,
|
||||
lambda: (nodes_, conns_),
|
||||
lambda: (nodes_, delete_conn_by_pos(conns_, idx)),
|
||||
)
|
||||
|
||||
# --- Scheduling Logic (unchanged from user's code) ---
|
||||
k_node_add, k_node_del, k_conn_add, k_conn_del, k_schedule = \
|
||||
jax.random.split(randkey, 5)
|
||||
probs = jax.random.uniform(k_schedule, (4,))
|
||||
|
||||
def nothing(_, n_, c_): return n_, c_
|
||||
|
||||
# Apply mutations conditionally using original helper functions
|
||||
nodes, conns = jax.lax.cond(
|
||||
(self.node_add > 0) & (probs[0] < self.node_add),
|
||||
mutate_add_node, nothing, k_node_add, nodes, conns
|
||||
)
|
||||
nodes, conns = jax.lax.cond(
|
||||
(self.node_delete > 0) & (probs[1] < self.node_delete),
|
||||
mutate_delete_node, nothing, k_node_del, nodes, conns
|
||||
)
|
||||
# Apply connection addition using the OPTIMIZED version
|
||||
nodes, conns = jax.lax.cond(
|
||||
(self.conn_add > 0) & (probs[2] < self.conn_add),
|
||||
_mutate_add_conn_recurrent_optimized, # <<< Use optimized add_conn
|
||||
nothing, k_conn_add, nodes, conns
|
||||
)
|
||||
# Apply connection deletion using original helper function
|
||||
nodes, conns = jax.lax.cond(
|
||||
(self.conn_delete > 0) & (probs[3] < self.conn_delete),
|
||||
mutate_delete_conn, nothing, k_conn_del, nodes, conns
|
||||
)
|
||||
return nodes, conns
|
||||
|
||||
164
test/test_module_duplication.py
Normal file
164
test/test_module_duplication.py
Normal file
@@ -0,0 +1,164 @@
|
||||
"""Tests for the MEND ModuleDuplication mutation.
|
||||
|
||||
Tests verify that:
|
||||
1. The ModuleDuplication operator alone adds exactly one hidden node.
|
||||
2. The duplicated node has connections copied from the source.
|
||||
3. CombinedMutation integrates both default and duplication mutations.
|
||||
"""
|
||||
|
||||
import jax
|
||||
import jax.numpy as jnp
|
||||
from tensorneat.genome import DefaultGenome
|
||||
from tensorneat.genome.operations.mutation import ModuleDuplication
|
||||
|
||||
|
||||
def _count_hidden(nodes, genome):
|
||||
"""Count non-NaN hidden nodes (excluding inputs/outputs)."""
|
||||
return sum(
|
||||
1
|
||||
for n in nodes
|
||||
if not jnp.isnan(n[0])
|
||||
and int(n[0]) not in set(genome.input_idx.tolist())
|
||||
and int(n[0]) not in set(genome.output_idx.tolist())
|
||||
)
|
||||
|
||||
|
||||
def _count_valid_conns(conns):
|
||||
"""Count non-NaN connections."""
|
||||
return sum(1 for c in conns if not jnp.isnan(c[0]))
|
||||
|
||||
|
||||
def test_module_duplication_standalone():
|
||||
"""Test ModuleDuplication in isolation (not via CombinedMutation).
|
||||
|
||||
Start with a genome that has one hidden node (via init_hidden_layers),
|
||||
then apply only ModuleDuplication with rate=1.0.
|
||||
"""
|
||||
genome = DefaultGenome(
|
||||
num_inputs=2,
|
||||
num_outputs=1,
|
||||
max_nodes=10,
|
||||
max_conns=30,
|
||||
init_hidden_layers=(1,), # start with 1 hidden node
|
||||
)
|
||||
state = genome.setup()
|
||||
randkey = jax.random.PRNGKey(42)
|
||||
nodes, conns = genome.initialize(state, randkey)
|
||||
|
||||
init_hidden = _count_hidden(nodes, genome)
|
||||
init_conns = _count_valid_conns(conns)
|
||||
assert init_hidden == 1, f"Expected 1 initial hidden node, got {init_hidden}"
|
||||
|
||||
# Apply only the duplication operator (not CombinedMutation).
|
||||
dup = ModuleDuplication(duplication_rate=1.0)
|
||||
k1, _ = jax.random.split(randkey)
|
||||
new_node_key = jnp.array(genome.max_nodes + 1)
|
||||
new_conn_key = jnp.array(
|
||||
[genome.max_conns + 1, genome.max_conns + 2, genome.max_conns + 3]
|
||||
)
|
||||
nodes_mut, conns_mut = dup(
|
||||
state, genome, k1, nodes, conns, new_node_key, new_conn_key
|
||||
)
|
||||
|
||||
post_hidden = _count_hidden(nodes_mut, genome)
|
||||
post_conns = _count_valid_conns(conns_mut)
|
||||
|
||||
assert post_hidden == init_hidden + 1, (
|
||||
f"Module duplication should add exactly one hidden node, "
|
||||
f"got {post_hidden} (was {init_hidden})"
|
||||
)
|
||||
# The source node had 2 incoming (from inputs) + 1 outgoing (to output) = 3 conns.
|
||||
# Duplication should copy all of them.
|
||||
assert post_conns > init_conns, (
|
||||
f"Duplication should add connections, got {post_conns} (was {init_conns})"
|
||||
)
|
||||
|
||||
|
||||
def test_duplicated_node_has_connections():
|
||||
"""The duplicated node must have both incoming and outgoing connections."""
|
||||
genome = DefaultGenome(
|
||||
num_inputs=2,
|
||||
num_outputs=1,
|
||||
max_nodes=10,
|
||||
max_conns=30,
|
||||
init_hidden_layers=(1,),
|
||||
)
|
||||
state = genome.setup()
|
||||
randkey = jax.random.PRNGKey(7)
|
||||
nodes, conns = genome.initialize(state, randkey)
|
||||
|
||||
dup = ModuleDuplication(duplication_rate=1.0)
|
||||
k1, _ = jax.random.split(randkey)
|
||||
new_node_key = jnp.array(genome.max_nodes + 1)
|
||||
new_conn_key = jnp.array(
|
||||
[genome.max_conns + 1, genome.max_conns + 2, genome.max_conns + 3]
|
||||
)
|
||||
nodes_mut, conns_mut = dup(
|
||||
state, genome, k1, nodes, conns, new_node_key, new_conn_key
|
||||
)
|
||||
|
||||
nk = float(new_node_key)
|
||||
incoming = sum(
|
||||
1 for c in conns_mut if not jnp.isnan(c[0]) and float(c[1]) == nk
|
||||
)
|
||||
outgoing = sum(
|
||||
1 for c in conns_mut if not jnp.isnan(c[0]) and float(c[0]) == nk
|
||||
)
|
||||
assert incoming > 0, "Duplicated node must have incoming connections"
|
||||
assert outgoing > 0, "Duplicated node must have outgoing connections"
|
||||
|
||||
|
||||
def test_combined_mutation_with_duplication():
|
||||
"""CombinedMutation should produce a valid genome (no crashes)."""
|
||||
genome = DefaultGenome(
|
||||
num_inputs=2,
|
||||
num_outputs=1,
|
||||
max_nodes=15,
|
||||
max_conns=40,
|
||||
duplication_rate=1.0,
|
||||
)
|
||||
state = genome.setup()
|
||||
randkey = jax.random.PRNGKey(99)
|
||||
nodes, conns = genome.initialize(state, randkey)
|
||||
|
||||
k1, _ = jax.random.split(randkey)
|
||||
new_node_key = jnp.array(genome.max_nodes + 1)
|
||||
new_conn_key = jnp.array(
|
||||
[genome.max_conns + 1, genome.max_conns + 2, genome.max_conns + 3]
|
||||
)
|
||||
nodes_mut, conns_mut = genome.execute_mutation(
|
||||
state, k1, nodes, conns, new_node_key, new_conn_key
|
||||
)
|
||||
|
||||
# Should not crash and should have at least as many nodes/conns as before.
|
||||
init_valid = sum(1 for n in nodes if not jnp.isnan(n[0]))
|
||||
post_valid = sum(1 for n in nodes_mut if not jnp.isnan(n[0]))
|
||||
assert post_valid >= init_valid, "Mutation should not lose nodes"
|
||||
|
||||
|
||||
def test_duplication_disabled_when_rate_zero():
|
||||
"""With duplication_rate=0.0, no duplication should occur."""
|
||||
genome = DefaultGenome(
|
||||
num_inputs=2,
|
||||
num_outputs=1,
|
||||
max_nodes=10,
|
||||
max_conns=30,
|
||||
init_hidden_layers=(1,),
|
||||
)
|
||||
state = genome.setup()
|
||||
randkey = jax.random.PRNGKey(0)
|
||||
nodes, conns = genome.initialize(state, randkey)
|
||||
|
||||
dup = ModuleDuplication(duplication_rate=0.0)
|
||||
k1, _ = jax.random.split(randkey)
|
||||
new_node_key = jnp.array(genome.max_nodes + 1)
|
||||
new_conn_key = jnp.array(
|
||||
[genome.max_conns + 1, genome.max_conns + 2, genome.max_conns + 3]
|
||||
)
|
||||
nodes_mut, conns_mut = dup(
|
||||
state, genome, k1, nodes, conns, new_node_key, new_conn_key
|
||||
)
|
||||
|
||||
assert _count_hidden(nodes_mut, genome) == _count_hidden(nodes, genome), (
|
||||
"No duplication should occur with rate=0.0"
|
||||
)
|
||||
Reference in New Issue
Block a user