forked from StudioInfinity/dyna3
Compare commits
8 commits
main
...
curvature-
Author | SHA1 | Date | |
---|---|---|---|
![]() |
47cc559cd6 | ||
![]() |
b117c00992 | ||
![]() |
ca9de34427 | ||
![]() |
25f446499b | ||
![]() |
f1f87e97be | ||
![]() |
677d770738 | ||
![]() |
c6e6e7be9f | ||
![]() |
d243f19e25 |
7 changed files with 1371 additions and 305 deletions
788
app-proto/Cargo.lock
generated
Normal file
788
app-proto/Cargo.lock
generated
Normal file
|
@ -0,0 +1,788 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.8.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "allocator-api2"
|
||||||
|
version = "0.2.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "approx"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.18.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.1.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476"
|
||||||
|
dependencies = [
|
||||||
|
"shlex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "console_error_panic_hook"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dyna3"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"console_error_panic_hook",
|
||||||
|
"dyna3",
|
||||||
|
"itertools",
|
||||||
|
"js-sys",
|
||||||
|
"lazy_static",
|
||||||
|
"nalgebra",
|
||||||
|
"readonly",
|
||||||
|
"rustc-hash",
|
||||||
|
"slab",
|
||||||
|
"sycamore",
|
||||||
|
"wasm-bindgen-test",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "equivalent"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.14.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"allocator-api2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "html-escape"
|
||||||
|
version = "0.2.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476"
|
||||||
|
dependencies = [
|
||||||
|
"utf8-width",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
|
||||||
|
dependencies = [
|
||||||
|
"equivalent",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.70"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
|
||||||
|
dependencies = [
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.158"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matrixmultiply"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"rawpointer",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "minicov"
|
||||||
|
version = "0.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c71e683cd655513b99affab7d317deb690528255a0d5f717f1024093c12b169"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nalgebra"
|
||||||
|
version = "0.33.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c4b5f057b303842cf3262c27e465f4c303572e7f6b0648f60e16248ac3397f4"
|
||||||
|
dependencies = [
|
||||||
|
"approx",
|
||||||
|
"matrixmultiply",
|
||||||
|
"nalgebra-macros",
|
||||||
|
"num-complex",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
"simba",
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nalgebra-macros"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||||
|
dependencies = [
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.46"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-rational"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
||||||
|
dependencies = [
|
||||||
|
"num-bigint",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "paste"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.86"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rawpointer"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "readonly"
|
||||||
|
version = "0.2.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f2a62d85ed81ca5305dc544bd42c8804c5060b78ffa5ad3c64b0fb6a8c13d062"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-hash"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "safe_arch"
|
||||||
|
version = "0.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3460605018fdc9612bce72735cba0d27efbcd9904780d44c7e3a9948f96148a"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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 = "scoped-tls"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simba"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa"
|
||||||
|
dependencies = [
|
||||||
|
"approx",
|
||||||
|
"num-complex",
|
||||||
|
"num-traits",
|
||||||
|
"paste",
|
||||||
|
"wide",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slab"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slotmap"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a"
|
||||||
|
dependencies = [
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sycamore"
|
||||||
|
version = "0.9.0-beta.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dedaf7237c05913604a5b0b2536b613f6c8510c6b213d2583b1294869755cabd"
|
||||||
|
dependencies = [
|
||||||
|
"hashbrown",
|
||||||
|
"indexmap",
|
||||||
|
"paste",
|
||||||
|
"sycamore-core",
|
||||||
|
"sycamore-macro",
|
||||||
|
"sycamore-reactive",
|
||||||
|
"sycamore-web",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sycamore-core"
|
||||||
|
version = "0.9.0-beta.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5ddddc3d1bcb38c04ad55d2d1ab4f6a358e4daaeae0a0436892f1fade9fb31a"
|
||||||
|
dependencies = [
|
||||||
|
"hashbrown",
|
||||||
|
"paste",
|
||||||
|
"sycamore-reactive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sycamore-macro"
|
||||||
|
version = "0.9.0-beta.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77181c27cb753e86065308901871ccc7456fb19527b6a4ffacad3b63175ed014"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rand",
|
||||||
|
"sycamore-view-parser",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sycamore-reactive"
|
||||||
|
version = "0.9.0-beta.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7aa6870203507c07e850687c0ccf528eb0f04240e3596bac9137007ffb6c50b1"
|
||||||
|
dependencies = [
|
||||||
|
"paste",
|
||||||
|
"slotmap",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sycamore-view-parser"
|
||||||
|
version = "0.9.0-beta.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a6144640af2eafffc68a92f3aacbbfaa21f7fd31906e2336fe304fd100fe226b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sycamore-web"
|
||||||
|
version = "0.9.0-beta.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bca93dcf1b1830bf1aac93508ed51babcda92c1d32d96067ab416d94e4b7c475"
|
||||||
|
dependencies = [
|
||||||
|
"html-escape",
|
||||||
|
"js-sys",
|
||||||
|
"once_cell",
|
||||||
|
"paste",
|
||||||
|
"smallvec",
|
||||||
|
"sycamore-core",
|
||||||
|
"sycamore-macro",
|
||||||
|
"sycamore-reactive",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.77"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8-width"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "walkdir"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||||
|
dependencies = [
|
||||||
|
"same-file",
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.93"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-backend"
|
||||||
|
version = "0.2.93"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-futures"
|
||||||
|
version = "0.4.43"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.93"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.93"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-backend",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.93"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-test"
|
||||||
|
version = "0.3.43"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68497a05fb21143a08a7d24fc81763384a3072ee43c44e86aad1744d6adef9d9"
|
||||||
|
dependencies = [
|
||||||
|
"console_error_panic_hook",
|
||||||
|
"js-sys",
|
||||||
|
"minicov",
|
||||||
|
"scoped-tls",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"wasm-bindgen-futures",
|
||||||
|
"wasm-bindgen-test-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-test-macro"
|
||||||
|
version = "0.3.43"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b8220be1fa9e4c889b30fd207d4906657e7e90b12e0e6b0c8b8d8709f5de021"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "web-sys"
|
||||||
|
version = "0.3.70"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wide"
|
||||||
|
version = "0.7.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b828f995bf1e9622031f8009f8481a85406ce1f4d4588ff746d872043e855690"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"safe_arch",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.59.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_gnullvm",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.7.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.7.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
|
@ -1,26 +1,19 @@
|
||||||
use nalgebra::DMatrix;
|
use dyna3::engine::{Q, point, realize_gram, sphere, ConstraintProblem};
|
||||||
|
|
||||||
use dyna3::engine::{Q, point, realize_gram, sphere, PartialMatrix};
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let gram = {
|
let mut problem = ConstraintProblem::from_guess(&[
|
||||||
let mut gram_to_be = PartialMatrix::new();
|
|
||||||
for j in 0..2 {
|
|
||||||
for k in j..2 {
|
|
||||||
gram_to_be.push_sym(j, k, if (j, k) == (1, 1) { 1.0 } else { 0.0 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gram_to_be
|
|
||||||
};
|
|
||||||
let guess = DMatrix::from_columns(&[
|
|
||||||
point(0.0, 0.0, 2.0),
|
point(0.0, 0.0, 2.0),
|
||||||
sphere(0.0, 0.0, 0.0, 1.0)
|
sphere(0.0, 0.0, 0.0, 1.0)
|
||||||
]);
|
]);
|
||||||
let frozen = [(3, 0)];
|
for j in 0..2 {
|
||||||
|
for k in j..2 {
|
||||||
|
problem.gram.push_sym(j, k, if (j, k) == (1, 1) { 1.0 } else { 0.0 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
problem.frozen.push(3, 0, problem.guess[(3, 0)]);
|
||||||
println!();
|
println!();
|
||||||
let (config, _, success, history) = realize_gram(
|
let (config, _, success, history) = realize_gram(
|
||||||
&gram, guess, &frozen,
|
&problem, 1.0e-12, 0.5, 0.9, 1.1, 200, 110
|
||||||
1.0e-12, 0.5, 0.9, 1.1, 200, 110
|
|
||||||
);
|
);
|
||||||
print!("\nCompleted Gram matrix:{}", config.tr_mul(&*Q) * &config);
|
print!("\nCompleted Gram matrix:{}", config.tr_mul(&*Q) * &config);
|
||||||
print!("Configuration:{}", config);
|
print!("Configuration:{}", config);
|
||||||
|
|
|
@ -1,29 +1,22 @@
|
||||||
use nalgebra::DMatrix;
|
use dyna3::engine::{Q, realize_gram, sphere, ConstraintProblem};
|
||||||
|
|
||||||
use dyna3::engine::{Q, realize_gram, sphere, PartialMatrix};
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let gram = {
|
let mut problem = ConstraintProblem::from_guess({
|
||||||
let mut gram_to_be = PartialMatrix::new();
|
|
||||||
for j in 0..3 {
|
|
||||||
for k in j..3 {
|
|
||||||
gram_to_be.push_sym(j, k, if j == k { 1.0 } else { -1.0 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gram_to_be
|
|
||||||
};
|
|
||||||
let guess = {
|
|
||||||
let a: f64 = 0.75_f64.sqrt();
|
let a: f64 = 0.75_f64.sqrt();
|
||||||
DMatrix::from_columns(&[
|
&[
|
||||||
sphere(1.0, 0.0, 0.0, 1.0),
|
sphere(1.0, 0.0, 0.0, 1.0),
|
||||||
sphere(-0.5, a, 0.0, 1.0),
|
sphere(-0.5, a, 0.0, 1.0),
|
||||||
sphere(-0.5, -a, 0.0, 1.0)
|
sphere(-0.5, -a, 0.0, 1.0)
|
||||||
])
|
]
|
||||||
};
|
});
|
||||||
|
for j in 0..3 {
|
||||||
|
for k in j..3 {
|
||||||
|
problem.gram.push_sym(j, k, if j == k { 1.0 } else { -1.0 });
|
||||||
|
}
|
||||||
|
}
|
||||||
println!();
|
println!();
|
||||||
let (config, _, success, history) = realize_gram(
|
let (config, _, success, history) = realize_gram(
|
||||||
&gram, guess, &[],
|
&problem, 1.0e-12, 0.5, 0.9, 1.1, 200, 110
|
||||||
1.0e-12, 0.5, 0.9, 1.1, 200, 110
|
|
||||||
);
|
);
|
||||||
print!("\nCompleted Gram matrix:{}", config.tr_mul(&*Q) * &config);
|
print!("\nCompleted Gram matrix:{}", config.tr_mul(&*Q) * &config);
|
||||||
if success {
|
if success {
|
||||||
|
|
|
@ -166,18 +166,7 @@ pub fn AddRemove() -> View {
|
||||||
button(
|
button(
|
||||||
on:click=|_| {
|
on:click=|_| {
|
||||||
let state = use_context::<AppState>();
|
let state = use_context::<AppState>();
|
||||||
state.assembly.insert_new_element();
|
state.assembly.insert_new_sphere();
|
||||||
|
|
||||||
/* DEBUG */
|
|
||||||
// print updated list of elements by identifier
|
|
||||||
console::log_1(&JsValue::from("elements by identifier:"));
|
|
||||||
for (id, key) in state.assembly.elements_by_id.get_clone().iter() {
|
|
||||||
console::log_3(
|
|
||||||
&JsValue::from(" "),
|
|
||||||
&JsValue::from(id),
|
|
||||||
&JsValue::from(*key)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
) { "+" }
|
) { "+" }
|
||||||
button(
|
button(
|
||||||
|
@ -188,13 +177,18 @@ pub fn AddRemove() -> View {
|
||||||
},
|
},
|
||||||
on:click=|_| {
|
on:click=|_| {
|
||||||
let state = use_context::<AppState>();
|
let state = use_context::<AppState>();
|
||||||
let subjects = state.selection.with(
|
let subjects: [_; 2] = state.selection.with(
|
||||||
|sel| {
|
// the button is only enabled when two elements are
|
||||||
let subject_vec: Vec<_> = sel.into_iter().collect();
|
// selected, so we know the cast to a two-element array
|
||||||
(subject_vec[0].clone(), subject_vec[1].clone())
|
// will succeed
|
||||||
}
|
|sel| sel
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.try_into()
|
||||||
|
.unwrap()
|
||||||
);
|
);
|
||||||
state.assembly.insert_new_regulator(subjects);
|
state.assembly.insert_new_product_regulator(subjects);
|
||||||
state.selection.update(|sel| sel.clear());
|
state.selection.update(|sel| sel.clear());
|
||||||
}
|
}
|
||||||
) { "🔗" }
|
) { "🔗" }
|
||||||
|
|
|
@ -1,12 +1,20 @@
|
||||||
use nalgebra::{DMatrix, DVector, DVectorView, Vector3};
|
use nalgebra::{DMatrix, DVector, DVectorView, Vector3};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use slab::Slab;
|
use slab::Slab;
|
||||||
use std::{collections::BTreeSet, sync::atomic::{AtomicU64, Ordering}};
|
use std::{collections::BTreeSet, rc::Rc, sync::atomic::{AtomicU64, Ordering}};
|
||||||
use sycamore::prelude::*;
|
use sycamore::prelude::*;
|
||||||
use web_sys::{console, wasm_bindgen::JsValue}; /* DEBUG */
|
use web_sys::{console, wasm_bindgen::JsValue}; /* DEBUG */
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
engine::{Q, local_unif_to_std, realize_gram, ConfigSubspace, PartialMatrix},
|
engine::{
|
||||||
|
Q,
|
||||||
|
local_unif_to_std,
|
||||||
|
realize_gram,
|
||||||
|
sphere,
|
||||||
|
ConfigSubspace,
|
||||||
|
ConstraintProblem
|
||||||
|
},
|
||||||
|
outline::OutlineItem,
|
||||||
specified::SpecifiedValue
|
specified::SpecifiedValue
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,8 +38,8 @@ pub struct Element {
|
||||||
pub color: ElementColor,
|
pub color: ElementColor,
|
||||||
pub representation: Signal<DVector<f64>>,
|
pub representation: Signal<DVector<f64>>,
|
||||||
|
|
||||||
// All regulators with this element as a subject. The assembly owning
|
// the regulators this element is subject to. the assembly that owns the
|
||||||
// this element is responsible for keeping this set up to date.
|
// element is responsible for keeping this set up to date
|
||||||
pub regulators: Signal<BTreeSet<RegulatorKey>>,
|
pub regulators: Signal<BTreeSet<RegulatorKey>>,
|
||||||
|
|
||||||
// a serial number, assigned by `Element::new`, that uniquely identifies
|
// a serial number, assigned by `Element::new`, that uniquely identifies
|
||||||
|
@ -115,15 +123,95 @@ impl Element {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_to_problem(&self, problem: &mut ConstraintProblem) {
|
||||||
|
if let Some(index) = self.column_index {
|
||||||
|
problem.gram.push_sym(index, index, 1.0);
|
||||||
|
problem.guess.set_column(index, &self.representation.get_clone_untracked());
|
||||||
|
} else {
|
||||||
|
panic!("Tried to write problem data from an unindexed element: \"{}\"", self.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
pub trait Regulator: OutlineItem {
|
||||||
pub struct Regulator {
|
// get information
|
||||||
pub subjects: (ElementKey, ElementKey),
|
fn subjects(&self) -> Vec<ElementKey>;
|
||||||
|
fn measurement(&self) -> ReadSignal<f64>;
|
||||||
|
fn set_point(&self) -> Signal<SpecifiedValue>;
|
||||||
|
|
||||||
|
// write problem data
|
||||||
|
fn write_to_problem(&self, problem: &mut ConstraintProblem, elts: &Slab<Element>);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ProductRegulator {
|
||||||
|
pub subjects: [ElementKey; 2],
|
||||||
pub measurement: ReadSignal<f64>,
|
pub measurement: ReadSignal<f64>,
|
||||||
pub set_point: Signal<SpecifiedValue>
|
pub set_point: Signal<SpecifiedValue>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Regulator for ProductRegulator {
|
||||||
|
fn subjects(&self) -> Vec<ElementKey> {
|
||||||
|
self.subjects.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn measurement(&self) -> ReadSignal<f64> {
|
||||||
|
self.measurement
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_point(&self) -> Signal<SpecifiedValue> {
|
||||||
|
self.set_point
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_to_problem(&self, problem: &mut ConstraintProblem, elts: &Slab<Element>) {
|
||||||
|
self.set_point.with_untracked(|set_pt| {
|
||||||
|
if let Some(val) = set_pt.value {
|
||||||
|
let subject_column_indices = self.subjects.map(
|
||||||
|
|subj| elts[subj].column_index
|
||||||
|
);
|
||||||
|
if let [Some(row), Some(col)] = subject_column_indices {
|
||||||
|
problem.gram.push_sym(row, col, val);
|
||||||
|
} else {
|
||||||
|
panic!("Tried to write problem data from a regulator with an unindexed subject");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HalfCurvatureRegulator {
|
||||||
|
pub subject: ElementKey,
|
||||||
|
pub measurement: ReadSignal<f64>,
|
||||||
|
pub set_point: Signal<SpecifiedValue>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Regulator for HalfCurvatureRegulator {
|
||||||
|
fn subjects(&self) -> Vec<ElementKey> {
|
||||||
|
vec![self.subject]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn measurement(&self) -> ReadSignal<f64> {
|
||||||
|
self.measurement
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_point(&self) -> Signal<SpecifiedValue> {
|
||||||
|
self.set_point
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_to_problem(&self, problem: &mut ConstraintProblem, elts: &Slab<Element>) {
|
||||||
|
self.set_point.with_untracked(|set_pt| {
|
||||||
|
if let Some(val) = set_pt.value {
|
||||||
|
if let Some(col) = elts[self.subject].column_index {
|
||||||
|
const CURVATURE_COMPONENT: usize = 3;
|
||||||
|
problem.frozen.push(CURVATURE_COMPONENT, col, val);
|
||||||
|
} else {
|
||||||
|
panic!("Tried to write problem data from a regulator with an unindexed subject");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// the velocity is expressed in uniform coordinates
|
// the velocity is expressed in uniform coordinates
|
||||||
pub struct ElementMotion<'a> {
|
pub struct ElementMotion<'a> {
|
||||||
pub key: ElementKey,
|
pub key: ElementKey,
|
||||||
|
@ -137,7 +225,7 @@ type AssemblyMotion<'a> = Vec<ElementMotion<'a>>;
|
||||||
pub struct Assembly {
|
pub struct Assembly {
|
||||||
// elements and regulators
|
// elements and regulators
|
||||||
pub elements: Signal<Slab<Element>>,
|
pub elements: Signal<Slab<Element>>,
|
||||||
pub regulators: Signal<Slab<Regulator>>,
|
pub regulators: Signal<Slab<Rc<dyn Regulator>>>,
|
||||||
|
|
||||||
// solution variety tangent space. the basis vectors are stored in
|
// solution variety tangent space. the basis vectors are stored in
|
||||||
// configuration matrix format, ordered according to the elements' column
|
// configuration matrix format, ordered according to the elements' column
|
||||||
|
@ -170,23 +258,25 @@ impl Assembly {
|
||||||
// insert an element into the assembly without checking whether we already
|
// insert an element into the assembly without checking whether we already
|
||||||
// have an element with the same identifier. any element that does have the
|
// have an element with the same identifier. any element that does have the
|
||||||
// same identifier will get kicked out of the `elements_by_id` index
|
// same identifier will get kicked out of the `elements_by_id` index
|
||||||
fn insert_element_unchecked(&self, elt: Element) {
|
fn insert_element_unchecked(&self, elt: Element) -> ElementKey {
|
||||||
let id = elt.id.clone();
|
let id = elt.id.clone();
|
||||||
let key = self.elements.update(|elts| elts.insert(elt));
|
let key = self.elements.update(|elts| elts.insert(elt));
|
||||||
self.elements_by_id.update(|elts_by_id| elts_by_id.insert(id, key));
|
self.elements_by_id.update(|elts_by_id| elts_by_id.insert(id, key));
|
||||||
|
key
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_insert_element(&self, elt: Element) -> bool {
|
pub fn try_insert_element(&self, elt: Element) -> Option<ElementKey> {
|
||||||
let can_insert = self.elements_by_id.with_untracked(
|
let can_insert = self.elements_by_id.with_untracked(
|
||||||
|elts_by_id| !elts_by_id.contains_key(&elt.id)
|
|elts_by_id| !elts_by_id.contains_key(&elt.id)
|
||||||
);
|
);
|
||||||
if can_insert {
|
if can_insert {
|
||||||
self.insert_element_unchecked(elt);
|
Some(self.insert_element_unchecked(elt))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
can_insert
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_new_element(&self) {
|
pub fn insert_new_sphere(self) {
|
||||||
// find the next unused identifier in the default sequence
|
// find the next unused identifier in the default sequence
|
||||||
let mut id_num = 1;
|
let mut id_num = 1;
|
||||||
let mut id = format!("sphere{}", id_num);
|
let mut id = format!("sphere{}", id_num);
|
||||||
|
@ -197,67 +287,81 @@ impl Assembly {
|
||||||
id = format!("sphere{}", id_num);
|
id = format!("sphere{}", id_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create and insert a new element
|
// create and insert a sphere
|
||||||
self.insert_element_unchecked(
|
let key = self.insert_element_unchecked(
|
||||||
Element::new(
|
Element::new(
|
||||||
id,
|
id,
|
||||||
format!("Sphere {}", id_num),
|
format!("Sphere {}", id_num),
|
||||||
[0.75_f32, 0.75_f32, 0.75_f32],
|
[0.75_f32, 0.75_f32, 0.75_f32],
|
||||||
DVector::<f64>::from_column_slice(&[0.0, 0.0, 0.0, 0.5, -0.5])
|
sphere(0.0, 0.0, 0.0, 1.0)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// create and insert a curvature regulator
|
||||||
|
self.insert_new_half_curvature_regulator(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_regulator(&self, regulator: Regulator) {
|
fn insert_regulator(&self, regulator: Rc<dyn Regulator>) {
|
||||||
let subjects = regulator.subjects;
|
let subjects = regulator.subjects();
|
||||||
let key = self.regulators.update(|regs| regs.insert(regulator));
|
let key = self.regulators.update(
|
||||||
let subject_regulators = self.elements.with(
|
|regs| regs.insert(regulator)
|
||||||
|elts| (elts[subjects.0].regulators, elts[subjects.1].regulators)
|
|
||||||
);
|
);
|
||||||
subject_regulators.0.update(|regs| regs.insert(key));
|
let subject_regulators: Vec<_> = self.elements.with(
|
||||||
subject_regulators.1.update(|regs| regs.insert(key));
|
|elts| subjects.into_iter().map(
|
||||||
}
|
|subj| elts[subj].regulators
|
||||||
|
).collect()
|
||||||
pub fn insert_new_regulator(self, subjects: (ElementKey, ElementKey)) {
|
|
||||||
// create and insert a new regulator
|
|
||||||
let measurement = self.elements.map(
|
|
||||||
move |elts| {
|
|
||||||
let reps = (
|
|
||||||
elts[subjects.0].representation.get_clone(),
|
|
||||||
elts[subjects.1].representation.get_clone()
|
|
||||||
);
|
|
||||||
reps.0.dot(&(&*Q * reps.1))
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
let set_point = create_signal(SpecifiedValue::from_empty_spec());
|
for regulators in subject_regulators {
|
||||||
self.insert_regulator(Regulator {
|
regulators.update(|regs| regs.insert(key));
|
||||||
subjects: subjects,
|
}
|
||||||
measurement: measurement,
|
|
||||||
set_point: set_point
|
|
||||||
});
|
|
||||||
|
|
||||||
/* DEBUG */
|
/* DEBUG */
|
||||||
// print an updated list of regulators
|
// print an updated list of regulators
|
||||||
console::log_1(&JsValue::from("Regulators:"));
|
console::log_1(&JsValue::from("Regulators:"));
|
||||||
self.regulators.with(|regs| {
|
self.regulators.with(|regs| {
|
||||||
for (_, reg) in regs.into_iter() {
|
for (_, reg) in regs.into_iter() {
|
||||||
console::log_5(
|
console::log_1(&JsValue::from(format!(
|
||||||
&JsValue::from(" "),
|
" {:?}: {}",
|
||||||
&JsValue::from(reg.subjects.0),
|
reg.subjects(),
|
||||||
&JsValue::from(reg.subjects.1),
|
reg.set_point().with_untracked(
|
||||||
&JsValue::from(":"),
|
|set_pt| {
|
||||||
®.set_point.with_untracked(
|
let spec = &set_pt.spec;
|
||||||
|set_pt| JsValue::from(set_pt.spec.as_str())
|
if spec.is_empty() {
|
||||||
|
"__".to_string()
|
||||||
|
} else {
|
||||||
|
spec.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
);
|
)));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_new_product_regulator(self, subjects: [ElementKey; 2]) {
|
||||||
|
// create and insert a new product regulator
|
||||||
|
let measurement = self.elements.map(
|
||||||
|
move |elts| {
|
||||||
|
let representations = subjects.map(|subj| elts[subj].representation);
|
||||||
|
representations[0].with(|rep_0|
|
||||||
|
representations[1].with(|rep_1|
|
||||||
|
rep_0.dot(&(&*Q * rep_1))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
let set_point = create_signal(SpecifiedValue::from_empty_spec());
|
||||||
|
self.insert_regulator(Rc::new(ProductRegulator {
|
||||||
|
subjects: subjects,
|
||||||
|
measurement: measurement,
|
||||||
|
set_point: set_point
|
||||||
|
}));
|
||||||
|
|
||||||
// update the realization when the regulator becomes a constraint, or is
|
// update the realization when the regulator becomes a constraint, or is
|
||||||
// edited while acting as a constraint
|
// edited while acting as a constraint
|
||||||
create_effect(move || {
|
create_effect(move || {
|
||||||
console::log_1(&JsValue::from(
|
console::log_1(&JsValue::from(
|
||||||
format!("Updated constraint with subjects ({}, {})", subjects.0, subjects.1)
|
format!("Updated regulator with subjects {:?}", subjects)
|
||||||
));
|
));
|
||||||
if set_point.with(|set_pt| set_pt.is_present()) {
|
if set_point.with(|set_pt| set_pt.is_present()) {
|
||||||
self.realize();
|
self.realize();
|
||||||
|
@ -265,6 +369,64 @@ impl Assembly {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn insert_new_half_curvature_regulator(self, subject: ElementKey) {
|
||||||
|
// create and insert a new half-curvature regulator
|
||||||
|
let measurement = self.elements.map(
|
||||||
|
move |elts| elts[subject].representation.with(|rep| rep[3])
|
||||||
|
);
|
||||||
|
let set_point = create_signal(SpecifiedValue::from_empty_spec());
|
||||||
|
self.insert_regulator(Rc::new(HalfCurvatureRegulator {
|
||||||
|
subject: subject,
|
||||||
|
measurement: measurement,
|
||||||
|
set_point: set_point
|
||||||
|
}));
|
||||||
|
|
||||||
|
// update the realization when the regulator becomes a constraint, or is
|
||||||
|
// edited while acting as a constraint
|
||||||
|
create_effect(move || {
|
||||||
|
console::log_1(&JsValue::from(
|
||||||
|
format!("Updated regulator with subjects [{}]", subject)
|
||||||
|
));
|
||||||
|
if let Some(half_curv) = set_point.with(|set_pt| set_pt.value) {
|
||||||
|
let representation = self.elements.with(
|
||||||
|
|elts| elts[subject].representation
|
||||||
|
);
|
||||||
|
representation.update(|rep| {
|
||||||
|
// set the sphere's half-curvature to the desired value
|
||||||
|
rep[3] = half_curv;
|
||||||
|
|
||||||
|
// restore normalization by contracting toward the curvature
|
||||||
|
// axis
|
||||||
|
const SIZE_THRESHOLD: f64 = 1e-9;
|
||||||
|
let half_q_lt = -2.0 * half_curv * rep[4];
|
||||||
|
let half_q_lt_sq = half_q_lt * half_q_lt;
|
||||||
|
let mut spatial = rep.fixed_rows_mut::<3>(0);
|
||||||
|
let q_sp = spatial.norm_squared();
|
||||||
|
if q_sp < SIZE_THRESHOLD && half_q_lt_sq < SIZE_THRESHOLD {
|
||||||
|
spatial.copy_from_slice(
|
||||||
|
&[0.0, 0.0, (1.0 - 2.0 * half_q_lt).sqrt()]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let scaling = half_q_lt + (q_sp + half_q_lt_sq).sqrt();
|
||||||
|
spatial.scale_mut(1.0 / scaling);
|
||||||
|
rep[4] /= scaling;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DEBUG */
|
||||||
|
// verify normalization
|
||||||
|
let rep_for_debug = rep.clone();
|
||||||
|
console::log_1(&JsValue::from(
|
||||||
|
format!(
|
||||||
|
"Sphere self-product after curvature change: {}",
|
||||||
|
rep_for_debug.dot(&(&*Q * &rep_for_debug))
|
||||||
|
)
|
||||||
|
));
|
||||||
|
});
|
||||||
|
self.realize();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// --- realization ---
|
// --- realization ---
|
||||||
|
|
||||||
pub fn realize(&self) {
|
pub fn realize(&self) {
|
||||||
|
@ -275,55 +437,39 @@ impl Assembly {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// set up the Gram matrix and the initial configuration matrix
|
// set up the constraint problem
|
||||||
let (gram, guess) = self.elements.with_untracked(|elts| {
|
let problem = self.elements.with_untracked(|elts| {
|
||||||
// set up the off-diagonal part of the Gram matrix
|
let mut problem_to_be = ConstraintProblem::new(elts.len());
|
||||||
let mut gram_to_be = PartialMatrix::new();
|
for (_, elt) in elts {
|
||||||
|
elt.write_to_problem(&mut problem_to_be);
|
||||||
|
}
|
||||||
self.regulators.with_untracked(|regs| {
|
self.regulators.with_untracked(|regs| {
|
||||||
for (_, reg) in regs {
|
for (_, reg) in regs {
|
||||||
reg.set_point.with_untracked(|set_pt| {
|
reg.write_to_problem(&mut problem_to_be, elts);
|
||||||
if let Some(val) = set_pt.value {
|
|
||||||
let subjects = reg.subjects;
|
|
||||||
let row = elts[subjects.0].column_index.unwrap();
|
|
||||||
let col = elts[subjects.1].column_index.unwrap();
|
|
||||||
gram_to_be.push_sym(row, col, val);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
problem_to_be
|
||||||
// set up the initial configuration matrix and the diagonal of the
|
|
||||||
// Gram matrix
|
|
||||||
let mut guess_to_be = DMatrix::<f64>::zeros(5, elts.len());
|
|
||||||
for (_, elt) in elts {
|
|
||||||
let index = elt.column_index.unwrap();
|
|
||||||
gram_to_be.push_sym(index, index, 1.0);
|
|
||||||
guess_to_be.set_column(index, &elt.representation.get_clone_untracked());
|
|
||||||
}
|
|
||||||
|
|
||||||
(gram_to_be, guess_to_be)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/* DEBUG */
|
/* DEBUG */
|
||||||
// log the Gram matrix
|
// log the Gram matrix
|
||||||
console::log_1(&JsValue::from("Gram matrix:"));
|
console::log_1(&JsValue::from("Gram matrix:"));
|
||||||
gram.log_to_console();
|
problem.gram.log_to_console();
|
||||||
|
|
||||||
/* DEBUG */
|
/* DEBUG */
|
||||||
// log the initial configuration matrix
|
// log the initial configuration matrix
|
||||||
console::log_1(&JsValue::from("Old configuration:"));
|
console::log_1(&JsValue::from("Old configuration:"));
|
||||||
for j in 0..guess.nrows() {
|
for j in 0..problem.guess.nrows() {
|
||||||
let mut row_str = String::new();
|
let mut row_str = String::new();
|
||||||
for k in 0..guess.ncols() {
|
for k in 0..problem.guess.ncols() {
|
||||||
row_str.push_str(format!(" {:>8.3}", guess[(j, k)]).as_str());
|
row_str.push_str(format!(" {:>8.3}", problem.guess[(j, k)]).as_str());
|
||||||
}
|
}
|
||||||
console::log_1(&JsValue::from(row_str));
|
console::log_1(&JsValue::from(row_str));
|
||||||
}
|
}
|
||||||
|
|
||||||
// look for a configuration with the given Gram matrix
|
// look for a configuration with the given Gram matrix
|
||||||
let (config, tangent, success, history) = realize_gram(
|
let (config, tangent, success, history) = realize_gram(
|
||||||
&gram, guess, &[],
|
&problem, 1.0e-12, 0.5, 0.9, 1.1, 200, 110
|
||||||
1.0e-12, 0.5, 0.9, 1.1, 200, 110
|
|
||||||
);
|
);
|
||||||
|
|
||||||
/* DEBUG */
|
/* DEBUG */
|
||||||
|
@ -458,4 +604,48 @@ impl Assembly {
|
||||||
// sync
|
// sync
|
||||||
self.realize();
|
self.realize();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::engine;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "Tried to write problem data from an unindexed element: \"sphere\"")]
|
||||||
|
fn unindexed_element_test() {
|
||||||
|
let _ = create_root(|| {
|
||||||
|
Element::new(
|
||||||
|
"sphere".to_string(),
|
||||||
|
"Sphere".to_string(),
|
||||||
|
[1.0_f32, 1.0_f32, 1.0_f32],
|
||||||
|
engine::sphere(0.0, 0.0, 0.0, 1.0)
|
||||||
|
).write_to_problem(&mut ConstraintProblem::new(1));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "Tried to write problem data from a regulator with an unindexed subject")]
|
||||||
|
fn unindexed_subject_test() {
|
||||||
|
let _ = create_root(|| {
|
||||||
|
let mut elts = Slab::new();
|
||||||
|
let subjects = [0, 1].map(|k| {
|
||||||
|
elts.insert(
|
||||||
|
Element::new(
|
||||||
|
format!("sphere{k}"),
|
||||||
|
format!("Sphere {k}"),
|
||||||
|
[1.0_f32, 1.0_f32, 1.0_f32],
|
||||||
|
engine::sphere(0.0, 0.0, 0.0, 1.0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
});
|
||||||
|
elts[subjects[0]].column_index = Some(0);
|
||||||
|
ProductRegulator {
|
||||||
|
subjects: subjects,
|
||||||
|
measurement: create_memo(|| 0.0),
|
||||||
|
set_point: create_signal(SpecifiedValue::try_from("0.0".to_string()).unwrap())
|
||||||
|
}.write_to_problem(&mut ConstraintProblem::new(2), &elts);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -37,7 +37,7 @@ pub fn sphere_with_offset(dir_x: f64, dir_y: f64, dir_z: f64, off: f64, curv: f6
|
||||||
|
|
||||||
// --- partial matrices ---
|
// --- partial matrices ---
|
||||||
|
|
||||||
struct MatrixEntry {
|
pub struct MatrixEntry {
|
||||||
index: (usize, usize),
|
index: (usize, usize),
|
||||||
value: f64
|
value: f64
|
||||||
}
|
}
|
||||||
|
@ -49,42 +49,72 @@ impl PartialMatrix {
|
||||||
PartialMatrix(Vec::<MatrixEntry>::new())
|
PartialMatrix(Vec::<MatrixEntry>::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_sym(&mut self, row: usize, col: usize, value: f64) {
|
pub fn push(&mut self, row: usize, col: usize, value: f64) {
|
||||||
let PartialMatrix(entries) = self;
|
let PartialMatrix(entries) = self;
|
||||||
entries.push(MatrixEntry { index: (row, col), value: value });
|
entries.push(MatrixEntry { index: (row, col), value: value });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_sym(&mut self, row: usize, col: usize, value: f64) {
|
||||||
|
self.push(row, col, value);
|
||||||
if row != col {
|
if row != col {
|
||||||
entries.push(MatrixEntry { index: (col, row), value: value });
|
self.push(col, row, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DEBUG */
|
/* DEBUG */
|
||||||
pub fn log_to_console(&self) {
|
pub fn log_to_console(&self) {
|
||||||
let PartialMatrix(entries) = self;
|
for &MatrixEntry { index: (row, col), value } in self {
|
||||||
for ent in entries {
|
console::log_1(&JsValue::from(
|
||||||
let ent_str = format!(" {} {} {}", ent.index.0, ent.index.1, ent.value);
|
format!(" {} {} {}", row, col, value)
|
||||||
console::log_1(&JsValue::from(ent_str.as_str()));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn freeze(&self, a: &DMatrix<f64>) -> DMatrix<f64> {
|
||||||
|
let mut result = a.clone();
|
||||||
|
for &MatrixEntry { index, value } in self {
|
||||||
|
result[index] = value;
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
fn proj(&self, a: &DMatrix<f64>) -> DMatrix<f64> {
|
fn proj(&self, a: &DMatrix<f64>) -> DMatrix<f64> {
|
||||||
let mut result = DMatrix::<f64>::zeros(a.nrows(), a.ncols());
|
let mut result = DMatrix::<f64>::zeros(a.nrows(), a.ncols());
|
||||||
let PartialMatrix(entries) = self;
|
for &MatrixEntry { index, .. } in self {
|
||||||
for ent in entries {
|
result[index] = a[index];
|
||||||
result[ent.index] = a[ent.index];
|
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sub_proj(&self, rhs: &DMatrix<f64>) -> DMatrix<f64> {
|
fn sub_proj(&self, rhs: &DMatrix<f64>) -> DMatrix<f64> {
|
||||||
let mut result = DMatrix::<f64>::zeros(rhs.nrows(), rhs.ncols());
|
let mut result = DMatrix::<f64>::zeros(rhs.nrows(), rhs.ncols());
|
||||||
let PartialMatrix(entries) = self;
|
for &MatrixEntry { index, value } in self {
|
||||||
for ent in entries {
|
result[index] = value - rhs[index];
|
||||||
result[ent.index] = ent.value - rhs[ent.index];
|
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IntoIterator for PartialMatrix {
|
||||||
|
type Item = MatrixEntry;
|
||||||
|
type IntoIter = std::vec::IntoIter<Self::Item>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
let PartialMatrix(entries) = self;
|
||||||
|
entries.into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a PartialMatrix {
|
||||||
|
type Item = &'a MatrixEntry;
|
||||||
|
type IntoIter = std::slice::Iter<'a, MatrixEntry>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
let PartialMatrix(entries) = self;
|
||||||
|
entries.into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- configuration subspaces ---
|
// --- configuration subspaces ---
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -195,6 +225,34 @@ impl DescentHistory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- constraint problems ---
|
||||||
|
|
||||||
|
pub struct ConstraintProblem {
|
||||||
|
pub gram: PartialMatrix,
|
||||||
|
pub frozen: PartialMatrix,
|
||||||
|
pub guess: DMatrix<f64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConstraintProblem {
|
||||||
|
pub fn new(element_count: usize) -> ConstraintProblem {
|
||||||
|
const ELEMENT_DIM: usize = 5;
|
||||||
|
ConstraintProblem {
|
||||||
|
gram: PartialMatrix::new(),
|
||||||
|
frozen: PartialMatrix::new(),
|
||||||
|
guess: DMatrix::<f64>::zeros(ELEMENT_DIM, element_count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "dev")]
|
||||||
|
pub fn from_guess(guess_columns: &[DVector<f64>]) -> ConstraintProblem {
|
||||||
|
ConstraintProblem {
|
||||||
|
gram: PartialMatrix::new(),
|
||||||
|
frozen: PartialMatrix::new(),
|
||||||
|
guess: DMatrix::from_columns(guess_columns)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- gram matrix realization ---
|
// --- gram matrix realization ---
|
||||||
|
|
||||||
// the Lorentz form
|
// the Lorentz form
|
||||||
|
@ -286,12 +344,12 @@ fn seek_better_config(
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
// seek a matrix `config` for which `config' * Q * config` matches the partial
|
// seek a matrix `config` that matches the partial matrix `problem.frozen` and
|
||||||
// matrix `gram`. use gradient descent starting from `guess`
|
// has `config' * Q * config` matching the partial matrix `problem.gram`. start
|
||||||
|
// at `problem.guess`, set the frozen entries to their desired values, and then
|
||||||
|
// use a regularized Newton's method to seek the desired Gram matrix
|
||||||
pub fn realize_gram(
|
pub fn realize_gram(
|
||||||
gram: &PartialMatrix,
|
problem: &ConstraintProblem,
|
||||||
guess: DMatrix<f64>,
|
|
||||||
frozen: &[(usize, usize)],
|
|
||||||
scaled_tol: f64,
|
scaled_tol: f64,
|
||||||
min_efficiency: f64,
|
min_efficiency: f64,
|
||||||
backoff: f64,
|
backoff: f64,
|
||||||
|
@ -299,6 +357,11 @@ pub fn realize_gram(
|
||||||
max_descent_steps: i32,
|
max_descent_steps: i32,
|
||||||
max_backoff_steps: i32
|
max_backoff_steps: i32
|
||||||
) -> (DMatrix<f64>, ConfigSubspace, bool, DescentHistory) {
|
) -> (DMatrix<f64>, ConfigSubspace, bool, DescentHistory) {
|
||||||
|
// destructure the problem data
|
||||||
|
let ConstraintProblem {
|
||||||
|
gram, guess, frozen
|
||||||
|
} = problem;
|
||||||
|
|
||||||
// start the descent history
|
// start the descent history
|
||||||
let mut history = DescentHistory::new();
|
let mut history = DescentHistory::new();
|
||||||
|
|
||||||
|
@ -313,11 +376,11 @@ pub fn realize_gram(
|
||||||
|
|
||||||
// convert the frozen indices to stacked format
|
// convert the frozen indices to stacked format
|
||||||
let frozen_stacked: Vec<usize> = frozen.into_iter().map(
|
let frozen_stacked: Vec<usize> = frozen.into_iter().map(
|
||||||
|index| index.1*element_dim + index.0
|
|MatrixEntry { index: (row, col), .. }| col*element_dim + row
|
||||||
).collect();
|
).collect();
|
||||||
|
|
||||||
// use Newton's method with backtracking and gradient descent backup
|
// use a regularized Newton's method with backtracking
|
||||||
let mut state = SearchState::from_config(gram, guess);
|
let mut state = SearchState::from_config(gram, frozen.freeze(guess));
|
||||||
let mut hess = DMatrix::zeros(element_dim, assembly_dim);
|
let mut hess = DMatrix::zeros(element_dim, assembly_dim);
|
||||||
for _ in 0..max_descent_steps {
|
for _ in 0..max_descent_steps {
|
||||||
// find the negative gradient of the loss function
|
// find the negative gradient of the loss function
|
||||||
|
@ -415,7 +478,7 @@ pub fn realize_gram(
|
||||||
|
|
||||||
#[cfg(feature = "dev")]
|
#[cfg(feature = "dev")]
|
||||||
pub mod examples {
|
pub mod examples {
|
||||||
use std::{array, f64::consts::PI};
|
use std::f64::consts::PI;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -428,35 +491,7 @@ pub mod examples {
|
||||||
// https://www.nippon.com/en/japan-topics/c12801/
|
// https://www.nippon.com/en/japan-topics/c12801/
|
||||||
//
|
//
|
||||||
pub fn realize_irisawa_hexlet(scaled_tol: f64) -> (DMatrix<f64>, ConfigSubspace, bool, DescentHistory) {
|
pub fn realize_irisawa_hexlet(scaled_tol: f64) -> (DMatrix<f64>, ConfigSubspace, bool, DescentHistory) {
|
||||||
let gram = {
|
let mut problem = ConstraintProblem::from_guess(
|
||||||
let mut gram_to_be = PartialMatrix::new();
|
|
||||||
for s in 0..9 {
|
|
||||||
// each sphere is represented by a spacelike vector
|
|
||||||
gram_to_be.push_sym(s, s, 1.0);
|
|
||||||
|
|
||||||
// the circumscribing sphere is tangent to all of the other
|
|
||||||
// spheres, with matching orientation
|
|
||||||
if s > 0 {
|
|
||||||
gram_to_be.push_sym(0, s, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if s > 2 {
|
|
||||||
// each chain sphere is tangent to the "sun" and "moon"
|
|
||||||
// spheres, with opposing orientation
|
|
||||||
for n in 1..3 {
|
|
||||||
gram_to_be.push_sym(s, n, -1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// each chain sphere is tangent to the next chain sphere,
|
|
||||||
// with opposing orientation
|
|
||||||
let s_next = 3 + (s-2) % 6;
|
|
||||||
gram_to_be.push_sym(s, s_next, -1.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gram_to_be
|
|
||||||
};
|
|
||||||
|
|
||||||
let guess = DMatrix::from_columns(
|
|
||||||
[
|
[
|
||||||
sphere(0.0, 0.0, 0.0, 15.0),
|
sphere(0.0, 0.0, 0.0, 15.0),
|
||||||
sphere(0.0, 0.0, -9.0, 5.0),
|
sphere(0.0, 0.0, -9.0, 5.0),
|
||||||
|
@ -471,42 +506,45 @@ pub mod examples {
|
||||||
).collect::<Vec<_>>().as_slice()
|
).collect::<Vec<_>>().as_slice()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
for s in 0..9 {
|
||||||
|
// each sphere is represented by a spacelike vector
|
||||||
|
problem.gram.push_sym(s, s, 1.0);
|
||||||
|
|
||||||
|
// the circumscribing sphere is tangent to all of the other
|
||||||
|
// spheres, with matching orientation
|
||||||
|
if s > 0 {
|
||||||
|
problem.gram.push_sym(0, s, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if s > 2 {
|
||||||
|
// each chain sphere is tangent to the "sun" and "moon"
|
||||||
|
// spheres, with opposing orientation
|
||||||
|
for n in 1..3 {
|
||||||
|
problem.gram.push_sym(s, n, -1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// each chain sphere is tangent to the next chain sphere,
|
||||||
|
// with opposing orientation
|
||||||
|
let s_next = 3 + (s-2) % 6;
|
||||||
|
problem.gram.push_sym(s, s_next, -1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// the frozen entries fix the radii of the circumscribing sphere, the
|
// the frozen entries fix the radii of the circumscribing sphere, the
|
||||||
// "sun" and "moon" spheres, and one of the chain spheres
|
// "sun" and "moon" spheres, and one of the chain spheres
|
||||||
let frozen: [(usize, usize); 4] = array::from_fn(|k| (3, k));
|
for k in 0..4 {
|
||||||
|
problem.frozen.push(3, k, problem.guess[(3, k)]);
|
||||||
|
}
|
||||||
|
|
||||||
realize_gram(
|
realize_gram(&problem, scaled_tol, 0.5, 0.9, 1.1, 200, 110)
|
||||||
&gram, guess, &frozen,
|
|
||||||
scaled_tol, 0.5, 0.9, 1.1, 200, 110
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set up a kaleidocycle, made of points with fixed distances between them,
|
// set up a kaleidocycle, made of points with fixed distances between them,
|
||||||
// and find its tangent space
|
// and find its tangent space
|
||||||
pub fn realize_kaleidocycle(scaled_tol: f64) -> (DMatrix<f64>, ConfigSubspace, bool, DescentHistory) {
|
pub fn realize_kaleidocycle(scaled_tol: f64) -> (DMatrix<f64>, ConfigSubspace, bool, DescentHistory) {
|
||||||
const N_POINTS: usize = 12;
|
const N_HINGES: usize = 6;
|
||||||
let gram = {
|
let mut problem = ConstraintProblem::from_guess(
|
||||||
let mut gram_to_be = PartialMatrix::new();
|
(0..N_HINGES).step_by(2).flat_map(
|
||||||
for block in (0..N_POINTS).step_by(2) {
|
|
||||||
let block_next = (block + 2) % N_POINTS;
|
|
||||||
for j in 0..2 {
|
|
||||||
// diagonal and hinge edges
|
|
||||||
for k in j..2 {
|
|
||||||
gram_to_be.push_sym(block + j, block + k, if j == k { 0.0 } else { -0.5 });
|
|
||||||
}
|
|
||||||
|
|
||||||
// non-hinge edges
|
|
||||||
for k in 0..2 {
|
|
||||||
gram_to_be.push_sym(block + j, block_next + k, -0.625);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gram_to_be
|
|
||||||
};
|
|
||||||
|
|
||||||
let guess = {
|
|
||||||
const N_HINGES: usize = 6;
|
|
||||||
let guess_elts = (0..N_HINGES).step_by(2).flat_map(
|
|
||||||
|n| {
|
|n| {
|
||||||
let ang_hor = (n as f64) * PI/3.0;
|
let ang_hor = (n as f64) * PI/3.0;
|
||||||
let ang_vert = ((n + 1) as f64) * PI/3.0;
|
let ang_vert = ((n + 1) as f64) * PI/3.0;
|
||||||
|
@ -519,16 +557,30 @@ pub mod examples {
|
||||||
point(x_vert, y_vert, 0.5)
|
point(x_vert, y_vert, 0.5)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
).collect::<Vec<_>>();
|
).collect::<Vec<_>>().as_slice()
|
||||||
DMatrix::from_columns(&guess_elts)
|
);
|
||||||
};
|
|
||||||
|
|
||||||
let frozen: [_; N_POINTS] = array::from_fn(|k| (3, k));
|
const N_POINTS: usize = 2 * N_HINGES;
|
||||||
|
for block in (0..N_POINTS).step_by(2) {
|
||||||
|
let block_next = (block + 2) % N_POINTS;
|
||||||
|
for j in 0..2 {
|
||||||
|
// diagonal and hinge edges
|
||||||
|
for k in j..2 {
|
||||||
|
problem.gram.push_sym(block + j, block + k, if j == k { 0.0 } else { -0.5 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// non-hinge edges
|
||||||
|
for k in 0..2 {
|
||||||
|
problem.gram.push_sym(block + j, block_next + k, -0.625);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
realize_gram(
|
for k in 0..N_POINTS {
|
||||||
&gram, guess, &frozen,
|
problem.frozen.push(3, k, problem.guess[(3, k)])
|
||||||
scaled_tol, 0.5, 0.9, 1.1, 200, 110
|
}
|
||||||
)
|
|
||||||
|
realize_gram(&problem, scaled_tol, 0.5, 0.9, 1.1, 200, 110)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,6 +591,25 @@ mod tests {
|
||||||
|
|
||||||
use super::{*, examples::*};
|
use super::{*, examples::*};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn freeze_test() {
|
||||||
|
let frozen = PartialMatrix(vec![
|
||||||
|
MatrixEntry { index: (0, 0), value: 14.0 },
|
||||||
|
MatrixEntry { index: (0, 2), value: 28.0 },
|
||||||
|
MatrixEntry { index: (1, 1), value: 42.0 },
|
||||||
|
MatrixEntry { index: (1, 2), value: 49.0 }
|
||||||
|
]);
|
||||||
|
let config = DMatrix::<f64>::from_row_slice(2, 3, &[
|
||||||
|
1.0, 2.0, 3.0,
|
||||||
|
4.0, 5.0, 6.0
|
||||||
|
]);
|
||||||
|
let expected_result = DMatrix::<f64>::from_row_slice(2, 3, &[
|
||||||
|
14.0, 2.0, 28.0,
|
||||||
|
4.0, 42.0, 49.0
|
||||||
|
]);
|
||||||
|
assert_eq!(frozen.freeze(&config), expected_result);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn sub_proj_test() {
|
fn sub_proj_test() {
|
||||||
let target = PartialMatrix(vec![
|
let target = PartialMatrix(vec![
|
||||||
|
@ -560,18 +631,12 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn zero_loss_test() {
|
fn zero_loss_test() {
|
||||||
let gram = PartialMatrix({
|
let mut gram = PartialMatrix::new();
|
||||||
let mut entries = Vec::<MatrixEntry>::new();
|
for j in 0..3 {
|
||||||
for j in 0..3 {
|
for k in 0..3 {
|
||||||
for k in 0..3 {
|
gram.push(j, k, if j == k { 1.0 } else { -1.0 });
|
||||||
entries.push(MatrixEntry {
|
|
||||||
index: (j, k),
|
|
||||||
value: if j == k { 1.0 } else { -1.0 }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
entries
|
}
|
||||||
});
|
|
||||||
let config = {
|
let config = {
|
||||||
let a = 0.75_f64.sqrt();
|
let a = 0.75_f64.sqrt();
|
||||||
DMatrix::from_columns(&[
|
DMatrix::from_columns(&[
|
||||||
|
@ -584,37 +649,33 @@ mod tests {
|
||||||
assert!(state.loss.abs() < f64::EPSILON);
|
assert!(state.loss.abs() < f64::EPSILON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TO DO */
|
||||||
// at the frozen indices, the optimization steps should have exact zeros,
|
// at the frozen indices, the optimization steps should have exact zeros,
|
||||||
// and the realized configuration should match the initial guess
|
// and the realized configuration should have the desired values
|
||||||
#[test]
|
#[test]
|
||||||
fn frozen_entry_test() {
|
fn frozen_entry_test() {
|
||||||
let gram = {
|
let mut problem = ConstraintProblem::from_guess(&[
|
||||||
let mut gram_to_be = PartialMatrix::new();
|
|
||||||
for j in 0..2 {
|
|
||||||
for k in j..2 {
|
|
||||||
gram_to_be.push_sym(j, k, if (j, k) == (1, 1) { 1.0 } else { 0.0 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gram_to_be
|
|
||||||
};
|
|
||||||
let guess = DMatrix::from_columns(&[
|
|
||||||
point(0.0, 0.0, 2.0),
|
point(0.0, 0.0, 2.0),
|
||||||
sphere(0.0, 0.0, 0.0, 1.0)
|
sphere(0.0, 0.0, 0.0, 0.95)
|
||||||
]);
|
]);
|
||||||
let frozen = [(3, 0), (3, 1)];
|
for j in 0..2 {
|
||||||
println!();
|
for k in j..2 {
|
||||||
|
problem.gram.push_sym(j, k, if (j, k) == (1, 1) { 1.0 } else { 0.0 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
problem.frozen.push(3, 0, problem.guess[(3, 0)]);
|
||||||
|
problem.frozen.push(3, 1, 0.5);
|
||||||
let (config, _, success, history) = realize_gram(
|
let (config, _, success, history) = realize_gram(
|
||||||
&gram, guess.clone(), &frozen,
|
&problem, 1.0e-12, 0.5, 0.9, 1.1, 200, 110
|
||||||
1.0e-12, 0.5, 0.9, 1.1, 200, 110
|
|
||||||
);
|
);
|
||||||
assert_eq!(success, true);
|
assert_eq!(success, true);
|
||||||
for base_step in history.base_step.into_iter() {
|
for base_step in history.base_step.into_iter() {
|
||||||
for index in frozen {
|
for &MatrixEntry { index, .. } in &problem.frozen {
|
||||||
assert_eq!(base_step[index], 0.0);
|
assert_eq!(base_step[index], 0.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for index in frozen {
|
for MatrixEntry { index, value } in problem.frozen {
|
||||||
assert_eq!(config[index], guess[index]);
|
assert_eq!(config[index], value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -635,34 +696,32 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn tangent_test_three_spheres() {
|
fn tangent_test_three_spheres() {
|
||||||
const SCALED_TOL: f64 = 1.0e-12;
|
const SCALED_TOL: f64 = 1.0e-12;
|
||||||
let gram = {
|
const ELEMENT_DIM: usize = 5;
|
||||||
let mut gram_to_be = PartialMatrix::new();
|
let mut problem = ConstraintProblem::from_guess(&[
|
||||||
for j in 0..3 {
|
|
||||||
for k in j..3 {
|
|
||||||
gram_to_be.push_sym(j, k, if j == k { 1.0 } else { -1.0 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gram_to_be
|
|
||||||
};
|
|
||||||
let guess = DMatrix::from_columns(&[
|
|
||||||
sphere(0.0, 0.0, 0.0, -2.0),
|
sphere(0.0, 0.0, 0.0, -2.0),
|
||||||
sphere(0.0, 0.0, 1.0, 1.0),
|
sphere(0.0, 0.0, 1.0, 1.0),
|
||||||
sphere(0.0, 0.0, -1.0, 1.0)
|
sphere(0.0, 0.0, -1.0, 1.0)
|
||||||
]);
|
]);
|
||||||
let frozen: [_; 5] = std::array::from_fn(|k| (k, 0));
|
for j in 0..3 {
|
||||||
|
for k in j..3 {
|
||||||
|
problem.gram.push_sym(j, k, if j == k { 1.0 } else { -1.0 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for n in 0..ELEMENT_DIM {
|
||||||
|
problem.frozen.push(n, 0, problem.guess[(n, 0)]);
|
||||||
|
}
|
||||||
let (config, tangent, success, history) = realize_gram(
|
let (config, tangent, success, history) = realize_gram(
|
||||||
&gram, guess.clone(), &frozen,
|
&problem, SCALED_TOL, 0.5, 0.9, 1.1, 200, 110
|
||||||
SCALED_TOL, 0.5, 0.9, 1.1, 200, 110
|
|
||||||
);
|
);
|
||||||
assert_eq!(config, guess);
|
assert_eq!(config, problem.guess);
|
||||||
assert_eq!(success, true);
|
assert_eq!(success, true);
|
||||||
assert_eq!(history.scaled_loss.len(), 1);
|
assert_eq!(history.scaled_loss.len(), 1);
|
||||||
|
|
||||||
// list some motions that should form a basis for the tangent space of
|
// list some motions that should form a basis for the tangent space of
|
||||||
// the solution variety
|
// the solution variety
|
||||||
const UNIFORM_DIM: usize = 4;
|
const UNIFORM_DIM: usize = 4;
|
||||||
let element_dim = guess.nrows();
|
let element_dim = problem.guess.nrows();
|
||||||
let assembly_dim = guess.ncols();
|
let assembly_dim = problem.guess.ncols();
|
||||||
let tangent_motions_unif = vec![
|
let tangent_motions_unif = vec![
|
||||||
basis_matrix((0, 1), UNIFORM_DIM, assembly_dim),
|
basis_matrix((0, 1), UNIFORM_DIM, assembly_dim),
|
||||||
basis_matrix((1, 1), UNIFORM_DIM, assembly_dim),
|
basis_matrix((1, 1), UNIFORM_DIM, assembly_dim),
|
||||||
|
@ -805,22 +864,17 @@ mod tests {
|
||||||
fn proj_equivar_test() {
|
fn proj_equivar_test() {
|
||||||
// find a pair of spheres that meet at 120°
|
// find a pair of spheres that meet at 120°
|
||||||
const SCALED_TOL: f64 = 1.0e-12;
|
const SCALED_TOL: f64 = 1.0e-12;
|
||||||
let gram = {
|
let mut problem_orig = ConstraintProblem::from_guess(&[
|
||||||
let mut gram_to_be = PartialMatrix::new();
|
|
||||||
gram_to_be.push_sym(0, 0, 1.0);
|
|
||||||
gram_to_be.push_sym(1, 1, 1.0);
|
|
||||||
gram_to_be.push_sym(0, 1, 0.5);
|
|
||||||
gram_to_be
|
|
||||||
};
|
|
||||||
let guess_orig = DMatrix::from_columns(&[
|
|
||||||
sphere(0.0, 0.0, 0.5, 1.0),
|
sphere(0.0, 0.0, 0.5, 1.0),
|
||||||
sphere(0.0, 0.0, -0.5, 1.0)
|
sphere(0.0, 0.0, -0.5, 1.0)
|
||||||
]);
|
]);
|
||||||
|
problem_orig.gram.push_sym(0, 0, 1.0);
|
||||||
|
problem_orig.gram.push_sym(1, 1, 1.0);
|
||||||
|
problem_orig.gram.push_sym(0, 1, 0.5);
|
||||||
let (config_orig, tangent_orig, success_orig, history_orig) = realize_gram(
|
let (config_orig, tangent_orig, success_orig, history_orig) = realize_gram(
|
||||||
&gram, guess_orig.clone(), &[],
|
&problem_orig, SCALED_TOL, 0.5, 0.9, 1.1, 200, 110
|
||||||
SCALED_TOL, 0.5, 0.9, 1.1, 200, 110
|
|
||||||
);
|
);
|
||||||
assert_eq!(config_orig, guess_orig);
|
assert_eq!(config_orig, problem_orig.guess);
|
||||||
assert_eq!(success_orig, true);
|
assert_eq!(success_orig, true);
|
||||||
assert_eq!(history_orig.scaled_loss.len(), 1);
|
assert_eq!(history_orig.scaled_loss.len(), 1);
|
||||||
|
|
||||||
|
@ -833,11 +887,15 @@ mod tests {
|
||||||
sphere(-a, 0.0, 7.0 - a, 1.0)
|
sphere(-a, 0.0, 7.0 - a, 1.0)
|
||||||
])
|
])
|
||||||
};
|
};
|
||||||
|
let problem_tfm = ConstraintProblem {
|
||||||
|
gram: problem_orig.gram,
|
||||||
|
guess: guess_tfm,
|
||||||
|
frozen: problem_orig.frozen
|
||||||
|
};
|
||||||
let (config_tfm, tangent_tfm, success_tfm, history_tfm) = realize_gram(
|
let (config_tfm, tangent_tfm, success_tfm, history_tfm) = realize_gram(
|
||||||
&gram, guess_tfm.clone(), &[],
|
&problem_tfm, SCALED_TOL, 0.5, 0.9, 1.1, 200, 110
|
||||||
SCALED_TOL, 0.5, 0.9, 1.1, 200, 110
|
|
||||||
);
|
);
|
||||||
assert_eq!(config_tfm, guess_tfm);
|
assert_eq!(config_tfm, problem_tfm.guess);
|
||||||
assert_eq!(success_tfm, true);
|
assert_eq!(success_tfm, true);
|
||||||
assert_eq!(history_tfm.scaled_loss.len(), 1);
|
assert_eq!(history_tfm.scaled_loss.len(), 1);
|
||||||
|
|
||||||
|
@ -869,7 +927,7 @@ mod tests {
|
||||||
// the comparison tolerance because the transformation seems to
|
// the comparison tolerance because the transformation seems to
|
||||||
// introduce some numerical error
|
// introduce some numerical error
|
||||||
const SCALED_TOL_TFM: f64 = 1.0e-9;
|
const SCALED_TOL_TFM: f64 = 1.0e-9;
|
||||||
let tol_sq = ((guess_orig.nrows() * guess_orig.ncols()) as f64) * SCALED_TOL_TFM * SCALED_TOL_TFM;
|
let tol_sq = ((problem_orig.guess.nrows() * problem_orig.guess.ncols()) as f64) * SCALED_TOL_TFM * SCALED_TOL_TFM;
|
||||||
assert!((motion_proj_tfm - motion_tfm_proj).norm_squared() < tol_sq);
|
assert!((motion_proj_tfm - motion_tfm_proj).norm_squared() < tol_sq);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
use std::rc::Rc;
|
||||||
use sycamore::prelude::*;
|
use sycamore::prelude::*;
|
||||||
use web_sys::{
|
use web_sys::{
|
||||||
KeyboardEvent,
|
KeyboardEvent,
|
||||||
|
@ -9,24 +10,38 @@ use web_sys::{
|
||||||
use crate::{
|
use crate::{
|
||||||
AppState,
|
AppState,
|
||||||
assembly,
|
assembly,
|
||||||
assembly::{ElementKey, Regulator, RegulatorKey},
|
assembly::{
|
||||||
|
ElementKey,
|
||||||
|
HalfCurvatureRegulator,
|
||||||
|
ProductRegulator,
|
||||||
|
Regulator,
|
||||||
|
RegulatorKey
|
||||||
|
},
|
||||||
specified::SpecifiedValue
|
specified::SpecifiedValue
|
||||||
};
|
};
|
||||||
|
|
||||||
// an editable view of a regulator
|
// an editable view of a regulator
|
||||||
#[component(inline_props)]
|
#[component(inline_props)]
|
||||||
fn RegulatorInput(regulator: Regulator) -> View {
|
fn RegulatorInput(regulator: Rc<dyn Regulator>) -> View {
|
||||||
|
// get the regulator's measurement and set point signals
|
||||||
|
let measurement = regulator.measurement();
|
||||||
|
let set_point = regulator.set_point();
|
||||||
|
|
||||||
|
// the `valid` signal tracks whether the last entered value is a valid set
|
||||||
|
// point specification
|
||||||
let valid = create_signal(true);
|
let valid = create_signal(true);
|
||||||
|
|
||||||
|
// the `value` signal holds the current set point specification
|
||||||
let value = create_signal(
|
let value = create_signal(
|
||||||
regulator.set_point.with_untracked(|set_pt| set_pt.spec.clone())
|
set_point.with_untracked(|set_pt| set_pt.spec.clone())
|
||||||
);
|
);
|
||||||
|
|
||||||
// this closure resets the input value to the regulator's set point
|
// this `reset_value` closure resets the input value to the regulator's set
|
||||||
// specification
|
// point specification
|
||||||
let reset_value = move || {
|
let reset_value = move || {
|
||||||
batch(|| {
|
batch(|| {
|
||||||
valid.set(true);
|
valid.set(true);
|
||||||
value.set(regulator.set_point.with(|set_pt| set_pt.spec.clone()));
|
value.set(set_point.with(|set_pt| set_pt.spec.clone()));
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -39,7 +54,7 @@ fn RegulatorInput(regulator: Regulator) -> View {
|
||||||
r#type="text",
|
r#type="text",
|
||||||
class=move || {
|
class=move || {
|
||||||
if valid.get() {
|
if valid.get() {
|
||||||
regulator.set_point.with(|set_pt| {
|
set_point.with(|set_pt| {
|
||||||
if set_pt.is_present() {
|
if set_pt.is_present() {
|
||||||
"regulator-input constraint"
|
"regulator-input constraint"
|
||||||
} else {
|
} else {
|
||||||
|
@ -50,13 +65,13 @@ fn RegulatorInput(regulator: Regulator) -> View {
|
||||||
"regulator-input invalid"
|
"regulator-input invalid"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
placeholder=regulator.measurement.with(|result| result.to_string()),
|
placeholder=measurement.with(|result| result.to_string()),
|
||||||
bind:value=value,
|
bind:value=value,
|
||||||
on:change=move |_| {
|
on:change=move |_| {
|
||||||
valid.set(
|
valid.set(
|
||||||
match SpecifiedValue::try_from(value.get_clone_untracked()) {
|
match SpecifiedValue::try_from(value.get_clone_untracked()) {
|
||||||
Ok(set_pt) => {
|
Ok(set_pt) => {
|
||||||
regulator.set_point.set(set_pt);
|
set_point.set(set_pt);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
Err(_) => false
|
Err(_) => false
|
||||||
|
@ -75,26 +90,53 @@ fn RegulatorInput(regulator: Regulator) -> View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait OutlineItem {
|
||||||
|
fn outline_item(self: Rc<Self>, element_key: ElementKey) -> View;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutlineItem for ProductRegulator {
|
||||||
|
fn outline_item(self: Rc<Self>, element_key: ElementKey) -> View {
|
||||||
|
let state = use_context::<AppState>();
|
||||||
|
let other_subject = if self.subjects[0] == element_key {
|
||||||
|
self.subjects[1]
|
||||||
|
} else {
|
||||||
|
self.subjects[0]
|
||||||
|
};
|
||||||
|
let other_subject_label = state.assembly.elements.with(
|
||||||
|
|elts| elts[other_subject].label.clone()
|
||||||
|
);
|
||||||
|
view! {
|
||||||
|
li(class="regulator") {
|
||||||
|
div(class="regulator-label") { (other_subject_label) }
|
||||||
|
div(class="regulator-type") { "Inversive distance" }
|
||||||
|
RegulatorInput(regulator=self)
|
||||||
|
div(class="status")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutlineItem for HalfCurvatureRegulator {
|
||||||
|
fn outline_item(self: Rc<Self>, _element_key: ElementKey) -> View {
|
||||||
|
view! {
|
||||||
|
li(class="regulator") {
|
||||||
|
div(class="regulator-label") // for spacing
|
||||||
|
div(class="regulator-type") { "Half-curvature" }
|
||||||
|
RegulatorInput(regulator=self)
|
||||||
|
div(class="status")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// a list item that shows a regulator in an outline view of an element
|
// a list item that shows a regulator in an outline view of an element
|
||||||
#[component(inline_props)]
|
#[component(inline_props)]
|
||||||
fn RegulatorOutlineItem(regulator_key: RegulatorKey, element_key: ElementKey) -> View {
|
fn RegulatorOutlineItem(regulator_key: RegulatorKey, element_key: ElementKey) -> View {
|
||||||
let state = use_context::<AppState>();
|
let state = use_context::<AppState>();
|
||||||
let assembly = &state.assembly;
|
let regulator = state.assembly.regulators.with(
|
||||||
let regulator = assembly.regulators.with(|regs| regs[regulator_key]);
|
|regs| regs[regulator_key].clone()
|
||||||
let other_subject = if regulator.subjects.0 == element_key {
|
);
|
||||||
regulator.subjects.1
|
regulator.outline_item(element_key)
|
||||||
} else {
|
|
||||||
regulator.subjects.0
|
|
||||||
};
|
|
||||||
let other_subject_label = assembly.elements.with(|elts| elts[other_subject].label.clone());
|
|
||||||
view! {
|
|
||||||
li(class="regulator") {
|
|
||||||
div(class="regulator-label") { (other_subject_label) }
|
|
||||||
div(class="regulator-type") { "Inversive distance" }
|
|
||||||
RegulatorInput(regulator=regulator)
|
|
||||||
div(class="status")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// a list item that shows an element in an outline view of an assembly
|
// a list item that shows an element in an outline view of an assembly
|
||||||
|
@ -117,7 +159,15 @@ fn ElementOutlineItem(key: ElementKey, element: assembly::Element) -> View {
|
||||||
};
|
};
|
||||||
let regulated = element.regulators.map(|regs| regs.len() > 0);
|
let regulated = element.regulators.map(|regs| regs.len() > 0);
|
||||||
let regulator_list = element.regulators.map(
|
let regulator_list = element.regulators.map(
|
||||||
|regs| regs.clone().into_iter().collect()
|
move |elt_reg_keys| elt_reg_keys
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.sorted_by_key(
|
||||||
|
|®_key| state.assembly.regulators.with(
|
||||||
|
|regs| regs[reg_key].subjects().len()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.collect()
|
||||||
);
|
);
|
||||||
let details_node = create_node_ref();
|
let details_node = create_node_ref();
|
||||||
view! {
|
view! {
|
||||||
|
|
Loading…
Add table
Reference in a new issue