~ruther/ctu-fee-eoa

3a92d736977cc42edc06f6fca62b88976c49a559 — Rutherther a month ago cd58504
feat: add simple plotting of local search
M env/.gitignore => env/.gitignore +2 -1
@@ 1,1 1,2 @@
target
\ No newline at end of file
target
test_results/*.png
\ No newline at end of file

M env/Cargo.lock => env/Cargo.lock +770 -2
@@ 3,6 3,21 @@
version = 4

[[package]]
name = "adler2"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"

[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
 "libc",
]

[[package]]
name = "approx"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 18,27 33,289 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"

[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"

[[package]]
name = "bitflags"
version = "2.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"

[[package]]
name = "bumpalo"
version = "3.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"

[[package]]
name = "bytemuck"
version = "1.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4"

[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"

[[package]]
name = "cc"
version = "1.2.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7"
dependencies = [
 "find-msvc-tools",
 "shlex",
]

[[package]]
name = "cfg-if"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"

[[package]]
name = "chrono"
version = "0.4.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
dependencies = [
 "iana-time-zone",
 "js-sys",
 "num-traits",
 "wasm-bindgen",
 "windows-link",
]

[[package]]
name = "color_quant"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"

[[package]]
name = "core-foundation"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
dependencies = [
 "core-foundation-sys",
 "libc",
]

[[package]]
name = "core-foundation-sys"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"

[[package]]
name = "core-graphics"
version = "0.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081"
dependencies = [
 "bitflags 1.3.2",
 "core-foundation",
 "core-graphics-types",
 "foreign-types",
 "libc",
]

[[package]]
name = "core-graphics-types"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf"
dependencies = [
 "bitflags 1.3.2",
 "core-foundation",
 "libc",
]

[[package]]
name = "core-text"
version = "20.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9d2790b5c08465d49f8dc05c8bcae9fea467855947db39b0f8145c091aaced5"
dependencies = [
 "core-foundation",
 "core-graphics",
 "foreign-types",
 "libc",
]

[[package]]
name = "crc32fast"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
dependencies = [
 "cfg-if",
]

[[package]]
name = "dirs"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
dependencies = [
 "dirs-sys",
]

[[package]]
name = "dirs-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
dependencies = [
 "libc",
 "option-ext",
 "redox_users",
 "windows-sys",
]

[[package]]
name = "dlib"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"
dependencies = [
 "libloading",
]

[[package]]
name = "dwrote"
version = "0.11.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b35532432acc8b19ceed096e35dfa088d3ea037fe4f3c085f1f97f33b4d02"
dependencies = [
 "lazy_static",
 "libc",
 "winapi",
 "wio",
]

[[package]]
name = "env"
version = "0.1.0"
dependencies = [
 "nalgebra",
 "plotters",
 "rand",
 "rand_distr",
]

[[package]]
name = "fdeflate"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c"
dependencies = [
 "simd-adler32",
]

[[package]]
name = "find-msvc-tools"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127"

[[package]]
name = "flate2"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc5a4e564e38c699f2880d3fda590bedc2e69f3f84cd48b457bd892ce61d0aa9"
dependencies = [
 "crc32fast",
 "miniz_oxide",
]

[[package]]
name = "float-ord"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce81f49ae8a0482e4c55ea62ebbd7e5a686af544c00b9d090bba3ff9be97b3d"

[[package]]
name = "font-kit"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c7e611d49285d4c4b2e1727b72cf05353558885cc5252f93707b845dfcaf3d3"
dependencies = [
 "bitflags 2.9.4",
 "byteorder",
 "core-foundation",
 "core-graphics",
 "core-text",
 "dirs",
 "dwrote",
 "float-ord",
 "freetype-sys",
 "lazy_static",
 "libc",
 "log",
 "pathfinder_geometry",
 "pathfinder_simd",
 "walkdir",
 "winapi",
 "yeslogic-fontconfig-sys",
]

[[package]]
name = "foreign-types"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
dependencies = [
 "foreign-types-macros",
 "foreign-types-shared",
]

[[package]]
name = "foreign-types-macros"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
]

[[package]]
name = "foreign-types-shared"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"

[[package]]
name = "freetype-sys"
version = "0.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7edc5b9669349acfda99533e9e0bcf26a51862ab43b08ee7745c55d28eb134"
dependencies = [
 "cc",
 "libc",
 "pkg-config",
]

[[package]]
name = "getrandom"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
 "cfg-if",
 "libc",
 "wasi 0.11.1+wasi-snapshot-preview1",
]

[[package]]
name = "getrandom"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 47,22 324,118 @@ dependencies = [
 "cfg-if",
 "libc",
 "r-efi",
 "wasi",
 "wasi 0.14.7+wasi-0.2.4",
]

[[package]]
name = "gif"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045"
dependencies = [
 "color_quant",
 "weezl",
]

[[package]]
name = "iana-time-zone"
version = "0.1.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
dependencies = [
 "android_system_properties",
 "core-foundation-sys",
 "iana-time-zone-haiku",
 "js-sys",
 "log",
 "wasm-bindgen",
 "windows-core",
]

[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
 "cc",
]

[[package]]
name = "image"
version = "0.24.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d"
dependencies = [
 "bytemuck",
 "byteorder",
 "color_quant",
 "jpeg-decoder",
 "num-traits",
 "png",
]

[[package]]
name = "jpeg-decoder"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00810f1d8b74be64b13dbf3db89ac67740615d6c891f0e7b6179326533011a07"

[[package]]
name = "js-sys"
version = "0.3.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305"
dependencies = [
 "once_cell",
 "wasm-bindgen",
]

[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"

[[package]]
name = "libc"
version = "0.2.176"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174"

[[package]]
name = "libloading"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
dependencies = [
 "cfg-if",
 "windows-link",
]

[[package]]
name = "libm"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"

[[package]]
name = "libredox"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
dependencies = [
 "bitflags 2.9.4",
 "libc",
]

[[package]]
name = "log"
version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"

[[package]]
name = "matrixmultiply"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 73,6 446,16 @@ dependencies = [
]

[[package]]
name = "miniz_oxide"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
dependencies = [
 "adler2",
 "simd-adler32",
]

[[package]]
name = "nalgebra"
version = "0.33.2"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 149,12 532,108 @@ dependencies = [
]

[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"

[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"

[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"

[[package]]
name = "pathfinder_geometry"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b7e7b4ea703700ce73ebf128e1450eb69c3a8329199ffbfb9b2a0418e5ad3"
dependencies = [
 "log",
 "pathfinder_simd",
]

[[package]]
name = "pathfinder_simd"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf9027960355bf3afff9841918474a81a5f972ac6d226d518060bba758b5ad57"
dependencies = [
 "rustc_version",
]

[[package]]
name = "pkg-config"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"

[[package]]
name = "plotters"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747"
dependencies = [
 "chrono",
 "font-kit",
 "image",
 "lazy_static",
 "num-traits",
 "pathfinder_geometry",
 "plotters-backend",
 "plotters-bitmap",
 "plotters-svg",
 "ttf-parser",
 "wasm-bindgen",
 "web-sys",
]

[[package]]
name = "plotters-backend"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a"

[[package]]
name = "plotters-bitmap"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72ce181e3f6bf82d6c1dc569103ca7b1bd964c60ba03d7e6cdfbb3e3eb7f7405"
dependencies = [
 "gif",
 "image",
 "plotters-backend",
]

[[package]]
name = "plotters-svg"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670"
dependencies = [
 "plotters-backend",
]

[[package]]
name = "png"
version = "0.17.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526"
dependencies = [
 "bitflags 1.3.2",
 "crc32fast",
 "fdeflate",
 "flate2",
 "miniz_oxide",
]

[[package]]
name = "ppv-lite86"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 213,7 692,7 @@ version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
dependencies = [
 "getrandom",
 "getrandom 0.3.3",
]

[[package]]


@@ 233,6 712,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"

[[package]]
name = "redox_users"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac"
dependencies = [
 "getrandom 0.2.16",
 "libredox",
 "thiserror",
]

[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
 "semver",
]

[[package]]
name = "rustversion"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"

[[package]]
name = "safe_arch"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 242,6 747,27 @@ dependencies = [
]

[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
 "winapi-util",
]

[[package]]
name = "semver"
version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"

[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"

[[package]]
name = "simba"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 255,6 781,12 @@ dependencies = [
]

[[package]]
name = "simd-adler32"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"

[[package]]
name = "syn"
version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 266,6 798,32 @@ dependencies = [
]

[[package]]
name = "thiserror"
version = "2.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
dependencies = [
 "thiserror-impl",
]

[[package]]
name = "thiserror-impl"
version = "2.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
]

[[package]]
name = "ttf-parser"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4"

[[package]]
name = "typenum"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 278,6 836,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"

[[package]]
name = "walkdir"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
 "same-file",
 "winapi-util",
]

[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"

[[package]]
name = "wasi"
version = "0.14.7+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 296,6 870,81 @@ dependencies = [
]

[[package]]
name = "wasm-bindgen"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d"
dependencies = [
 "cfg-if",
 "once_cell",
 "rustversion",
 "wasm-bindgen-macro",
 "wasm-bindgen-shared",
]

[[package]]
name = "wasm-bindgen-backend"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19"
dependencies = [
 "bumpalo",
 "log",
 "proc-macro2",
 "quote",
 "syn",
 "wasm-bindgen-shared",
]

[[package]]
name = "wasm-bindgen-macro"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119"
dependencies = [
 "quote",
 "wasm-bindgen-macro-support",
]

[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
 "wasm-bindgen-backend",
 "wasm-bindgen-shared",
]

[[package]]
name = "wasm-bindgen-shared"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1"
dependencies = [
 "unicode-ident",
]

[[package]]
name = "web-sys"
version = "0.3.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120"
dependencies = [
 "js-sys",
 "wasm-bindgen",
]

[[package]]
name = "weezl"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3"

[[package]]
name = "wide"
version = "0.7.33"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 306,12 955,131 @@ dependencies = [
]

[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
 "winapi-i686-pc-windows-gnu",
 "winapi-x86_64-pc-windows-gnu",
]

[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"

[[package]]
name = "winapi-util"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
 "windows-sys",
]

[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

[[package]]
name = "windows-core"
version = "0.62.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
dependencies = [
 "windows-implement",
 "windows-interface",
 "windows-link",
 "windows-result",
 "windows-strings",
]

[[package]]
name = "windows-implement"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
]

[[package]]
name = "windows-interface"
version = "0.59.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
]

[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"

[[package]]
name = "windows-result"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
dependencies = [
 "windows-link",
]

[[package]]
name = "windows-strings"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
dependencies = [
 "windows-link",
]

[[package]]
name = "windows-sys"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
 "windows-link",
]

[[package]]
name = "wio"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5"
dependencies = [
 "winapi",
]

[[package]]
name = "wit-bindgen"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"

[[package]]
name = "yeslogic-fontconfig-sys"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "503a066b4c037c440169d995b869046827dbc71263f6e8f3be6d77d4f3229dbd"
dependencies = [
 "dlib",
 "once_cell",
 "pkg-config",
]

[[package]]
name = "zerocopy"
version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index"

M env/Cargo.toml => env/Cargo.toml +1 -0
@@ 5,5 5,6 @@ edition = "2024"

[dependencies]
nalgebra = "0.33.2"
plotters = "0.3.7"
rand = "0.9.2"
rand_distr = "0.5.1"

M env/src/evolutionary_strategy.rs => env/src/evolutionary_strategy.rs +8 -0
@@ 21,6 21,13 @@ fn normal_one_to_five<const LEN: usize>(perturbation: &mut RandomDistributionPer

    let new_sigma = sigma * exp.exp().powf(1.0 / LEN as f64);

    // Hopefully prevent cases when the sigma goes too low
    let new_sigma = if new_sigma < 0.000000001 {
        0.000000001
    } else {
        new_sigma
    };

    perturbation.set_std_dev(new_sigma)?;
    Ok(())
}


@@ 48,6 55,7 @@ impl<const LEN: usize, TOut> EvolutionaryStrategy<TOut, BoundedPerturbation<LEN,
            better: bool,
            _: &LocalSearchStats<<BoundedPerturbation<LEN, RandomDistributionPerturbation<LEN, Normal<f64>>> as PerturbationOperator>::Chromosome, TOut>
    ) -> Result<(), Self::Err> {
        println!("{}", perturbation.inner().std_dev());
        normal_one_to_five(perturbation.inner_mut(), better)
    }
}

M env/src/local_search/mod.rs => env/src/local_search/mod.rs +153 -8
@@ 1,9 1,13 @@
use std::fmt::Debug;
use crate::binary_string::{BinaryString, BinaryStringConversionError};
use crate::evolutionary_strategy::{EvolutionaryStrategy, IdentityStrategy};
use crate::fitness::FitnessFunction;
use crate::terminating::TerminatingCondition;
use crate::perturbation::PerturbationOperator;
use crate::comparison::BetterThanOperator;
use full_palette::BROWN;
use nalgebra::SVector;
use plotters::prelude::*;

// Functions
#[derive(Debug, Clone, PartialEq)]


@@ 19,17 23,46 @@ pub struct LocalSearchStats<TInput, TResult> {
    stats: Vec<LocalSearchCandidate<TInput, TResult>>
}

impl<TResult> LocalSearchStats<BinaryString, TResult> {
    pub fn to_real(self, min: &SVector<f64, 2>, max: &SVector<f64, 2>) -> Result<LocalSearchStats<SVector<f64, 2>, TResult>, BinaryStringConversionError> {
        Ok(LocalSearchStats::<SVector<f64, 2>, TResult>::from_vec(
            self.stats
                .into_iter()
                .map(|candidate|
                     Ok(LocalSearchCandidate {
                         fit: candidate.fit,
                         pos: candidate.pos.to_real(&min, &max)?,
                         cycle: candidate.cycle,
                     }))
                .collect::<Result<Vec<_>, _>>()?))
    }
}

impl<TInput, TResult> LocalSearchStats<TInput, TResult> {
    fn from_vec(stats: Vec<LocalSearchCandidate<TInput, TResult>>)  -> Self {
        Self {
            stats
        }
    }

    pub fn new() -> Self {
        Self {
            stats: vec![]
        }
    }

    pub fn stats(&self) -> &Vec<LocalSearchCandidate<TInput, TResult>> {
    pub fn candidates(&self) -> &Vec<LocalSearchCandidate<TInput, TResult>> {
        &self.stats
    }

    pub fn cycles(&self) -> usize {
        self.best().cycle
    }

    pub fn best(&self) -> &LocalSearchCandidate<TInput, TResult> {
        self.stats.last().expect("No candidates...")
    }

    pub fn append(&mut self, candidate: LocalSearchCandidate<TInput, TResult>) {
        self.stats.push(candidate)
    }


@@ 45,10 78,10 @@ pub struct LocalSearchResult<TInput, TResult>
    pub cycles: usize,

    // statistics
    pub best_candidates: LocalSearchStats<TInput, TResult>
    pub stats: LocalSearchStats<TInput, TResult>
}

fn local_search_first_improving<
pub fn local_search_first_improving<
        TInput, TResult, TErr, TFit, TTerminatingCondition, TPerturbationOperator, TBetterThanOperator>(
    fit: &TFit,
    terminating_condition: &mut TTerminatingCondition,


@@ 74,7 107,7 @@ where
    )
}

fn local_search_first_improving_evolving<
pub fn local_search_first_improving_evolving<
        TInput, TResult, TErr, TFit, TTerminatingCondition, TPerturbationOperator, TBetterThanOperator, TEvolutionaryStrategy>(
    fit: &TFit,
    terminating_condition: &mut TTerminatingCondition,


@@ 133,16 166,118 @@ where

    Ok(LocalSearchResult {
        best_candidate,
        best_candidates: stats,
        stats,
        cycles: cycle
    })
}

pub fn plot_fitness_evolution(file: &str, stats: LocalSearchStats<SVector<f64, 2>, f64>) -> Result<(), Box<dyn std::error::Error>> {
    let root = BitMapBackend::new(file, (1920, 768)).into_drawing_area();
    root.fill(&WHITE)?;

    let (left, right) = root.split_horizontally(root.relative_to_width(0.50));

    let mut chart = ChartBuilder::on(&left)
        .caption("Best candidate evaluation", ("sans-serif", 25).into_font())
        .margin(5)
        .x_label_area_size(30)
        .y_label_area_size(30)
        .build_cartesian_2d(0..stats.cycles(), stats.best().fit..stats.candidates().first().unwrap().fit)?;

    chart.configure_mesh()
        .x_desc("Cycle")
        .y_desc("Evaluation")
        .draw()?;

    chart
        .draw_series(LineSeries::new(
            stats.candidates().iter().map(|candidate| (candidate.cycle, candidate.fit)),
            &RED,
        ))?
        .label("Linear fitness")
        .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED));

    chart
        .configure_series_labels()
        .background_style(&WHITE.mix(0.8))
        .border_style(&BLACK)
        .draw()?;

    let mut chart = ChartBuilder::on(&right)
        .caption("Locations of best candidates so far", ("sans-serif", 25).into_font())
        .margin(5)
        .x_label_area_size(50)
        .y_label_area_size(50)
        // TODO
        .build_cartesian_2d(-10.0..10.0f64, -10.0..10.0f64)?;

    chart.configure_mesh()
        .x_desc("X coordinate")
        .y_desc("Y coordinate")
        .draw()?;

    let mut points = stats.candidates().iter()
        .map(|candidate| (candidate.pos.x, candidate.pos.y));

    chart
        .draw_series(LineSeries::new(
            points.clone(),
            &BLACK,
        ))?;

    chart
        .draw_series(PointSeries::of_element(
            points.clone(),
            3,
            &BLACK,
            &| c, s, st| {
                return EmptyElement::at(c)
                    + Circle::new((0,0),s,st.filled());
            },
        ))?
        .label("Candidates")
        .legend(|(x, y)| Circle::new((x, y), 3, BLACK.filled()));

    // TODO:
    let start = points.next().unwrap();
    let best = points.last().unwrap();

    chart
        .draw_series(std::iter::once(Circle::new(
            start, 4, BROWN.filled())
        ))?
        .label("Start")
        .legend(|(x, y)| Circle::new((x, y), 3, BROWN.filled()));

    chart
        .draw_series(std::iter::once(Circle::new(
            best, 4, GREEN.filled())
        ))?
        .label("Best")
        .legend(|(x, y)| Circle::new((x, y), 3, GREEN.filled()));

    chart
        .draw_series(std::iter::once(Text::new(
            "Start",
            start,
            ("sans-serif", 20).into_font(),
        )))?;

    chart
        .configure_series_labels()
        .background_style(&WHITE.mix(0.8))
        .border_style(&BLACK)
        .draw()?;

    root.present()?;
    Ok(())
}

#[cfg(test)]
pub mod tests {
    use nalgebra::SVector;

    use crate::{binary_string::{BinaryString, Bounds}, comparison::MinimizingOperator, evolutionary_strategy::OneToFiveStrategy, fitness::{one_max::OneMax, real::Linear, rosenbrock::Rosenbrock, sphere::Sphere, BinaryFitnessWrapper}, local_search::{local_search_first_improving, local_search_first_improving_evolving}, perturbation::{BinaryStringBitPerturbation, BoundedPerturbation, BoundedPerturbationStrategy, PatternPerturbation, RandomDistributionPerturbation}, terminating::{AndTerminatingConditions, EqualTerminatingCondition, NoBetterForCyclesTerminatingCondition}};
    use crate::{binary_string::{BinaryString, Bounds}, comparison::MinimizingOperator, evolutionary_strategy::OneToFiveStrategy, fitness::{one_max::OneMax, real::Linear, rosenbrock::Rosenbrock, sphere::Sphere, BinaryFitnessWrapper}, local_search::{local_search_first_improving, local_search_first_improving_evolving, plot_fitness_evolution}, perturbation::{BinaryStringBitPerturbation, BoundedPerturbation, BoundedPerturbationStrategy, PatternPerturbation, RandomDistributionPerturbation}, terminating::{AndTerminatingConditions, EqualTerminatingCondition, NoBetterForCyclesTerminatingCondition}};

    #[test]
    fn test_local_search_sphere() {


@@ 152,7 287,7 @@ pub mod tests {
        let max = SVector::<f64, 2>::from_element(31.0);
        let optimum_real = optimum.to_real(&min, &max).unwrap();
        let sphere = Sphere::new(optimum_real);
        let sphere_wrapped = BinaryFitnessWrapper::new(sphere, min, max);
        let sphere_wrapped = BinaryFitnessWrapper::new(sphere, min.clone(), max.clone());

        let result = local_search_first_improving(
            &sphere_wrapped,


@@ 179,6 314,8 @@ pub mod tests {
            result.best_candidate.pos,
            optimum
        );

        plot_fitness_evolution("test_results/sphere.png", result.stats.to_real(&min, &max).unwrap()).unwrap();
    }

    #[test]


@@ 263,7 400,7 @@ pub mod tests {
                        &mut NoBetterForCyclesTerminatingCondition::new(100)
                    ]
                ),
            &mut BinaryStringBitPerturbation::new(0.3),
            &mut BinaryStringBitPerturbation::new(0.1),
            &MinimizingOperator::new(),
            &BinaryString::new(vec![0; 10]),
        ).unwrap();


@@ 279,6 416,8 @@ pub mod tests {
            result.best_candidate.pos,
            optimum
        );

        plot_fitness_evolution("test_results/rosenbrock.png", result.stats.to_real(&min, &max).unwrap()).unwrap();
    }

    #[test]


@@ 318,6 457,8 @@ pub mod tests {
            result.best_candidate.pos,
            optimum
        );

        plot_fitness_evolution("test_results/linear.png", result.stats).unwrap();
    }

    #[test]


@@ 357,6 498,8 @@ pub mod tests {
            result.best_candidate.pos,
            optimum
        );

        plot_fitness_evolution("test_results/linear_pattern.png", result.stats).unwrap();
    }

    #[test]


@@ 397,5 540,7 @@ pub mod tests {
            result.best_candidate.pos,
            optimum
        );

        plot_fitness_evolution("test_results/linear_onetofive.png", result.stats).unwrap();
    }
}

M env/src/perturbation/mod.rs => env/src/perturbation/mod.rs +4 -0
@@ 153,6 153,10 @@ impl<const LEN: usize, T: PerturbationOperator<Chromosome = SVector<f64, LEN>>> 
        }
    }

    pub fn inner(&self) -> &T {
        &self.perturbation
    }

    pub fn inner_mut(&mut self) -> &mut T {
        &mut self.perturbation
    }

A env/test_results/.gitkeep => env/test_results/.gitkeep +0 -0
M manifest.scm => manifest.scm +5 -1
@@ 5,4 5,8 @@
  "julia"
  "rust"
  "rust-analyzer"
  "rust:cargo"))
  "rust:cargo"

  "pkg-config"
  "fontconfig"
  "freetype"))