diff --git a/.gitignore b/.gitignore index 7cc2842..d26e49d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ rust/target rust/.history/ +rust/Cargo.lock **/*.rs.bk *.tmp *.idx @@ -20,7 +21,7 @@ pip-wheel-metadata .eggs/ dist/ installer/Output/ -workspace.code-workspace +workspace.code-workspace ed_lrr_gui/web/jobs.db ed_lrr_gui/web/ed_lrr_web_ui.db __version__.py diff --git a/MANIFEST.in b/MANIFEST.in index a159d6a..42fde92 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,11 @@ include rust/Cargo.toml include rust/.cargo/config +exclude docs_mdbook +exclude celery_test +exclude installer +exclude imgui_test +exclude icon recursive-include rust/src * -recursive-include ed_lrr_gui * \ No newline at end of file +recursive-include ed_lrr_gui * +recursive-exclude __pycache__ *.pyc *.pyo +global-exclude __pycache__ \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index ce3a100..d3933ed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,9 @@ [build-system] requires = ["setuptools", "wheel","setuptools_rust"] build-backend = "setuptools.build_meta" + +[tool.poetry] +description = "Elite: Dangerous Long Range Route Plotter" +name="ed_lrr" +version="0.2.0" +authors = ["Daniel Seiller "] \ No newline at end of file diff --git a/rust/.devcontainer/devcontainer.json b/rust/.devcontainer/devcontainer.json new file mode 100644 index 0000000..a9a6b26 --- /dev/null +++ b/rust/.devcontainer/devcontainer.json @@ -0,0 +1,26 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: +// https://github.com/microsoft/vscode-dev-containers/tree/v0.238.0/containers/docker-existing-dockerfile +{ + "name": "ED_LRR", + + // Sets the run context to one level up instead of the .devcontainer folder. + "context": "..", + + // Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename. + "dockerFile": "../Dockerfile", + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Uncomment the next line to run commands after the container is created - for example installing curl. + // "postCreateCommand": "apt-get update && apt-get install -y curl", + + // Uncomment when using a ptrace-based debugger like C++, Go, and Rust + "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ] + + // Uncomment to use the Docker CLI from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker. + // "mounts": [ "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" ], + + // Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root. + // "remoteUser": "vscode" +} diff --git a/rust/.vscode/settings.json b/rust/.vscode/settings.json index 62906b4..bf0fd37 100644 --- a/rust/.vscode/settings.json +++ b/rust/.vscode/settings.json @@ -10,10 +10,11 @@ ], "discord.enabled": true, "python.pythonPath": "..\\.nox\\devenv-3-8\\python.exe", - "jupyter.jupyterServerType": "remote", + "jupyter.jupyterServerType": "local", "files.associations": { "*.ksy": "yaml", "*.vpy": "python", "stat.h": "c" - } + }, + "rust-analyzer.diagnostics.disabled": ["unresolved-import"] } \ No newline at end of file diff --git a/rust/Cargo.lock b/rust/Cargo.lock deleted file mode 100644 index df4f322..0000000 --- a/rust/Cargo.lock +++ /dev/null @@ -1,1718 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aho-corasick" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" -dependencies = [ - "memchr", -] - -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - -[[package]] -name = "arc-swap" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5d78ce20460b82d3fa150275ed9d55e21064fc7951177baacf86a145c4a4b1f" - -[[package]] -name = "as-slice" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" -dependencies = [ - "generic-array 0.12.4", - "generic-array 0.13.3", - "generic-array 0.14.5", - "stable_deref_trait", -] - -[[package]] -name = "atomic-polyfill" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686d748538a32325b28d6411dd8a939e7ad5128e5d0023cc4fd3573db456042" -dependencies = [ - "critical-section", - "riscv-target", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "backtrace" -version = "0.3.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "bare-metal" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" -dependencies = [ - "rustc_version 0.2.3", -] - -[[package]] -name = "bare-metal" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" - -[[package]] -name = "better-panic" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fa9e1d11a268684cbd90ed36370d7577afb6c62d912ddff5c15fc34343e5036" -dependencies = [ - "backtrace", - "console", -] - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bit_field" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" - -[[package]] -name = "bitfield" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "block-buffer" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95" -dependencies = [ - "generic-array 0.14.5", -] - -[[package]] -name = "bstr" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata", - "serde", -] - -[[package]] -name = "bumpalo" -version = "3.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "cast" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" -dependencies = [ - "rustc_version 0.4.0", -] - -[[package]] -name = "cc" -version = "1.0.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "bitflags", - "textwrap", - "unicode-width", -] - -[[package]] -name = "console" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31" -dependencies = [ - "encode_unicode", - "libc", - "once_cell", - "terminal_size", - "winapi", -] - -[[package]] -name = "cortex-m" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ff967e867ca14eba0c34ac25cd71ea98c678e741e3915d923999bb2fe7c826" -dependencies = [ - "bare-metal 0.2.5", - "bitfield", - "embedded-hal", - "volatile-register", -] - -[[package]] -name = "crc32fast" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "criterion" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" -dependencies = [ - "atty", - "cast", - "clap", - "criterion-plot", - "csv", - "itertools", - "lazy_static", - "num-traits", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_cbor", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" -dependencies = [ - "cast", - "itertools", -] - -[[package]] -name = "critical-section" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01e191a5a6f6edad9b679777ef6b6c0f2bdd4a333f2ecb8f61c3e28109a03d70" -dependencies = [ - "bare-metal 1.0.0", - "cfg-if", - "cortex-m", - "riscv", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97242a70df9b89a65d0b6df3c4bf5b9ce03c5b7309019777fbde37e7537f8762" -dependencies = [ - "cfg-if", - "crossbeam-utils", - "lazy_static", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120" -dependencies = [ - "cfg-if", - "lazy_static", -] - -[[package]] -name = "crypto-common" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d6b536309245c849479fba3da410962a43ed8e51c26b729208ec0ac2798d0" -dependencies = [ - "generic-array 0.14.5", -] - -[[package]] -name = "csv" -version = "1.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" -dependencies = [ - "bstr", - "csv-core", - "itoa 0.4.8", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" -dependencies = [ - "memchr", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "dict_derive" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6207f46b33b2bf00858b0edb03d188d31a46fedfde4aa53a27d69fe25acd80cf" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "diff-struct" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d40d5fdd7026162b70b4a819a09c602edb46cdba36923309bcdd08a154edf552" -dependencies = [ - "diff_derive", - "serde", -] - -[[package]] -name = "diff_derive" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a172f64d18b45c6ee85f07fce93b25bae44495db0cbc2694c1a6c875226c4e7a" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "digest" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b697d66081d42af4fba142d56918a3cb21dc8eb63372c6b85d14f44fb9c5979b" -dependencies = [ - "block-buffer", - "crypto-common", - "generic-array 0.14.5", -] - -[[package]] -name = "ed_lrr" -version = "0.2.0" -dependencies = [ - "better-panic", - "bincode", - "byteorder", - "criterion", - "crossbeam-channel", - "csv", - "csv-core", - "derivative", - "dict_derive", - "diff-struct", - "eddie", - "eval", - "eyre", - "flate2", - "fnv", - "humantime", - "intmap", - "itertools", - "log", - "memmap", - "nohash-hasher", - "num_cpus", - "permutohedron", - "postcard", - "pyo3", - "pyo3-log", - "pythonize", - "rand", - "rand_distr", - "regex", - "rstar", - "rustc-hash", - "serde", - "serde_json", - "sha3", - "stats_alloc", - "thiserror", - "tracing", - "tracing-chrome", - "tracing-subscriber", - "tracing-tracy", - "tracing-unwrap", - "tracy-client", -] - -[[package]] -name = "eddie" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ad36183b190ad1632999a8735b9842f3fda7a5afa433d9132e80860ef7051a" - -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "embedded-hal" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36cfb62ff156596c892272f3015ef952fe1525e85261fa3a7f327bd6b384ab9" -dependencies = [ - "nb 0.1.3", - "void", -] - -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - -[[package]] -name = "eval" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba90c19bed0c67afb0a24340b42d13ddddcb5413c4c17a04c11871bd6b572c42" -dependencies = [ - "quick-error", - "serde", - "serde_json", -] - -[[package]] -name = "eyre" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc225d8f637923fe585089fcf03e705c222131232d2c1fb622e84ecf725d0eb8" -dependencies = [ - "indenter", - "once_cell", -] - -[[package]] -name = "flate2" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" -dependencies = [ - "cfg-if", - "crc32fast", - "libc", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - -[[package]] -name = "generic-array" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" -dependencies = [ - "typenum", -] - -[[package]] -name = "generic-array" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "gimli" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" - -[[package]] -name = "half" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - -[[package]] -name = "hash32" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc" -dependencies = [ - "byteorder", -] - -[[package]] -name = "hash32" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" -dependencies = [ - "byteorder", -] - -[[package]] -name = "heapless" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634bd4d29cbf24424d0a4bfcbf80c6960129dc24424752a7d1d1390607023422" -dependencies = [ - "as-slice", - "generic-array 0.14.5", - "hash32 0.1.1", - "stable_deref_trait", -] - -[[package]] -name = "heapless" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d076121838e03f862871315477528debffdb7462fb229216ecef91b1a3eb31eb" -dependencies = [ - "atomic-polyfill", - "hash32 0.2.1", - "serde", - "spin", - "stable_deref_trait", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "indenter" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" - -[[package]] -name = "indoc" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8" -dependencies = [ - "indoc-impl", - "proc-macro-hack", -] - -[[package]] -name = "indoc-impl" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0" -dependencies = [ - "proc-macro-hack", - "proc-macro2", - "quote", - "syn", - "unindent", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "intmap" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae52f28f45ac2bc96edb7714de995cffc174a395fb0abf5bff453587c980d7b9" - -[[package]] -name = "itertools" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" - -[[package]] -name = "js-sys" -version = "0.3.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "json" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" - -[[package]] -name = "keccak" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.112" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" - -[[package]] -name = "libm" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" - -[[package]] -name = "lock_api" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "memchr" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" - -[[package]] -name = "memmap" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - -[[package]] -name = "miniz_oxide" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" -dependencies = [ - "adler", - "autocfg", -] - -[[package]] -name = "nb" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" -dependencies = [ - "nb 1.0.0", -] - -[[package]] -name = "nb" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" - -[[package]] -name = "nohash-hasher" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" - -[[package]] -name = "oorandom" -version = "11.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi", -] - -[[package]] -name = "paste" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" -dependencies = [ - "paste-impl", - "proc-macro-hack", -] - -[[package]] -name = "paste-impl" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" -dependencies = [ - "proc-macro-hack", -] - -[[package]] -name = "pdqselect" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec91767ecc0a0bbe558ce8c9da33c068066c57ecc8bb8477ef8c1ad3ef77c27" - -[[package]] -name = "permutohedron" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b687ff7b5da449d39e418ad391e5e08da53ec334903ddbb921db208908fc372c" - -[[package]] -name = "pin-project-lite" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" - -[[package]] -name = "plotters" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" - -[[package]] -name = "plotters-svg" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "postcard" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a25c0b0ae06fcffe600ad392aabfa535696c8973f2253d9ac83171924c58a858" -dependencies = [ - "heapless 0.7.10", - "postcard-cobs", - "serde", -] - -[[package]] -name = "postcard-cobs" -version = "0.1.5-pre" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c68cb38ed13fd7bc9dd5db8f165b7c8d9c1a315104083a2b10f11354c2af97f" - -[[package]] -name = "ppv-lite86" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" - -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - -[[package]] -name = "proc-macro2" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "pyo3" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cf01dbf1c05af0a14c7779ed6f3aa9deac9c3419606ac9de537a2d649005720" -dependencies = [ - "cfg-if", - "eyre", - "indoc", - "libc", - "parking_lot", - "paste", - "pyo3-build-config", - "pyo3-macros", - "unindent", -] - -[[package]] -name = "pyo3-build-config" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf9e4d128bfbddc898ad3409900080d8d5095c379632fbbfbb9c8cfb1fb852b" -dependencies = [ - "once_cell", -] - -[[package]] -name = "pyo3-log" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d43bb6bf4460e400696a4c8b4b647362e1eddc4ac31b993998692e4c2a9a5f" -dependencies = [ - "arc-swap", - "log", - "pyo3", -] - -[[package]] -name = "pyo3-macros" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67701eb32b1f9a9722b4bc54b548ff9d7ebfded011c12daece7b9063be1fd755" -dependencies = [ - "pyo3-macros-backend", - "quote", - "syn", -] - -[[package]] -name = "pyo3-macros-backend" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f44f09e825ee49a105f2c7b23ebee50886a9aee0746f4dd5a704138a64b0218a" -dependencies = [ - "proc-macro2", - "pyo3-build-config", - "quote", - "syn", -] - -[[package]] -name = "pythonize" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445529621b8801c031b9e43f12f543fdf64379584646f132d6dcf2731c814e03" -dependencies = [ - "pyo3", - "serde", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quote" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_distr" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "964d548f8e7d12e102ef183a0de7e98180c9f8729f555897a857b96e48122d2f" -dependencies = [ - "num-traits", - "rand", -] - -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rayon" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" -dependencies = [ - "autocfg", - "crossbeam-deque", - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "lazy_static", - "num_cpus", -] - -[[package]] -name = "redox_syscall" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" -dependencies = [ - "bitflags", -] - -[[package]] -name = "regex" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" - -[[package]] -name = "regex-syntax" -version = "0.6.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" - -[[package]] -name = "riscv" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6907ccdd7a31012b70faf2af85cd9e5ba97657cc3987c4f13f8e4d2c2a088aba" -dependencies = [ - "bare-metal 1.0.0", - "bit_field", - "riscv-target", -] - -[[package]] -name = "riscv-target" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88aa938cda42a0cf62a20cfe8d139ff1af20c2e681212b5b34adb5a58333f222" -dependencies = [ - "lazy_static", - "regex", -] - -[[package]] -name = "rstar" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc6fc513b8c3853e43a0c3f909ded14ffa82e5170c9c5f6fb175f9c85c8a433" -dependencies = [ - "heapless 0.6.1", - "num-traits", - "pdqselect", - "smallvec", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver 0.9.0", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver 1.0.4", -] - -[[package]] -name = "ryu" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" - -[[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 = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - -[[package]] -name = "serde" -version = "1.0.133" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_cbor" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" -dependencies = [ - "half", - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.133" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2bb9cd061c5865d345bb02ca49fcef1391741b672b54a0bf7b679badec3142" -dependencies = [ - "itoa 1.0.1", - "ryu", - "serde", -] - -[[package]] -name = "sha3" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f935e31cf406e8c0e96c2815a5516181b7004ae8c5f296293221e9b1e356bd" -dependencies = [ - "digest", - "keccak", -] - -[[package]] -name = "sharded-slab" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "smallvec" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" - -[[package]] -name = "spin" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5" -dependencies = [ - "lock_api", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "stats_alloc" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a260c96bf26273969f360c2fc2e2c7732acc2ce49d939c7243c7230c2ad179d0" - -[[package]] -name = "syn" -version = "1.0.85" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "terminal_size" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "thiserror" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thread_local" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" -dependencies = [ - "once_cell", -] - -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "tracing" -version = "0.1.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" -dependencies = [ - "cfg-if", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-chrome" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fa213f0cfbe503fb51065f2663726b093dac7cda39401eac060d0ebd4b8415c" -dependencies = [ - "json", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "tracing-core" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "tracing-log" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" -dependencies = [ - "lazy_static", - "log", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d81bfa81424cc98cb034b837c985b7a290f592e5b4322f353f94a0ab0f9f594" -dependencies = [ - "ansi_term", - "sharded-slab", - "smallvec", - "thread_local", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "tracing-tracy" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773057bb2b440e868776522a0587f732b1125116f12aca0eb37dea48d55ad2cd" -dependencies = [ - "tracing-core", - "tracing-subscriber", - "tracy-client", -] - -[[package]] -name = "tracing-unwrap" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7908a5f1475756bd7f81d6fe7e3607f13b33562c3ec8f9fb7502df790350f74a" -dependencies = [ - "tracing", -] - -[[package]] -name = "tracy-client" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62c0e37fbf87980abd5c35c3d86fd150c5ed349c3ae90959ba1877c799388203" -dependencies = [ - "tracy-client-sys", -] - -[[package]] -name = "tracy-client-sys" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6226e4e77f0d46ce7ebb0a4b1daa82790035248b75bbf605b932a1d7b3b22b6d" -dependencies = [ - "cc", -] - -[[package]] -name = "typenum" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" - -[[package]] -name = "unicode-width" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "unindent" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7" - -[[package]] -name = "vcell" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - -[[package]] -name = "volatile-register" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" -dependencies = [ - "vcell", -] - -[[package]] -name = "walkdir" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" -dependencies = [ - "same-file", - "winapi", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "wasm-bindgen" -version = "0.2.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" -dependencies = [ - "bumpalo", - "lazy_static", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" - -[[package]] -name = "web-sys" -version = "0.3.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[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.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 210a1d4..fbcaba0 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -18,59 +18,58 @@ lto = "fat" [dependencies] -pyo3 = { version = "0.15.1", features = ["extension-module","eyre"] } +pyo3 = { version = "0.16.5", features = ["extension-module","eyre","abi3-py37"] } csv = "1.1.6" humantime = "2.1.0" permutohedron = "0.2.4" -serde_json = "1.0.74" +serde_json = "1.0.81" fnv = "1.0.7" bincode = "1.3.3" -sha3 = "0.10.0" +sha3 = "0.10.1" byteorder = "1.4.3" -rstar = "0.9.2" -crossbeam-channel = "0.5.2" +rstar = "0.9.3" +crossbeam-channel = "0.5.4" better-panic = "0.3.0" derivative = "2.2.0" dict_derive = "0.4.0" -regex = "1.5.4" +regex = "1.5.6" num_cpus = "1.13.1" eddie = "0.4.2" -thiserror = "1.0.30" -pyo3-log = "0.5.0" -log = "0.4.14" -flate2 = "1.0.22" +thiserror = "1.0.31" +pyo3-log = "0.6.0" +log = "0.4.17" +flate2 = "1.0.24" eval = "0.4.3" -pythonize = "0.15.0" +pythonize = "0.16.0" itertools = "0.10.3" -intmap = "0.7.1" -diff-struct = "0.4.1" rustc-hash = "1.1.0" -stats_alloc = "0.1.8" +stats_alloc = "0.1.10" -tracing = { version = "0.1.29", optional = true } -tracing-subscriber = { version = "0.3.5", optional = true } -tracing-tracy = { version = "0.8.0", optional = true } -tracing-unwrap = { version = "0.9.2", optional = true } -tracy-client = { version = "0.12.6", optional = true } -tracing-chrome = "0.4.0" -rand = "0.8.4" -eyre = "0.6.6" +tracing = { version = "0.1.34", optional = true } +tracing-subscriber = { version = "0.3.11", optional = true } +tracing-tracy = { version = "0.10.0", optional = true } +# tracing-unwrap = { version = "0.9.2", optional = true } +tracy-client = { version = "0.14.0", optional = true } +tracing-chrome = "0.6.0" +rand = "0.8.5" +eyre = "0.6.8" memmap = "0.7.0" csv-core = "0.1.10" -postcard = { version = "0.7.3", features = ["alloc"] } nohash-hasher = "0.2.0" +dashmap = "5.3.4" +rayon = "1.5.3" [features] -profiling = ["tracing","tracing-subscriber","tracing-tracy","tracing-unwrap","tracy-client"] +profiling = ["tracing","tracing-subscriber","tracing-tracy","tracy-client"] [dev-dependencies] criterion = { version = "0.3.5", features = ["real_blackbox"] } -rand = "0.8.4" -rand_distr = "0.4.2" +rand = "0.8.5" +rand_distr = "0.4.3" [dependencies.serde] -version = "1.0.133" +version = "1.0.137" features = ["derive"] diff --git a/rust/Dockerfile b/rust/Dockerfile new file mode 100644 index 0000000..acdca0a --- /dev/null +++ b/rust/Dockerfile @@ -0,0 +1,5 @@ +FROM ghcr.io/pyo3/maturin + +LABEL ed_lrr_dev latest +RUN rustup default nightly +RUN pip install maturin[zig] \ No newline at end of file diff --git a/rust/clippy.toml b/rust/clippy.toml new file mode 100644 index 0000000..4dc4c31 --- /dev/null +++ b/rust/clippy.toml @@ -0,0 +1 @@ +disallowed-types = ["std::collections::HashMap", "std::collections::HashSet"] \ No newline at end of file diff --git a/rust/docker-compose.yml b/rust/docker-compose.yml new file mode 100644 index 0000000..bfa5627 --- /dev/null +++ b/rust/docker-compose.yml @@ -0,0 +1,8 @@ +version: "4.0" +services: + ed_lrr_build: + build: . + working_dir: /code + command: ["build","-r","--zig", "--compatibility","manylinux2010"] + volumes: + - .:/code \ No newline at end of file diff --git a/rust/run_test.py b/rust/run_test.py index 8f9fd3d..27504ba 100644 --- a/rust/run_test.py +++ b/rust/run_test.py @@ -6,32 +6,46 @@ import shutil import json -def setup_logging(loglevel="INFO"): +def setup_logging(loglevel="INFO", file=False): import logging import coloredlogs - coloredlogs.DEFAULT_FIELD_STYLES["delta"] = {"color": "green"} - coloredlogs.DEFAULT_FIELD_STYLES["levelname"] = {"color": "yellow"} + logfmt = " | ".join( + ["[%(delta)s] %(levelname)s", "%(name)s:%(pathname)s:%(lineno)s", "%(message)s"] + ) - class DeltaTimeFormatter(coloredlogs.ColoredFormatter): + class ColorDeltaTimeFormatter(coloredlogs.ColoredFormatter): def format(self, record): seconds = record.relativeCreated / 1000 duration = timedelta(seconds=seconds) record.delta = str(duration) return super().format(record) - coloredlogs.ColoredFormatter = DeltaTimeFormatter - logfmt = " | ".join( - ["[%(delta)s] %(levelname)s", "%(name)s:%(pathname)s:%(lineno)s", "%(message)s"] - ) + class DeltaTimeFormatter(coloredlogs.BasicFormatter): + def format(self, record): + seconds = record.relativeCreated / 1000 + duration = timedelta(seconds=seconds) + record.delta = str(duration) + return super().format(record) + + logger = logging.getLogger() + if file: + open("ed_lrr_test.log", "w").close() + fh = logging.FileHandler("ed_lrr_test.log") + fh.setLevel(logging.DEBUG) + fh.setFormatter(DeltaTimeFormatter(logfmt)) + logger.addHandler(fh) + coloredlogs.DEFAULT_FIELD_STYLES["delta"] = {"color": "green"} + coloredlogs.DEFAULT_FIELD_STYLES["levelname"] = {"color": "yellow"} + + coloredlogs.ColoredFormatter = ColorDeltaTimeFormatter numeric_level = getattr(logging, loglevel.upper(), None) if not isinstance(numeric_level, int): raise ValueError("Invalid log level: %s" % loglevel) - coloredlogs.install(level=numeric_level, fmt=logfmt) + coloredlogs.install(level=numeric_level, fmt=logfmt, logger=logger) + return -setup_logging() - JUMP_RANGE = 48 globals().setdefault("__file__", r"D:\devel\rust\ed_lrr_gui\rust\run_test.py") dirname = os.path.dirname(__file__) or "." @@ -39,28 +53,38 @@ os.chdir(dirname) t_start = datetime.now() os.environ["PYO3_PYTHON"] = sys.executable if "--clean" in sys.argv[1:]: - SP.check_call(["cargo","clean"]) + SP.check_call(["cargo", "clean"]) if "--build" in sys.argv[1:]: - SP.check_call(["cargo","lcheck"]) + SP.check_call(["cargo", "lcheck"]) SP.check_call([sys.executable, "-m", "pip", "install", "-e", ".."]) print("Build+Install took:", datetime.now() - t_start) sys.path.append("..") +setup_logging(file=True) _ed_lrr = __import__("_ed_lrr") + def callback(state): print(state) + + print(_ed_lrr) -r = _ed_lrr.PyRouter(callback) -r.load("../stars_2.csv", immediate=False) -print(r) -r.str_tree_test() - -exit() - r = _ed_lrr.PyRouter(callback) r.load("../stars.csv", immediate=False) -print(r.resolve("Sol","Saggitarius A","Colonia","Merope")) +# r.nb_perf_test(JUMP_RANGE) +# exit() +# start, end = "Sol", "Colonia" +# systems = r.resolve(start, end) +# sys_ids = {k: v["id"] for k, v in systems.items()} + +r.bfs_test(JUMP_RANGE) + +# cfg = {} +# cfg["mode"] = "incremental_broadening" +# # input("{}>".format(os.getpid())) +# # route = r.precompute_neighbors(JUMP_RANGE) +# route = r.route([sys_ids[start], sys_ids[end]], JUMP_RANGE, cfg, 0) +# print("Optimal route:", len(route)) exit() @@ -68,10 +92,12 @@ ships = _ed_lrr.PyShip.from_journal() r = _ed_lrr.PyRouter(callback) r.load("../stars.csv", immediate=False) -def func(*args,**kwargs): + +def func(*args, **kwargs): print(kwargs) return 12 + r.precompute_neighbors(JUMP_RANGE) exit() @@ -119,6 +145,7 @@ start, end = "Sol", "Colonia" systems = r.resolve(start, end) sys_ids = {k: v["id"] for k, v in systems.items()} + cfg = {} cfg["mode"] = "incremental_broadening" # input("{}>".format(os.getpid())) diff --git a/rust/rust-toolchain.toml b/rust/rust-toolchain.toml new file mode 100644 index 0000000..b33505e --- /dev/null +++ b/rust/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" \ No newline at end of file diff --git a/rust/src/common.rs b/rust/src/common.rs index 94eb183..9d6d0ae 100644 --- a/rust/src/common.rs +++ b/rust/src/common.rs @@ -1,11 +1,12 @@ //! # Common utlility functions -use crate::route::{LineCache, Router}; +use crate::route::Router; use bincode::Options; use crossbeam_channel::{bounded, Receiver}; use csv::ByteRecord; use dict_derive::IntoPyObject; use eyre::Result; use log::*; +use nohash_hasher::NoHashHasher; use pyo3::prelude::*; use pyo3::types::PyDict; use pyo3::{conversion::ToPyObject, create_exception}; @@ -13,8 +14,7 @@ use pythonize::depythonize; use serde::{Deserialize, Serialize}; use sha3::{Digest, Sha3_256}; use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; -use std::hash::{Hash, Hasher, BuildHasherDefault}; -use std::io::Write; +use std::hash::{BuildHasherDefault, Hash, Hasher}; use std::ops::{Deref, DerefMut}; use std::path::Path; use std::str::FromStr; @@ -25,22 +25,21 @@ use std::{ io::{BufReader, BufWriter}, path::PathBuf, }; -use nohash_hasher::NoHashHasher; use thiserror::Error; #[inline(always)] pub fn heuristic(range: f32, node: &TreeNode, goal: &TreeNode) -> f32 { // distance remaining after jumping from node towards goal - let a2 = dist2(&node.pos, &goal.pos); - let mult=node.get_mult(); - let b2 = range * range * mult*mult; + let a2 = dist(&node.pos, &goal.pos); + let mult = node.get_mult(); + let b2 = range * mult; return (a2 - b2).max(0.0); } /// Min-heap priority queue using f32 as priority -pub struct MinFHeap(pub BinaryHeap<(Reverse, T)>); +pub struct MinFHeap(BinaryHeap<(Reverse, T)>); /// Max-heap priority queue using f32 as priority -pub struct MaxFHeap(pub BinaryHeap<(F32, T)>); +pub struct MaxFHeap(BinaryHeap<(F32, T)>); impl MaxFHeap { /// Create new, empty priority queue @@ -391,7 +390,7 @@ pub enum SysEntry { } impl ToPyObject for SysEntry { - fn to_object(&self, py: Python) -> PyObject { + fn to_object(&self, py: Python<'_>) -> PyObject { match self { Self::ID(id) => id.to_object(py), Self::Name(name) => name.to_object(py), @@ -483,99 +482,6 @@ pub fn ndot(u: &[f32; 3], v: &[f32; 3]) -> f32 { (u[0] * v[0]) / lm + (u[1] * v[1]) / lm + (u[2] * v[2]) / lm } -/// Fuzzy string matcher, use to resolve star system names -#[cfg_attr(feature = "profiling", tracing::instrument(skip(rx)))] -fn matcher( - rx: Receiver, - names: Vec, - exact: bool, -) -> HashMap)> { - let mut best: HashMap)> = HashMap::new(); - for name in &names { - best.insert(name.to_string(), (0.0, None)); - } - let names_u8: Vec<(String, _)> = names.iter().map(|n| (n.clone(), n.as_bytes())).collect(); - let sdist = eddie::slice::Levenshtein::new(); - for sys in rx.into_iter() { - for (name, name_b) in &names_u8 { - if let Some(ent) = best.get_mut(name) { - if (ent.0 - 1.0).abs() < std::f64::EPSILON { - continue; - } - if exact && (&sys[1] == *name_b) { - let id = std::str::from_utf8(&sys[0]).unwrap().parse().unwrap(); - *ent = (1.0, Some(id)); - continue; - } - let d = sdist.similarity(&sys[1], name_b); - if d > ent.0 { - let id = std::str::from_utf8(&sys[0]).unwrap().parse().unwrap(); - *ent = (d, Some(id)); - } - }; - } - } - best -} - -/// Scan through the csv file at `path` and return a hash map -/// mapping the strings from `names` to a tuple `(score, Option)`. -/// Scoring matching uses the normalized Levenshtein distance where 1.0 is an exact match. -pub fn find_matches( - path: &Path, - names: Vec, - exact: bool, -) -> Result)>, String> { - let mut best: HashMap)> = HashMap::new(); - if names.is_empty() { - return Ok(best); - } - for name in &names { - best.insert(name.to_string(), (0.0, None)); - } - - let mut workers = Vec::new(); - let ncpus = num_cpus::get(); - let (tx, rx) = bounded(4096 * ncpus); - for _ in 0..ncpus { - let names = names.clone(); - let rx = rx.clone(); - let th = thread::spawn(move || matcher(rx, names, exact)); - workers.push(th); - } - - let mut rdr = match csv::ReaderBuilder::new().has_headers(false).from_path(path) { - Ok(rdr) => rdr, - Err(e) => { - return Err(format!("Error opening {}: {}", path.to_str().unwrap(), e)); - } - }; - let t_start = std::time::Instant::now(); - let mut processed: usize = 0; - for record in rdr.byte_records().flat_map(|v| v.ok()) { - tx.send(record).unwrap(); - processed += 1; - } - drop(tx); - while let Some(th) = workers.pop() { - for (name, (score, sys)) in th.join().unwrap().iter() { - best.entry(name.clone()).and_modify(|ent| { - if score > &ent.0 { - *ent = (*score, *sys); - } - }); - } - } - let dt = std::time::Instant::now() - t_start; - info!( - "Searched {} records in {:?}: {} records/second", - processed, - dt, - (processed as f64) / dt.as_secs_f64() - ); - Ok(best) -} - /// Hash the contents of `path` with sha3 and return the hash as a vector of bytes fn hash_file(path: &Path) -> Vec { let mut hash_reader = BufReader::new(File::open(path).unwrap()); @@ -632,7 +538,7 @@ pub struct TreeNode { } impl ToPyObject for TreeNode { - fn to_object(&self, py: Python) -> PyObject { + fn to_object(&self, py: Python<'_>) -> PyObject { pythonize::pythonize(py, self).unwrap() } } @@ -647,7 +553,7 @@ impl TreeNode { match self.flags { 0b11 => 4.0, 0b10 => 1.5, - _ => 1.0 + _ => 1.0, } } } @@ -696,22 +602,21 @@ pub struct System { impl System { fn get_flags(&self) -> u8 { - let mut flags=0; - if self.mult==4.0 { - return 0b11 + if self.mult == 4.0 { + return 0b11; } - if self.mult==1.5 { - return 0b10 + if self.mult == 1.5 { + return 0b10; } if self.has_scoopable { - return 0b01 + return 0b01; } - return 0b00 + return 0b00; } } impl ToPyObject for System { - fn to_object(&self, py: Python) -> PyObject { + fn to_object(&self, py: Python<'_>) -> PyObject { let d = PyDict::new(py); d.set_item("id", self.id).unwrap(); d.set_item("name", self.name.clone()).unwrap(); @@ -771,51 +676,55 @@ impl Default for DQueue { } } - - #[derive(Debug, Default, Serialize, Deserialize)] struct BKTreeNode { - ids: HashSet>>, - children: HashMap>> + ids: HashSet>>, + children: HashMap>>, } impl BKTreeNode { fn new(data: &[String], dist: &eddie::str::Levenshtein) -> Self { - let mut tree= Self::default(); - let mut max_depth=0; - (0..data.len()).map(|id| { - max_depth=max_depth.max(tree.insert(data,id as u32, dist,0)); - if (id>0) && (id%100_000 == 0) { - println!("Inserting ID {}, Max Depth: {}",id,max_depth); - } - }).max(); - println!("Max Depth: {}",max_depth); + let mut tree = Self::default(); + let mut max_depth = 0; + (0..data.len()) + .map(|id| { + max_depth = max_depth.max(tree.insert(data, id as u32, dist, 0)); + if (id > 0) && (id % 100_000 == 0) { + println!("Inserting ID {}, Max Depth: {}", id, max_depth); + } + }) + .max(); + println!("Max Depth: {}", max_depth); tree } fn from_id(id: u32) -> Self { - let mut ret=Self::default(); + let mut ret = Self::default(); ret.ids.insert(id); return ret; } - fn insert(&mut self, data: &[String],id: u32, dist: &eddie::str::Levenshtein, depth: usize) -> usize { + fn insert( + &mut self, + data: &[String], + id: u32, + dist: &eddie::str::Levenshtein, + depth: usize, + ) -> usize { if self.is_empty() { self.ids.insert(id); return depth; } let idx = self.get_id().unwrap() as usize; - let self_key = data.get(idx).unwrap(); - let ins_key = data.get(id as usize).unwrap(); - let dist_key = dist.distance(self_key,ins_key) as u8; - if dist_key==0 { + let dist_key = dist.distance(&data[idx], &data[id as usize]) as u8; + if dist_key == 0 { self.ids.insert(id); return depth; } if let Some(child) = self.children.get_mut(&dist_key) { - return child.insert(data,id,dist,depth+1); + return child.insert(data, id, dist, depth + 1); } else { - self.children.insert(dist_key,Self::from_id(id)); + self.children.insert(dist_key, Self::from_id(id)); return depth; } } @@ -835,13 +744,11 @@ pub struct BKTree { root: BKTreeNode, } - - impl BKTree { pub fn new(data: &[String], base_id: u32) -> Self { let dist = eddie::str::Levenshtein::new(); let root = BKTreeNode::new(data, &dist); - Self {base_id,root} + Self { base_id, root } } pub fn id(&self) -> u32 { @@ -851,8 +758,8 @@ impl BKTree { pub fn dump(&self, fh: &mut BufWriter) -> EdLrrResult<()> { let options = bincode::DefaultOptions::new(); let amt = options.serialized_size(self)?; - println!("Writing {}",amt); - options.serialize_into(fh,self)?; + println!("Writing {}", amt); + options.serialize_into(fh, self)?; Ok(()) } diff --git a/rust/src/lib.rs b/rust/src/lib.rs index fdf721f..0143205 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -1,4 +1,6 @@ +#![feature(binary_heap_retain)] #![allow(dead_code, clippy::needless_return, clippy::too_many_arguments)] +#![warn(rust_2018_idioms, rust_2021_compatibility, clippy::disallowed_types)] //! # Elite: Danerous Long Range Router pub mod common; pub mod galaxy; @@ -10,13 +12,9 @@ pub mod route; pub mod search_algos; pub mod ship; -use bincode::Options; -use csv::{Position, StringRecord}; -use eddie::Levenshtein; // ========================= use stats_alloc::{Region, StatsAlloc, INSTRUMENTED_SYSTEM}; use std::alloc::System as SystemAlloc; -use std::cell::RefMut; use std::collections::BTreeMap; use std::io::{BufWriter, Write}; use std::path::Path; @@ -30,8 +28,7 @@ mod profiling { pub fn init() {} } -extern crate derivative; -use crate::common::{find_matches, grid_stats, EdLrrError, SysEntry, System}; +use crate::common::{grid_stats, EdLrrError, SysEntry, System}; #[cfg(feature = "profiling")] use crate::profiling::*; use crate::route::{Router, SearchState}; @@ -39,16 +36,14 @@ use crate::ship::Ship; use eyre::Result; #[cfg(not(feature = "profiling"))] use log::*; +use pyo3::create_exception; use pyo3::exceptions::*; use pyo3::prelude::*; use pyo3::types::{IntoPyDict, PyDict, PyTuple}; -use pyo3::{create_exception, PyObjectProtocol}; -use route::{LineCache, PyModeConfig}; -use std::{ - cell::RefCell, collections::HashMap, convert::TryInto, fs::File, io::BufReader, path::PathBuf, -}; +use route::PyModeConfig; +use std::{collections::HashMap, convert::TryInto, fs::File, path::PathBuf}; -#[cfg(feature = "profiling")] +#[cfg(feature = "mem_profiling")] #[global_allocator] static GLOBAL: ProfiledAllocator = ProfiledAllocator::new(std::alloc::System, 1024); @@ -87,8 +82,6 @@ impl PyRouter { .ok_or_else(|| PyErr::from(EdLrrError::RuntimeError("no stars.csv loaded".to_owned()))) .map(PathBuf::from) } - - } #[pymethods] @@ -115,25 +108,23 @@ impl PyRouter { #[args(primary_only = "false", immediate = "false")] #[pyo3(text_signature = "(path, primary_only, /)")] - fn load(&mut self, path: String, py: Python, immediate: bool) -> PyResult { + fn load(&mut self, path: String, py: Python<'_>, immediate: bool) -> PyResult { self.stars_path = Some(path); if immediate { - let stars_path = self.check_stars()?; - let route_res = self.router.load(&stars_path); - if let Err(err_msg) = route_res { - return Err(PyErr::new::(err_msg)); - }; + self.router + .load(&self.check_stars()?) + .map_err(PyErr::new::)?; } Ok(py.None()) } #[pyo3(text_signature = "(/)")] - fn unload(&mut self, py: Python) -> PyObject { + fn unload(&mut self, py: Python<'_>) -> PyObject { self.router.unload(); py.None() } - fn plot(&mut self, py: Python) -> PyResult { + fn plot(&mut self, py: Python<'_>) -> PyResult { let stars_path = self.check_stars()?; let route_res = self.router.load(&stars_path); if let Err(err_msg) = route_res { @@ -155,7 +146,7 @@ impl PyRouter { Ok(plot_bbox.to_object(py)) } - fn run_bfs(&mut self, range: f32, py: Python) -> PyResult { + fn run_bfs(&mut self, range: f32, py: Python<'_>) -> PyResult { let stars_path = self.check_stars()?; let route_res = self.router.load(&stars_path); if let Err(err_msg) = route_res { @@ -167,7 +158,7 @@ impl PyRouter { .map(|_| py.None()) } - fn precompute_graph(&mut self, range: f32, py: Python) -> PyResult { + fn precompute_graph(&mut self, range: f32, py: Python<'_>) -> PyResult { let stars_path = self.check_stars()?; let route_res = self.router.load(&stars_path); if let Err(err_msg) = route_res { @@ -179,31 +170,29 @@ impl PyRouter { .map(|_| py.None()) } - fn nb_perf_test(&mut self, range: f32, py: Python) -> PyResult { + fn nb_perf_test(&mut self, range: f32, py: Python<'_>) -> PyResult { let stars_path = self.check_stars()?; let route_res = self.router.load(&stars_path); if let Err(err_msg) = route_res { return Err(PyErr::new::(err_msg)); }; - let mut nbmap = BTreeMap::new(); let tree = self.router.get_tree(); let total_nodes = tree.size(); + let mut total_nbs = 0; for (n, node) in tree.iter().enumerate() { - let nbs = self - .router - .neighbours(node, range) - .map(|nb| nb.id) - .collect::>(); - nbmap.insert(node.id, nbs); + total_nbs += self.router.neighbours(node, range).count(); + // nbmap.insert(node.id, nbs); if n % 100_000 == 0 { - println!("{}/{}", n, total_nodes); + let avg = total_nbs as f64 / (n + 1) as f64; + info!("{}/{} {} ({})", n, total_nodes, total_nbs, avg); } } - println!("{}", nbmap.len()); + let avg = total_nbs as f64 / total_nodes as f64; + info!("Total: {} ({})", total_nbs, avg); Ok(py.None()) } - fn precompute_neighbors(&mut self, range: f32, py: Python) -> PyResult { + fn precompute_neighbors(&mut self, range: f32, py: Python<'_>) -> PyResult { let stars_path = self.check_stars()?; let route_res = self.router.load(&stars_path); if let Err(err_msg) = route_res { @@ -215,6 +204,36 @@ impl PyRouter { .map(|_| py.None()) } + fn bfs_test(&mut self, range: f32) -> PyResult<()> { + use rand::prelude::*; + let stars_path = self.check_stars()?; + let route_res = self.router.load(&stars_path); + if let Err(err_msg) = route_res { + return Err(PyErr::new::(err_msg)); + }; + let mut rng = rand::rngs::StdRng::seed_from_u64(0); + let nodes = self.router.get_tree().size(); + loop { + let source = *self + .router + .get_tree() + .iter() + .nth(rng.gen_range(0..nodes)) + .unwrap(); + let goal = *self + .router + .get_tree() + .iter() + .nth(rng.gen_range(0..nodes)) + .unwrap(); + self.router.bfs_loop_test(range, &source, &goal, 0); + for w in 0..=15 { + self.router.bfs_loop_test(range, &source, &goal, 2usize.pow(w)); + } + } + Ok(()) + } + #[args( greedyness = "0.5", max_dist = "0.0", @@ -238,7 +257,7 @@ impl PyRouter { let ids: Vec = match resolve(&hops, &self.router.path, true) { Ok(sytems) => sytems.into_iter().map(|id| id.into_id()).collect(), Err(err_msg) => { - return Err(EdLrrError::ResolveError(err_msg).into()); + return Err(err_msg.into()); } }; let mut is_default = false; @@ -287,7 +306,7 @@ impl PyRouter { return res; } - fn perf_test(&self, callback: PyObject, py: Python) -> PyResult { + fn perf_test(&self, callback: PyObject, py: Python<'_>) -> PyResult { use common::TreeNode; let node = TreeNode { pos: [-65.21875, 7.75, -111.03125], @@ -320,22 +339,34 @@ impl PyRouter { #[args(grid_size = "1.0")] #[pyo3(text_signature = "(grid_size)")] - fn get_grid(&self, grid_size: f32, py: Python) -> PyResult { + fn get_grid(&self, grid_size: f32, py: Python<'_>) -> PyResult { let stars_path = self.check_stars()?; grid_stats(&stars_path, grid_size) .map(|ret| ret.to_object(py)) .map_err(PyErr::new::) } + fn floyd_warshall_test(&mut self, range: f32) -> PyResult> { + let stars_path = self.check_stars()?; + self.router + .load(&stars_path) + .map_err(PyErr::new::)?; + let res = self + .router + .floyd_warshall(range) + .map_err(PyErr::new::)?; + Ok(res) + } + #[args(hops = "*")] #[pyo3(text_signature = "(sys_1, sys_2, ..., /)")] - fn resolve(&self, hops: Vec, py: Python) -> PyResult { + fn resolve(&self, hops: Vec, py: Python<'_>) -> PyResult { info!("Resolving systems..."); let stars_path = self.check_stars()?; let systems: Vec = match resolve(&hops, &stars_path, false) { Ok(sytems) => sytems.into_iter().map(|sys| sys.into_system()).collect(), Err(err_msg) => { - return Err(EdLrrError::ResolveError(err_msg).into()); + return Err(err_msg.into()); } }; let ret: Vec<(_, System)> = hops @@ -356,15 +387,15 @@ impl PyRouter { .map_err(EdLrrError::from)?; let mut data: Vec = Vec::with_capacity(CHUNK_SIZE); let t_start = Instant::now(); - let mut base_id=0; + let mut base_id = 0; let mut wr = BufWriter::new(File::create("test.bktree")?); for sys in reader.into_deserialize::() { let sys = sys?; data.push(sys.name); - if data.len()>CHUNK_SIZE { + if data.len() > CHUNK_SIZE { let tree = BKTree::new(&data, base_id); tree.dump(&mut wr)?; - base_id=sys.id; + base_id = sys.id; } } if !data.is_empty() { @@ -375,10 +406,7 @@ impl PyRouter { println!("Took: {:?}", t_start.elapsed()); Ok(()) } -} -#[pyproto] -impl PyObjectProtocol for PyRouter { fn __str__(&self) -> PyResult { Ok(format!("{:?}", &self)) } @@ -387,7 +415,6 @@ impl PyObjectProtocol for PyRouter { Ok(format!("{:?}", &self)) } } - enum ResolveResult { System(System), ID(u32), @@ -409,7 +436,11 @@ impl ResolveResult { } } -fn resolve(entries: &[SysEntry], path: &Path, id_only: bool) -> Result, String> { +fn resolve( + entries: &[SysEntry], + path: &Path, + id_only: bool, +) -> Result, EdLrrError> { let mut names: Vec = Vec::new(); let mut ret: Vec = Vec::new(); let mut needs_rtree = false; @@ -423,7 +454,10 @@ fn resolve(entries: &[SysEntry], path: &Path, id_only: bool) -> Result Result { - let ent_res = name_ids - .get(name) - .ok_or(format!("System {} not found", name))?; - let sys = ent_res - .as_ref() - .ok_or(format!("System {} not found", name))?; + let ent_res = name_ids.get(name).ok_or_else(|| { + EdLrrError::ResolveError(format!("System {} not found", name)) + })?; + let sys = ent_res.as_ref().ok_or_else(|| { + EdLrrError::ResolveError(format!("System {} not found", name)) + })?; ret.push(*sys); } SysEntry::ID(id) => ret.push(*id), @@ -453,7 +487,7 @@ fn resolve(entries: &[SysEntry], path: &Path, id_only: bool) -> Result Result PyResult { - Ok(format!("{:?}", &self.ship)) - } - - fn __repr__(&self) -> PyResult { - Ok(format!("{:?}", &self.ship)) - } -} - #[pymethods] impl PyShip { #[staticmethod] - fn from_loadout(py: Python, loadout: &str) -> PyResult { + fn from_loadout(py: Python<'_>, loadout: &str) -> PyResult { match Ship::new_from_json(loadout) { Ok(ship) => Ok((PyShip { ship: ship.1 }).into_py(py)), Err(err_msg) => Err(PyErr::new::(err_msg)), } } #[staticmethod] - fn from_journal(py: Python) -> PyResult { + fn from_journal(py: Python<'_>) -> PyResult { let mut ship = match Ship::new_from_journal() { Ok(ship) => ship, Err(err_msg) => { @@ -516,38 +538,38 @@ impl PyShip { Ok(PyDict::from_sequence(py, ships.to_object(py))?.to_object(py)) } - fn to_dict(&self, py: Python) -> PyResult { + fn to_dict(&self, py: Python<'_>) -> PyResult { self.ship.to_object(py) } #[pyo3(text_signature = "(dist, /)")] - fn fuel_cost(&self, _py: Python, dist: f32) -> f32 { + fn fuel_cost(&self, _py: Python<'_>, dist: f32) -> f32 { self.ship.fuel_cost(dist) } #[getter] - fn range(&self, _py: Python) -> f32 { + fn range(&self, _py: Python<'_>) -> f32 { self.ship.range() } #[getter] - fn max_range(&self, _py: Python) -> f32 { + fn max_range(&self, _py: Python<'_>) -> f32 { self.ship.max_range() } #[pyo3(text_signature = "(dist, /)")] - fn make_jump(&mut self, dist: f32, _py: Python) -> Option { + fn make_jump(&mut self, dist: f32, _py: Python<'_>) -> Option { self.ship.make_jump(dist) } #[pyo3(text_signature = "(dist, /)")] - fn can_jump(&self, dist: f32, _py: Python) -> bool { + fn can_jump(&self, dist: f32, _py: Python<'_>) -> bool { self.ship.can_jump(dist) } #[args(fuel_amount = "None")] #[pyo3(text_signature = "(fuel_amount, /)")] - fn refuel(&mut self, fuel_amount: Option, _py: Python) { + fn refuel(&mut self, fuel_amount: Option, _py: Python<'_>) { if let Some(fuel) = fuel_amount { self.ship.fuel_mass = (self.ship.fuel_mass + fuel).min(self.ship.fuel_capacity) } else { @@ -556,9 +578,17 @@ impl PyShip { } #[pyo3(text_signature = "(factor, /)")] - fn boost(&mut self, factor: f32, _py: Python) { + fn boost(&mut self, factor: f32, _py: Python<'_>) { self.ship.boost(factor); } + + fn __str__(&self) -> PyResult { + Ok(format!("{:?}", &self.ship)) + } + + fn __repr__(&self) -> PyResult { + Ok(format!("{:?}", &self.ship)) + } } impl PyShip { @@ -572,14 +602,14 @@ fn preprocess_edsm( _bodies_path: &str, _systems_path: &str, _out_path: &str, - _py: Python, + _py: Python<'_>, ) -> PyResult<()> { Err(pyo3::exceptions::PyNotImplementedError::new_err( "please use Spansh's Galaxy dump and preprocess_galaxy()", )) } -fn to_py_value(value: eval::Value, py: Python) -> PyResult { +fn to_py_value(value: eval::Value, py: Python<'_>) -> PyResult { type Value = eval::Value; match value { Value::String(s) => Ok(s.to_object(py)), @@ -611,14 +641,14 @@ fn to_py_value(value: eval::Value, py: Python) -> PyResult { } } -fn to_py(res: Result, py: Python) -> PyResult { +fn to_py(res: Result, py: Python<'_>) -> PyResult { res.map_err(|e| PyErr::from(EdLrrError::EvalError(e))) .and_then(|r| to_py_value(r, py)) } #[pyfunction] #[pyo3(text_signature = "(expr)")] -fn expr_test(expr: &str, py: Python) -> PyResult { +fn expr_test(expr: &str, py: Python<'_>) -> PyResult { use eval::{to_value, Expr, Value}; let mut res = Expr::new(expr) .compile() @@ -647,7 +677,7 @@ fn preprocess_galaxy(path: &str, out_path: &str) -> PyResult<()> { } #[pymodule] -pub fn _ed_lrr(_py: Python, m: &PyModule) -> PyResult<()> { +pub fn _ed_lrr(_py: Python<'_>, m: &PyModule) -> PyResult<()> { better_panic::install(); pyo3_log::init(); profiling::init(); diff --git a/rust/src/mmap_csv.rs b/rust/src/mmap_csv.rs index 16a0930..f8d7a66 100644 --- a/rust/src/mmap_csv.rs +++ b/rust/src/mmap_csv.rs @@ -1,26 +1,62 @@ use crate::common::{EdLrrError, EdLrrResult, System}; use crate::info; +use crossbeam_channel::bounded; use csv_core::{ReadFieldResult, Reader}; +use dashmap::DashMap; +use eyre::Result; +use itertools::Itertools; use memmap::Mmap; use std::collections::HashMap; use std::fs::File; use std::path::Path; +use std::sync::Arc; -pub fn mmap_csv(path: &Path, query: Vec) -> Result>, String> { - let file = File::open(path).map_err(|e| e.to_string())?; - let mm = unsafe { Mmap::map(&file) }.map_err(|e| e.to_string())?; - let mut best = query - .iter() - .map(|s| (s, (s.as_bytes(), usize::MAX, u32::MAX))) - .collect::>(); - let t_start = std::time::Instant::now(); - let dist = eddie::slice::DamerauLevenshtein::new(); - let mut row = 0; - { - let mut data = &mm[..]; +struct MmapCsv { + mm: Mmap, +} + +impl MmapCsv { + fn new(path: &Path) -> Result { + let file = File::open(path)?; + let mm = unsafe { Mmap::map(&file) }?; + Ok(Self { mm }) + } + + fn search(&self, query: Vec) -> Result>, EdLrrError> { + let t_start = std::time::Instant::now(); + let map = Arc::new(DashMap::new()); + let (tx, rx) = bounded(1024); + let query_b = query.iter().map(|s| s.bytes().collect_vec()).collect_vec(); + let mut workers = (0..(num_cpus::get())) + .map(|_| { + let query_b = query_b.clone(); + let query = query.clone(); + let rx = rx.clone(); + let map = map.clone(); + std::thread::spawn(move || { + let dist = eddie::slice::DamerauLevenshtein::new(); + rx.into_iter() + // .flatten() + .for_each(|(id, name): (_, Vec)| { + for (query, query_b) in query.iter().zip(query_b.iter()) { + let d = dist.distance(name.as_slice(), query_b); + let mut e = map.entry(query.clone()).or_insert((usize::MAX, None)); + if d < e.0 { + *e = (d, Some(id)); + } + } + }); + }) + }) + .collect_vec(); + drop(rx); + let mut data = &self.mm[..]; let mut rdr = Reader::new(); let mut field = [0; 1024]; let mut fieldidx = 0; + // let mut chunk = vec![]; + let mut sys_id = 0u32; + let mut row = 0; loop { let (result, nread, nwrite) = rdr.read_field(data, &mut field); data = &data[nread..]; @@ -28,18 +64,22 @@ pub fn mmap_csv(path: &Path, query: Vec) -> Result {} ReadFieldResult::OutputFull => { - return Err("Encountered field larget than 1024 bytes!".to_string()); + return Err(EdLrrError::ResolveError( + "Encountered field larget than 1024 bytes!".to_string(), + )); } ReadFieldResult::Field { record_end } => { - if fieldidx == 1 { - for (_, (name_b, best_dist, id)) in best.iter_mut() { - let d = dist.distance(name_b, field); - if d < *best_dist { - *best_dist = d; - *id = row; - } + match fieldidx { + 0 => { + sys_id = unsafe { std::str::from_utf8_unchecked(field) } + .parse::() + .unwrap(); } - } + 1 => tx + .send((sys_id, field.to_vec())) + .map_err(|e| EdLrrError::ResolveError(e.to_string()))?, + _ => (), + }; if record_end { fieldidx = 0; row += 1; @@ -54,16 +94,28 @@ pub fn mmap_csv(path: &Path, query: Vec) -> Result>(); + let rate = (row as f64) / t_start.elapsed().as_secs_f64(); + info!( + "Took: {:.2?}, {:.2} systems/second", + t_start.elapsed(), + rate + ); + Ok(res) } - let search_result = best - .drain(..) - .map(|(query_name, (_, _, idx))| (query_name.clone(), Some(idx))) - .collect::>>(); - let rate = (row as f64) / t_start.elapsed().as_secs_f64(); - info!( - "Took: {:.2?}, {:.2} systems/second", - t_start.elapsed(), - rate - ); - Ok(search_result) +} + +pub fn mmap_csv( + path: &Path, + query: Vec, +) -> Result>, EdLrrError> { + MmapCsv::new(path)?.search(query) } diff --git a/rust/src/route.rs b/rust/src/route.rs index 4216dbc..92c7554 100644 --- a/rust/src/route.rs +++ b/rust/src/route.rs @@ -7,6 +7,7 @@ use crate::profiling::{span, Level}; use crate::ship::Ship; use crossbeam_channel::{bounded, unbounded, Receiver, SendError, Sender}; +use dashmap::{DashMap, DashSet}; use derivative::Derivative; use dict_derive::IntoPyObject; @@ -18,6 +19,8 @@ use permutohedron::LexicalPermutation; use pyo3::prelude::*; use pythonize::depythonize; +use rayon::prelude::*; +use rayon::ThreadPoolBuilder; use rstar::{PointDistance, RStarInsertionStrategy, RTree, RTreeObject, RTreeParams, AABB}; use rustc_hash::{FxHashMap, FxHashSet}; use serde::{Deserialize, Serialize}; @@ -27,10 +30,11 @@ use std::fs::File; use std::hash::{Hash, Hasher}; use std::io::{BufReader, BufWriter, Write}; use std::path::PathBuf; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Mutex}; use std::thread; use std::thread::JoinHandle; -use std::time::Instant; +use std::time::{Duration, Instant}; use std::{ collections::{BinaryHeap, VecDeque}, path::Path, @@ -317,8 +321,8 @@ impl TryFrom for ModeConfig { #[allow(non_camel_case_types)] pub enum PrecomputeMode { Full, - Route_From, - Route_To, + Route_From(u32), + Route_To(u32), None, } @@ -817,6 +821,74 @@ impl Router { return self.scoopable.contains(&id); } + pub fn bfs_loop_test(&self, range: f32, source: &TreeNode, goal: &TreeNode, n: usize) -> (bool, usize, usize) { + // info!("Starting thread pool"); + // ThreadPoolBuilder::new() + // .num_threads(8) + // .build_global() + // .unwrap(); + let t_start = Instant::now(); + let route_dist = dist(&source.pos, &goal.pos); + let seen: Arc> = Arc::new(DashMap::new()); + let mut depth = 0; + let mut queue = vec![*source]; + let mut queue_next = vec![]; + let tree = self.tree.clone(); + let r2 = range * range; + let mut found = false; + while !queue.is_empty() { + depth += 1; + let seen = seen.clone(); + queue_next.extend(queue.drain(..).flat_map(|sys| { + let seen = seen.clone(); + tree.locate_within_distance(sys.pos, r2) + .filter_map(move |nb| seen.insert(nb.id, sys.id).is_none().then_some(*nb)) + })); + if seen.contains_key(&goal.id) { + found = true; + break; + } + std::mem::swap(&mut queue_next, &mut queue); + if n != 0 { + queue.sort_by_cached_key(|v| F32(heuristic(range, v, goal))); + queue.truncate(n); + } + // info!("[{}|{}] {}", goal.id, depth, queue.len()); + } + let seen = Arc::try_unwrap(seen) + .unwrap() + .into_iter() + .collect::>(); + info!( + "[{}|{}->{} ({:.02} Ly)|{}] Depth: {} Seen: {} ({:.02}%) Took: {}", + n, + source.id, + goal.id, + route_dist, + found, + depth, + seen.len(), + ((seen.len() as f64) / (tree.size() as f64)) * 100.0, + humantime::format_duration(t_start.elapsed()) + ); + return (found, depth, seen.len()); + let path=self.reconstruct(goal.id, &seen); + } + + fn reconstruct(&self, goal_id: u32, map: &FxHashMap) -> Result, String> { + let mut path = vec![]; + let mut current = goal_id; + while let Some(next) = map.get(¤t) { + path.push( + self.get(*next)? + .ok_or(format!("System ID {} not found", next))?, + ); + current = *next; + } + path.reverse(); + Ok(path) + } + fn best_multiroute( &mut self, waypoints: &[System], @@ -1468,7 +1540,9 @@ impl Router { let mut refuels = state.refuels; let dist = dist(&nb.pos, &state.node.pos); let (fuel_cost, new_fuel) = { - if let Some(res) = ship.fuel_cost_for_jump(state.fuel, dist, state.node.get_mult()) { + if let Some(res) = + ship.fuel_cost_for_jump(state.fuel, dist, state.node.get_mult()) + { // can jump with current amount of fuel res } else if let Some(res) = @@ -1544,7 +1618,22 @@ impl Router { }) } - pub fn floyd_warshall(&self, _range: f32) { + pub fn floyd_warshall(&self, range: f32) -> Result, String> { + let mut dist: FxHashMap = FxHashMap::default(); + info!("nb..."); + let total = self.tree.size(); + for (n, node) in self.tree.iter().enumerate() { + if (n % 100_000) == 0 { + println!("{}/{}", n, total); + } + let key = (node.id as u64) << 32; + for nb in self.neighbours(node, range) { + let key = key | nb.id as u64; + dist.entry(key).or_insert(1); + } + let key = ((node.id as u64) << 32) | node.id as u64; + dist.insert(key, 0); + } todo!() } @@ -1553,86 +1642,81 @@ impl Router { h = (dist(node,goal)-(range*node.mult)).max(0.0) // remaining distance after jumping from here */ let src = self.tree.nearest_neighbor(&[0.0, 0.0, 0.0]).unwrap(); + // let mut route_log = BufWriter::new(File::create("route_log_ib.txt").map_err(|e| e.to_string())?); let goal = self .tree - // .nearest_neighbor(&[-1111.5625, -134.21875, 65269.75]) // Beagle Point - .nearest_neighbor(&[-9530.5, -910.28125, 19808.125]) // Colonia + .nearest_neighbor(&[-1111.5625, -134.21875, 65269.75]) // Beagle Point + // .nearest_neighbor(&[-9530.5, -910.28125, 19808.125]) // Colonia .unwrap(); let mut best_node = FxHashMap::default(); - let mut prev = FxHashMap::default(); - let mut wait_list: FxHashMap> = FxHashMap::default(); - let mut in_wait_list: FxHashSet = FxHashSet::default(); + // let mut prev = FxHashMap::default(); + let mut queue = MinFHeap::new(); + let t_start = Instant::now(); + let mut n = 0usize; + let mut skipped = 0usize; + let mut global_best = u32::MAX; + queue.push(heuristic(range, src, goal), (0, src)); loop { - let t_start = Instant::now(); - let mut n = 0usize; - let mut skipped = 0usize; - let mut depth = 0usize; - let mut queue = VecDeque::new(); - queue.push_back(*src); - 'outer: loop { - // println!("D: {} | Q: {}", depth, queue.len()); - let mut queue_next = VecDeque::new(); - if queue.is_empty() { - warn!( - "Depth: {} | Visited: {} | Skipped: {} | search space exhausted after {}", - depth, - n, - skipped, - humantime::format_duration(t_start.elapsed()) - ); - break; + println!("Q: {}", queue.len()); + if queue.is_empty() { + warn!( + "Visited: {} | Skipped: {} | search space exhausted after {}", + n, + skipped, + humantime::format_duration(t_start.elapsed()) + ); + break; + } + while let Some((_, (depth, node))) = queue.pop() { + let best_len = best_node.len(); + let best_depth = best_node.entry(node.id).or_insert(depth); + if *best_depth > global_best { + skipped += 1; + continue; } - while let Some(node) = queue.pop_front() { - let best_len = best_node.len(); - let best_depth = best_node.entry(node.id).or_insert(depth); - if depth > *best_depth { - skipped += 1; - continue; - } - if depth < *best_depth { - *best_depth = depth; - } - n += 1; - if node.id == goal.id { + // writeln!(route_log,"{}, {}",node.id,depth).map_err(|e| e.to_string())?; + // route_log.flush().map_err(|e| e.to_string())?; + if depth < *best_depth { + *best_depth = depth; + } + n += 1; + if node.id == goal.id { + if depth < global_best { + global_best = global_best.min(depth); + queue.retain(|(_, (d, _))| *d <= global_best); info!( - "Depth: {}, Skipped: {}, Seen: {} (Total: {}) | Best: {} | elapsed: {}", - depth, + "Queued: {}, Skipped: {}, Seen: {} (Total: {}) | Best: {} | elapsed: {}", + queue.len(), skipped, n, best_len, - best_depth, + global_best, humantime::format_duration(t_start.elapsed()).to_string() ); - for layer_n in wait_list.keys().sorted() { - println!("WL({}): {}", layer_n, wait_list[layer_n].len()); - } - todo!(); - break 'outer; } - let valid_nbs = self - .neighbours(&node, node.get_mult() * range) - .filter(|nb| (self.valid(nb.id) || (nb.id == goal.id))) - .filter(|nb| match best_node.get(&nb.id) { - Some(&d) => (depth + 1) <= d, - None => true, - }) - .map(|nb| { - prev.insert(nb.id, node); - (F32(heuristic(range, nb, goal)), *nb) - }); - queue_next.extend(valid_nbs); + continue; + } else if n % 10000 == 0 { + info!( + "Queued: {}, Skipped: {}, Seen: {} (Total: {}) | Best: {} | elapsed: {}", + queue.len(), + skipped, + n, + best_len, + global_best, + humantime::format_duration(t_start.elapsed()).to_string() + ); } - queue_next.make_contiguous().sort(); - if let Some((_, nb)) = queue_next.pop_front() { - queue.push_back(nb); - } - let layer = wait_list.entry(depth).or_default(); - while let Some((F32(v), nb)) = queue_next.pop_front() { - if in_wait_list.insert(nb.id) { - layer.push(v, nb); - }; - } - depth += 1; + self.neighbours(node, node.get_mult() * range) + .filter(|nb| (self.valid(nb.id) || (nb.id == goal.id))) + .filter(|nb| match best_node.get(&nb.id) { + Some(&d) => depth < d, + None => true, + }) + .map(|nb| (heuristic(range, nb, goal), nb)) + .for_each(|(h, nb)| { + // prev.insert(nb.id, node.id); + queue.push(h, (depth + 1, nb)); + }); } } todo!() @@ -1705,7 +1789,7 @@ impl Router { let tx = tx_r.clone(); let rx = rx_q.clone(); thread::spawn(move || { - while let Ok(nodes) = rx.recv() { + rx.into_iter().for_each(|nodes| { let mut ret = vec![]; for node in nodes { let res: Vec = @@ -1713,9 +1797,8 @@ impl Router { ret.push((node, res)); } tx.send(ret).unwrap(); - } + }); drop(tx); - drop(rx); }) }) .collect(); @@ -1784,49 +1867,31 @@ impl Router { #[cfg_attr(feature = "profiling", tracing::instrument)] pub fn precompute_all(&mut self, range: f32) -> Result<(), String> { + use flate2::write::GzEncoder; let fh_nb = File::create(format!(r#"O:\nb_{}.dat"#, range)).unwrap(); - let mut buf_writer = BufWriter::new(fh_nb); + let mut fh_encoder = BufWriter::new(fh_nb); let mut pos: u64 = 0; + let mut n = 0; let total = self.tree.size(); - let (tx, rx, threads) = self.neighbor_workers(num_cpus::get(), range); - let mut n: usize = 0; + // let (tx, rx, threads) = self.neighbor_workers(num_cpus::get(), range); let mut map: FxHashMap = FxHashMap::default(); - info!("Precomputing neighbor map"); - info!("Sumbitting jobs"); - self.tree - .iter() - .chunks(10_000) - .into_iter() - .for_each(|chunk| { - tx.send(chunk.cloned().collect()).unwrap(); - }); - drop(tx); - info!("Processing..."); - rx.into_iter() - .flatten() - .enumerate() - .for_each(|(n, (node, mut neighbors))| { - let neighbors: Vec = neighbors.drain(..).map(|n| n.id).collect(); - // map.insert(node.id, pos); - pos += buf_writer - .write(&bincode::serialize(&neighbors).unwrap()) - .unwrap() as u64; - if (n % 100000) == 0 { - let prc = ((n as f64) / (total as f64)) * 100f64; - info!("{}/{} ({:.2}%) done, {} bytes", n, total, prc, pos); - } - }); + info!("Precomputing neighbor map..."); + self.tree.iter().for_each(|node| { + let nb = self.neighbours(node, range).map(|nb| nb.id).collect_vec(); + map.insert(node.id, pos); + pos += fh_encoder.write(&bincode::serialize(&nb).unwrap()).unwrap() as u64; + if (n % 10000) == 0 { + let prc = ((n as f64) / (total as f64)) * 100f64; + info!("{}/{} ({:.2}%) done, {} bytes", n, total, prc, pos); + } + n += 1; + }); let mut fh_idx = BufWriter::new(File::create(format!(r#"O:\nb_{}.idx"#, range)).unwrap()); info!("Writing index map"); info!( "Wrote {} bytes", fh_idx.write(&bincode::serialize(&map).unwrap()).unwrap() ); - info!("Joining threads"); - for t in threads { - t.join().unwrap(); - } - info!("Done!"); Ok(()) } @@ -2476,13 +2541,15 @@ impl Router { let next_depth = depth + 1; match node { BiDirNode::Forward(node) => { - let nbs = self.neighbours(&node, node.get_mult() * range).filter_map(|nb| { - if !seen_fwd.insert(nb.id) { - return None; - } - prev.insert(nb.id, node.id); - Some((next_depth, BiDirNode::Forward(*nb))) - }); + let nbs = + self.neighbours(&node, node.get_mult() * range) + .filter_map(|nb| { + if !seen_fwd.insert(nb.id) { + return None; + } + prev.insert(nb.id, node.id); + Some((next_depth, BiDirNode::Forward(*nb))) + }); queue.extend(nbs); } BiDirNode::Backwards(node) => { diff --git a/rust/src/ship.rs b/rust/src/ship.rs index 17553f2..7e89191 100644 --- a/rust/src/ship.rs +++ b/rust/src/ship.rs @@ -229,7 +229,7 @@ impl Ship { } impl FSD { - pub fn to_object(&self, py: Python) -> PyResult { + pub fn to_object(&self, py: Python<'_>) -> PyResult { let elem = PyDict::new(py); elem.set_item("rating_val", self.rating_val)?; elem.set_item("class_val", self.class_val)?; @@ -242,7 +242,7 @@ impl FSD { } impl Ship { - pub fn to_object(&self, py: Python) -> PyResult { + pub fn to_object(&self, py: Python<'_>) -> PyResult { let elem = PyDict::new(py); elem.set_item("base_mass", self.base_mass)?; elem.set_item("fuel_mass", self.fuel_mass)?; diff --git a/setup.py b/setup.py index bf616b1..82227e7 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from setuptools import find_packages, setup +from setuptools import find_packages, find_namespace_packages, setup from setuptools_rust import Binding, RustExtension, Strip import os @@ -68,7 +68,7 @@ setup( description="Elite: Dangerous long range route plotter", long_description=long_description, long_description_content_type="text/markdown", - url="https://gitlab.com/Earthnuker/ed_lrr/-/tree/pyqt_gui", + url="https://gitdab.com/Earthnuker/ED_LRR/src/branch/pyqt_gui", rust_extensions=[ RustExtension( "_ed_lrr", @@ -82,7 +82,7 @@ setup( quiet=True, ) ], - packages=find_packages(), + packages=find_namespace_packages(), entry_points={ "console_scripts": ["ed_lrr = ed_lrr_gui.__main__:main"], "gui_scripts": ["ed_lrr_gui = ed_lrr_gui.__main__:gui_main"],