Compare commits
1194 Commits
feature/to
...
dev
Author | SHA1 | Date | |
---|---|---|---|
1881feb5e2 | |||
|
201887187d | ||
fc0393436f | |||
9228e6019c | |||
edbf8c05be | |||
|
f335d63659 | ||
|
c696a22f62 | ||
2fe04040c6 | |||
255d4ba6b7 | |||
48b334a2b6 | |||
ac851bea62 | |||
3b74968f9a | |||
214467d21c | |||
ecb5d28110 | |||
ec88d6be9e | |||
461e5a7c54 | |||
1be6a5ca0e | |||
a67bda8a33 | |||
efef5996e1 | |||
69b59b43f4 | |||
82196250f6 | |||
86324a9219 | |||
203a350650 | |||
b076a6573a | |||
|
e7d8b94889 | ||
5dea38eef8 | |||
|
dcf5b19d80 | ||
11722db3c8 | |||
fcb7e2fa7d | |||
dba001eff3 | |||
49f0d1fe7d | |||
ad66a63ac2 | |||
32c5b3c10d | |||
|
bc1b75f79e | ||
fd9da63ef9 | |||
024e2a1a4f | |||
41a325d428 | |||
79642a869d | |||
fbee95ab8b | |||
10739e0d04 | |||
f8e91c2402 | |||
7d88fb0166 | |||
ca9df8a167 | |||
9e3fd240b8 | |||
a526dcc16b | |||
83d9e1f0af | |||
8a754ace19 | |||
c6f6191ef1 | |||
|
960a334b8e | ||
|
cc4159be67 | ||
24b934eab7 | |||
5c82a5e1fa | |||
2f2f552648 | |||
2386ecba41 | |||
46eacbb750 | |||
ea887b8c72 | |||
544b8610e1 | |||
a84f1e1500 | |||
328d45444c | |||
1765f8cf8c | |||
bfb556b013 | |||
5129f29084 | |||
56933ecff3 | |||
12a02320ec | |||
7a4e9e70f9 | |||
23c0758ba6 | |||
dd3d38490a | |||
9da14089e0 | |||
5196322b7a | |||
eff70eb690 | |||
67994d35d9 | |||
efb853c1bc | |||
19bebfd1ed | |||
62f1c59d73 | |||
976714475e | |||
1e2a8a40e5 | |||
cfac7ecffc | |||
14f0fa1a6f | |||
a3c65e5b17 | |||
4abe25c188 | |||
6da51b7794 | |||
a001c74025 | |||
d3893ab7e6 | |||
|
7e46c7de4e | ||
|
e00c2a4e2b | ||
|
5f2690309b | ||
c0a7cff1d8 | |||
009f93adbb | |||
|
ef4335bc41 | ||
1f6b7abf46 | |||
|
f91b018d4f | ||
|
346e2e97f2 | ||
|
0655642933 | ||
|
e8dafad6c5 | ||
|
162e37cb2f | ||
|
cac5b513f3 | ||
|
0c7f5697da | ||
|
1ed40cd8ce | ||
|
29d392a8a0 | ||
|
963e14b00a | ||
c940645e2e | |||
|
c017d58265 | ||
|
8d81d2d8d5 | ||
|
f65a463773 | ||
|
2ead722620 | ||
|
47600dff23 | ||
|
3a1817586f | ||
|
1afb0d0a4c | ||
|
33cb317cee | ||
|
20c20a30e8 | ||
|
e738fbc86d | ||
|
ce16946105 | ||
|
a18fa01100 | ||
65c6962544 | |||
3e9d28be31 | |||
|
b5f85a6d86 | ||
13d6ea2a16 | |||
378180ba09 | |||
|
1c337789a5 | ||
|
debcef4c9a | ||
|
acff855c93 | ||
1222fd4617 | |||
8cdbc8dbbe | |||
4ab2244ac9 | |||
4ab1b7d0d4 | |||
8eb25596a0 | |||
4dbcaca87c | |||
1316e6548e | |||
|
46b3773419 | ||
|
cfe8e9bfee | ||
|
64e563340a | ||
|
f44039e309 | ||
|
16385b5f4e | ||
|
b526f9a476 | ||
|
89a5522144 | ||
|
19c1af1874 | ||
|
10f84bd630 | ||
40b3fa782c | |||
|
a02085918a | ||
|
a9627071ff | ||
|
a74a7808a2 | ||
|
a7c54d3ffb | ||
|
0c565c6056 | ||
f09371a3f9 | |||
cdfddb7551 | |||
8e281e8b0f | |||
|
1e27af9cf5 | ||
|
0193349f94 | ||
|
98781c83ad | ||
|
e6da61c52a | ||
|
dababe3075 | ||
|
85395ff82e | ||
|
5b95923bb9 | ||
|
a91b43a52d | ||
|
0ce1861ab4 | ||
|
a68ebef26d | ||
|
2b83560da8 | ||
e76d8e0774 | |||
875e32679b | |||
|
31d1cc774a | ||
|
a4ca6e3d58 | ||
5965ca940b | |||
e1d5409c0d | |||
8ac7567afd | |||
b2746e5c0e | |||
ce388fed44 | |||
|
4db091d898 | ||
|
165dfd6c5d | ||
|
ba26c7020e | ||
|
1d7f4ed538 | ||
|
115736e98a | ||
|
96554d2b0c | ||
7cc6a4be40 | |||
00ce7d5a48 | |||
a0e2ef1afc | |||
025cb58060 | |||
639a255aaf | |||
f5201b6be0 | |||
1e46ffbd98 | |||
fd35d7c614 | |||
109e050f03 | |||
f809e40791 | |||
d08424428e | |||
93bc15f346 | |||
|
11dd4088d9 | ||
|
24c39c97cd | ||
|
ea5305c8d8 | ||
|
d87eefcaa3 | ||
6d219341f9 | |||
56bba749c0 | |||
|
81213eb943 | ||
c442eb7e94 | |||
62c8610a9e | |||
c36af3515e | |||
ef336af87d | |||
cd2ade881a | |||
5625800fc9 | |||
|
28b85b0f53 | ||
|
4c1ffdb6d9 | ||
72c7030297 | |||
a3963ac4f5 | |||
4871baf0e5 | |||
|
2bce369c5d | ||
|
1b6a41c728 | ||
|
61d43ae5fa | ||
|
6288eb9d97 | ||
|
2c13386646 | ||
db61f71440 | |||
04127fc3f2 | |||
|
cc0fb2a718 | ||
ed4aa47913 | |||
67316c4a70 | |||
7d897ad8cb | |||
|
8998a394b3 | ||
|
c342c5cd78 | ||
|
d535a2155f | ||
|
bef317677c | ||
|
50579f4712 | ||
784d397ab1 | |||
6deeaf057e | |||
2c6d1e89c5 | |||
0366a69123 | |||
db30913542 | |||
d97888f135 | |||
7f4f4c7703 | |||
2e4be2aa3a | |||
3f4fe9e43b | |||
6d47c0ccec | |||
29977650f1 | |||
991ab907d8 | |||
|
9e141db871 | ||
b14e2fdd08 | |||
cff563c321 | |||
8286db30af | |||
94489b28e2 | |||
fb0d016aa8 | |||
e24463c58b | |||
ee569b85f8 | |||
b0abcf2d0c | |||
c653052d8c | |||
|
2376d278c3 | ||
89d0cbc7ea | |||
b602066f48 | |||
d70389d2e6 | |||
4d1137659b | |||
6bf8d9d325 | |||
2358f53cf7 | |||
20886d6f6b | |||
b5d04ba02c | |||
3729faf49b | |||
a9821772db | |||
5042fda751 | |||
ad97751327 | |||
0c1d0aa64e | |||
ec77cd1fc3 | |||
|
26662b5114 | ||
98e21f3c3a | |||
978de59b7a | |||
5af0c91f0a | |||
6111c673ee | |||
|
7f77c1e710 | ||
|
efe14f50bf | ||
|
b6d2eb3b1b | ||
a8182fad23 | |||
ee0d44e12e | |||
e636ed27bd | |||
5402ba47c9 | |||
9456217935 | |||
|
c5516e5581 | ||
0e9072710f | |||
137ddb3ade | |||
|
99fee476bc | ||
|
a2fb14a221 | ||
|
c2025ee1c9 | ||
|
b5406e460e | ||
323e8b6872 | |||
1e8a8cac7e | |||
|
ad30c68eba | ||
|
0c6ad35c13 | ||
|
e1b8fcdbbf | ||
|
fe4eb96dae | ||
|
163a7c717a | ||
|
9d4df5d8e0 | ||
|
f2cbbeba20 | ||
|
429eefa3f7 | ||
|
86fce7ec68 | ||
|
8faa312424 | ||
|
3260c3d171 | ||
|
7de157ce24 | ||
|
f48e4483cc | ||
|
2d86cf1cc7 | ||
|
99c7174802 | ||
|
58d7015782 | ||
|
3a91cb2579 | ||
|
db19df4329 | ||
|
a1a2c41846 | ||
3eef778f60 | |||
|
579511a5ee | ||
68add4cb5f | |||
b522e5919e | |||
|
fc036215a5 | ||
|
debff5357b | ||
|
4f88982734 | ||
|
fa6d741869 | ||
|
ada1141738 | ||
|
cdb116fa20 | ||
|
32769d6906 | ||
18ae964e57 | |||
bfadf5b33d | |||
846a6d2620 | |||
f5fe53a9f2 | |||
5846f42141 | |||
|
4ea29c82c5 | ||
56f3c05907 | |||
|
87aeda84d9 | ||
0eb9bd810c | |||
|
f7d159bc03 | ||
|
5bc627f1d4 | ||
|
6ff79e28ac | ||
|
f726e6d0f1 | ||
|
51dd72e48f | ||
|
1c719b9e70 | ||
|
d44a48bdb1 | ||
|
d3be07987c | ||
|
923c52737d | ||
|
5834fad938 | ||
|
45ed45bd13 | ||
|
e40977647d | ||
|
e89e4e19d3 | ||
|
39088ec36b | ||
|
102e83b478 | ||
|
672a3c1552 | ||
|
f147636e9d | ||
|
c8b9951f46 | ||
|
64b33aed18 | ||
|
da46ea923c | ||
|
043d292eca | ||
|
0ef2258665 | ||
|
ed634013f6 | ||
|
cb7291ccb0 | ||
|
630d16bbee | ||
|
fc2455fe34 | ||
|
3e917baaaf | ||
|
403ff93f4a | ||
|
9fc99a4c72 | ||
|
6c8fa29304 | ||
|
d416f8cf34 | ||
|
680d23ddcb | ||
|
1ea336b70e | ||
|
b5a94923b5 | ||
a1267d84ac | |||
|
eadd521e35 | ||
b5031121ce | |||
|
d0134bdbe9 | ||
a810790d8d | |||
|
b09127f090 | ||
|
f0053daf77 | ||
85a1e8b33f | |||
|
58e0715714 | ||
|
5928adfe45 | ||
|
4e08d6d877 | ||
1fd8dfd7b8 | |||
|
37ad48e820 | ||
|
dbb48a2a9f | ||
|
ab9bba2202 | ||
|
b50d8dcd23 | ||
|
94fd24d852 | ||
|
e710013800 | ||
|
3a6aa14320 | ||
fabad733f4 | |||
e1276b684f | |||
569e01fce1 | |||
|
17703e407d | ||
|
a6b86eeee1 | ||
|
03b92de6e0 | ||
|
8af183a969 | ||
|
a2b02ef09e | ||
|
9b51062bf7 | ||
|
89cdbf4d71 | ||
|
b92ef23f5d | ||
|
de9f3cc8df | ||
c28be83226 | |||
|
af2e437a48 | ||
5a36c3e03c | |||
|
2144c6382c | ||
|
7e4ece8dbc | ||
|
b698f2d613 | ||
|
19cd74013b | ||
|
5bb895a653 | ||
358d750226 | |||
d862a0a896 | |||
74e6bc65a3 | |||
916bc69e4b | |||
7e4d223044 | |||
b509dc917d | |||
|
ff58985d78 | ||
1295a407c3 | |||
6247e79884 | |||
27a252b637 | |||
229c36b661 | |||
|
40b088149b | ||
|
86d89f89f9 | ||
eba3a2526e | |||
3de8976ea5 | |||
|
c24cf90262 | ||
3a2faa7da4 | |||
a2c0bc8a10 | |||
73f72f12bc | |||
|
7f7b550674 | ||
|
5988b9ad30 | ||
|
97a320c9ef | ||
|
bae465fe86 | ||
|
3277a99ed3 | ||
|
38fd3e24c8 | ||
|
13fb49e48c | ||
|
92cffd78d9 | ||
|
b3087c245f | ||
|
f7286d33d2 | ||
|
7e328a5dbf | ||
|
060f0ee35d | ||
ce82d2d076 | |||
3a3a5bd77f | |||
29369cd6d7 | |||
|
420bf05b22 | ||
|
0a5122a974 | ||
|
d75a41482d | ||
|
5b8d6b601e | ||
|
b44c99c265 | ||
|
39ce855075 | ||
|
2f9e504357 | ||
|
09868f090b | ||
|
98b9a70893 | ||
|
c6d1068df4 | ||
|
51b0d232b5 | ||
|
83d57c7295 | ||
|
88e0dcf413 | ||
|
25ec59b985 | ||
|
fbc21101bb | ||
|
5d4514a742 | ||
|
90a7c4d901 | ||
|
a965f5683f | ||
39640498fc | |||
|
85cd3b4de6 | ||
|
cdc85291bc | ||
|
ed2f14b68e | ||
|
86553e9f35 | ||
|
d63c4acf10 | ||
|
ffd3ae7684 | ||
|
a8a95c9df7 | ||
|
e5186d469a | ||
|
2082175af5 | ||
|
75fd920735 | ||
|
3c9d8a4eee | ||
|
24944cdb16 | ||
|
9aa131a9c6 | ||
|
16cf1bc65e | ||
|
bb5e638b31 | ||
|
1f9d8d34f5 | ||
|
91c9ea61da | ||
|
1754ae0695 | ||
|
79736a0a9b | ||
|
f86529d659 | ||
|
ebd7f799ad | ||
|
31ccf744c5 | ||
|
fb01d85197 | ||
|
44febbdd73 | ||
|
dd820da765 | ||
|
07f4b83722 | ||
|
de53d032af | ||
|
033edd3feb | ||
|
59e65afc63 | ||
|
93de1d5311 | ||
|
571c6342dd | ||
|
cab5958107 | ||
|
191dd02e47 | ||
|
843d63c76a | ||
|
ffea8cc223 | ||
|
ab9dcd83b9 | ||
|
92ba439f2a | ||
0b2e8ff25e | |||
|
df075718db | ||
|
8518f333e3 | ||
4575ab2b79 | |||
|
2483c56f1c | ||
|
c80f70fe0f | ||
|
a621dd7c5b | ||
|
dda6602ed4 | ||
|
b13765ec19 | ||
|
7aff774bc1 | ||
|
7a72a0b979 | ||
ac3adfa644 | |||
|
a78e361b17 | ||
|
8974164ec0 | ||
408443989c | |||
|
745a7ad66e | ||
|
7b1bdc21a4 | ||
|
ef747f642f | ||
|
e094f6e8ee | ||
53ab8334dd | |||
|
d35516b9af | ||
7bb66f6a00 | |||
41fc6b4dd9 | |||
|
2e13d518f6 | ||
|
8607639876 | ||
|
d10815020d | ||
91d93b3bb2 | |||
dd8a4796f6 | |||
479d106165 | |||
|
4b4c878e21 | ||
2f96d619fc | |||
|
4badc3e044 | ||
|
6255a46004 | ||
e11df4fdd5 | |||
|
a9779fe38b | ||
|
f6fa288011 | ||
|
a3556ecdb3 | ||
|
cf5f886226 | ||
|
5ba7d74bd2 | ||
|
c6a4721d64 | ||
|
d2e3110480 | ||
24799a691f | |||
|
4691caaa7f | ||
|
06a6a99ef0 | ||
|
0f7a25762e | ||
|
e38b2e1c53 | ||
|
a6922ab9d8 | ||
|
7ceb0b69b8 | ||
|
e25827eb14 | ||
|
b1911ebe2d | ||
|
70ac232c15 | ||
|
7b50400de5 | ||
|
f231d722c6 | ||
4e16cf1c98 | |||
6c2abdaab0 | |||
c583320051 | |||
9a1f8a2266 | |||
fa9ff4c978 | |||
d62bc66d4a | |||
f6b576071d | |||
1315a8cd34 | |||
a1351aa942 | |||
bf504ae6c5 | |||
0e1e97a3ff | |||
726864ed0e | |||
|
bd0895b268 | ||
|
62e7073ed2 | ||
|
a994b8a50c | ||
b65197f577 | |||
|
eb1bc5acc4 | ||
|
db06d10cc2 | ||
46e7da9ae0 | |||
0f5f59e175 | |||
4db7398a28 | |||
64629561af | |||
7bdc54c818 | |||
|
f8d21ad072 | ||
29a90efca5 | |||
4635cd3fb3 | |||
7e59ec5804 | |||
cc114041c4 | |||
47aeb36979 | |||
cfd3f3b7e1 | |||
69e6849a12 | |||
6c4741ede6 | |||
40c02f4bd7 | |||
|
42259e3eb9 | ||
98bbc8349c | |||
|
ae8655d6af | ||
|
bfc6cbe5d8 | ||
dccc92bf2f | |||
a81ab474f7 | |||
827f115a92 | |||
05ae21580b | |||
9b9fe07044 | |||
6de43ee4ba | |||
da34d0f71b | |||
4513b06e87 | |||
688382eed6 | |||
d0354da80a | |||
0ac5363acf | |||
|
6a9f4d4626 | ||
8d2770c275 | |||
09a9df5213 | |||
30e3e80397 | |||
d9f36365d9 | |||
663aaa8b4c | |||
fd8a61c852 | |||
abae29bbed | |||
85aefb5380 | |||
0f634688cc | |||
01bbb4bb13 | |||
|
4a066ea364 | ||
|
a68884142f | ||
64781a6785 | |||
974d73e25c | |||
89eebbecb7 | |||
9fcc1b3af2 | |||
546d56aeee | |||
49ec5d1554 | |||
|
6dc9e8847a | ||
|
55ea3658b9 | ||
|
8581b32448 | ||
|
b0bbdc122e | ||
|
7e0820d861 | ||
|
0b90dd4df2 | ||
|
3c6b068c39 | ||
|
bcc666d19e | ||
|
47ac2dd0a9 | ||
|
f271ded526 | ||
|
603db46eb8 | ||
|
1bc642efb6 | ||
|
e7173e9d5d | ||
|
ca6955beb5 | ||
|
b74bc32015 | ||
|
9023098090 | ||
8d33d6beab | |||
dfd6e0a949 | |||
aaa298616d | |||
|
06fc5bbe66 | ||
9b8da4cdcc | |||
|
da27c2e494 | ||
a020d1545c | |||
|
ff1fee022c | ||
|
adff75bb6b | ||
|
86a45504e3 | ||
|
21dd5ddd7d | ||
|
8e766497c6 | ||
|
c377d6cda8 | ||
|
56fed6c16a | ||
|
2aede5b7b9 | ||
|
899d7d8152 | ||
|
afd5908784 | ||
|
fe21f0c954 | ||
|
065f95f912 | ||
|
dd776bb0d1 | ||
|
dd01c39cbe | ||
|
2d3a5fb5c8 | ||
c263b1acbe | |||
ef50a4d963 | |||
|
8b3298f7a8 | ||
|
ec8f14a6e9 | ||
|
bc28412950 | ||
|
ca645aec17 | ||
|
b1998ed1a9 | ||
|
3023bd639e | ||
|
ef41c3f168 | ||
|
ecd70f2139 | ||
|
5d2eaaf68a | ||
3ba12f4999 | |||
|
d50163d247 | ||
|
83fc4e28d8 | ||
|
839b1f2a82 | ||
|
9f513b355c | ||
|
4a0c47c3dc | ||
|
7feb87ff05 | ||
|
65d0cbbe31 | ||
|
5d5f84ad55 | ||
|
d133f54476 | ||
94c58b7749 | |||
|
45f1588175 | ||
|
cfe6c3ef4b | ||
|
4d6428a308 | ||
|
c1b105db2a | ||
|
03be37bb4f | ||
|
b99d0b96d8 | ||
|
9a9ebc7304 | ||
|
590910ac2d | ||
|
abb3d9fe50 | ||
|
6c815abd54 | ||
|
2dff15c5aa | ||
|
ecab9a458f | ||
|
71b3dc2179 | ||
|
46bf66c8ee | ||
|
7b736a7c81 | ||
|
4810f2e63e | ||
|
c0ab082d24 | ||
|
a3c64dc273 | ||
|
7d0eff74f6 | ||
95c0b2d3f0 | |||
7f32348e7a | |||
|
0f3b3b35d9 | ||
|
a02cf0487c | ||
|
65e0560553 | ||
|
8da331f476 | ||
c8621ee5b7 | |||
f84f7f8e45 | |||
f2b7a08ad8 | |||
c240fa4a9e | |||
88e94a7fd9 | |||
3ec674c61b | |||
12805712d3 | |||
380c76fe40 | |||
ec7a971df7 | |||
a24c8dcbce | |||
18509f1259 | |||
|
889244902b | ||
|
189449f40e | ||
|
a722cf0cdb | ||
|
bb228e0c68 | ||
|
485e90fcd0 | ||
|
958788bc91 | ||
|
15a0258b7d | ||
|
2889f0794b | ||
|
d7a4228f5f | ||
|
5d2fff6575 | ||
8a07140f7c | |||
0898285542 | |||
ddb8917535 | |||
|
b4dd4380c0 | ||
|
e7235e2a9c | ||
a67c112793 | |||
8b92db9923 | |||
d45d44f96d | |||
53a6d3543f | |||
|
72f4d7c7e6 | ||
|
dfac6aeb5c | ||
83b6d8fee0 | |||
4c1a7f98a1 | |||
e6c6925209 | |||
7f1789c556 | |||
516444d1bc | |||
15d874fb06 | |||
|
47526d4dd5 | ||
|
eb3a8655fb | ||
f86a6130e0 | |||
d1e76175b7 | |||
6f39b38a72 | |||
4964fb2642 | |||
|
4065466be3 | ||
|
b33c68e315 | ||
|
6362918365 | ||
|
b94172fd22 | ||
42d130f69c | |||
fff7377687 | |||
6eb95f26eb | |||
|
a0621bba5b | ||
|
cf555bc8ae | ||
dc9ec54644 | |||
1a615c503d | |||
1b60f71ed0 | |||
|
c1b94ff0bc | ||
|
a86e8eb164 | ||
|
bdb9ce6a59 | ||
|
a299003236 | ||
|
c204747401 | ||
|
e110253d8f | ||
|
ed5e94f580 | ||
|
fcb9605338 | ||
|
1e94538931 | ||
feb5743f58 | |||
f5289abdc3 | |||
97c4b81717 | |||
|
3131e2a40d | ||
|
d721c4b597 | ||
|
e5f3ee75be | ||
|
8443fac4ae | ||
|
1e71f29d5e | ||
|
ded01251d1 | ||
|
ed86a31c50 | ||
|
b4e47494fc | ||
|
9184bd55de | ||
|
74d14970b9 | ||
|
e01ee63c03 | ||
|
e302b5ea4c | ||
|
2da0648d73 | ||
|
3ad7f32ada | ||
|
d17a3ac6ef | ||
|
1716b7f5d1 | ||
|
e2920ed683 | ||
|
bbef697b7d | ||
|
ca02f5406d | ||
|
50d55e9734 | ||
6d78bb8d91 | |||
515d2391ee | |||
7ce0829597 | |||
e4e661a3bf | |||
0622be2494 | |||
|
c420c2ccc6 | ||
|
512ed1139c | ||
|
33e27cd992 | ||
|
11a1624e64 | ||
|
dde1db7b0a | ||
|
75ef241be3 | ||
|
a5b72f2016 | ||
|
21b5d45b96 | ||
|
5b725a087b | ||
|
d73d03c055 | ||
|
e80eefa90f | ||
|
d31726a0d9 | ||
|
0ef64130ae | ||
|
0920e21d62 | ||
|
14ca7cdd31 | ||
|
1b1a078dea | ||
|
febe526325 | ||
|
db5378c9f4 | ||
|
5fe1320855 | ||
|
90149e3965 | ||
|
56cadbd9ef | ||
|
dc22bd8498 | ||
|
8ac253b9fe | ||
|
35928e7960 | ||
|
0e793eba26 | ||
|
499cf85ff0 | ||
|
16bed53997 | ||
|
477e64e4d3 | ||
|
a1cbd7a457 | ||
|
0680a3a1cb | ||
|
229c1b57da | ||
|
b7cc4e4b1b | ||
|
431db00f1a | ||
|
218b81a242 | ||
|
d0281871fa | ||
|
3e10e1463a | ||
|
591b408729 | ||
|
b59e48410f | ||
|
7f8914d8ea | ||
|
8898f908ef | ||
|
eca1ad48f5 | ||
|
889b8a4490 | ||
|
a8a5c769c4 | ||
|
f0627b2ced | ||
|
5aaba0dae4 | ||
|
c8fb770ffd | ||
|
1fe1a74b48 | ||
|
48d86fac56 | ||
|
ac6608b5b4 | ||
|
bfba653904 | ||
|
83c7ec8c6b | ||
|
fe81dea243 | ||
|
b7cac3a015 | ||
|
1b6bd67b90 | ||
|
74773686b4 | ||
|
8a039326d4 | ||
|
f0cdb9b657 | ||
|
e2c7751c7e | ||
|
1695fc5075 | ||
|
42ddd2e569 | ||
|
86c2816cfd | ||
|
77d72c7bf6 | ||
|
6be5caa93f | ||
|
e5e62bc544 | ||
|
72d91b04da | ||
|
2aed0316f4 | ||
|
fd7e26d6c5 | ||
|
598b2e1587 | ||
|
bd068b2c14 | ||
|
e371a4a6db | ||
|
b546f3f78b | ||
|
09f0a2879e | ||
|
cba62a9468 | ||
|
432f404d7c | ||
|
b9f1f0e525 | ||
|
64c6cbf860 | ||
|
6f5b0f0a03 | ||
|
51f084d28b | ||
|
a0e9180db6 | ||
|
b65a673173 | ||
|
0f786e4f6f | ||
|
e3f7b7a5fa | ||
|
23ea4a95a1 | ||
|
c2db3a23e1 | ||
|
30ca333c04 | ||
|
2c001cb1b3 | ||
7b6361e59d | |||
|
1f71b5333a | ||
257337f4fb | |||
|
4f593aec63 | ||
|
077c2b4e3b | ||
|
287e2aeba2 | ||
2cf56641aa | |||
|
559e8b24ab | ||
|
cc11df6174 | ||
|
76b5cd0de5 | ||
|
84b149fa81 | ||
|
488f5f0008 | ||
7a11ed0797 | |||
|
23d2f8d758 | ||
|
cfa9077e29 | ||
|
264139fe13 | ||
|
0a0d0af94a | ||
|
a722672b35 | ||
|
b6a57dbfd0 | ||
6aa5b547b5 | |||
9c353f4a0d | |||
|
477f75270c | ||
|
84fa878ee3 | ||
fd4108b74f | |||
86818f6864 | |||
07e39a068d | |||
6c215abf13 | |||
|
2418b0bb9e | ||
f67cfcc9e6 | |||
922ca564b1 | |||
|
3dc7038b6e | ||
562e641b06 | |||
b84ac68bd8 | |||
|
41d0be8085 | ||
8689d29e4c | |||
|
a110dc20d5 | ||
00a2ce2152 | |||
|
2ac55e851f | ||
|
4ac65b60cd | ||
299592ed25 | |||
e38685951c | |||
ef1200aad0 | |||
65a8d8f581 | |||
|
82d8394a9f | ||
|
1582ac2c29 | ||
|
4f8ab4dd78 | ||
|
e9c31b7827 | ||
|
1e7cf39150 | ||
|
77a3db56fc | ||
1d1937405d | |||
ba3c9b6d45 | |||
|
baa303171e | ||
|
41ac72b4fb | ||
|
b7da52edb1 | ||
|
41b7349a43 | ||
19ec6a57a4 | |||
93bc371622 | |||
|
0fa73e1e9e | ||
|
b46e8c5fe2 | ||
e2ceb64d36 | |||
|
2092cc9af4 | ||
|
bbe7c99ec5 | ||
|
aeb71b5d27 | ||
|
c7669d4fba | ||
|
a2d41d5e73 | ||
6cea5742e8 | |||
ce4dcb63b0 | |||
000c79d42f | |||
4abd0bdb6f | |||
acb4052fe4 | |||
|
75783bcb03 | ||
|
b51427d2ab | ||
|
1e8da7a87b | ||
|
a692412cff | ||
|
fe8579180d | ||
|
3f0dff3ce9 | ||
|
e4dbabc30f | ||
|
5d8b42da90 | ||
|
8c1131dd58 | ||
|
a09a1c7adc | ||
|
ea4d6618b4 | ||
|
74dfca4e2e | ||
31460df721 | |||
|
383376080e | ||
5bdc02d18c | |||
|
174f6566e1 | ||
|
2bbe10e41c | ||
|
dcdc22dd9d | ||
|
45301d9172 | ||
|
4336788a6b | ||
|
814eab8cde | ||
|
94093378e0 | ||
|
cf91da1a98 | ||
f7e792faff | |||
|
ae5ca44dc0 | ||
|
e6921025d1 | ||
a91d468b74 | |||
|
3e98240b94 | ||
af4866e876 | |||
c2bab5d138 | |||
|
ae911fcc2f | ||
|
9ee506b1d2 | ||
|
b36281fa39 | ||
|
706a44fd33 | ||
|
5abd63cde2 | ||
|
61edf999c8 | ||
|
6305acea68 | ||
|
b4fc311668 | ||
|
9574099f9b | ||
|
f26cad6d18 | ||
|
07b6f988c2 | ||
|
b5d3ca76db | ||
|
ae30d3a03e | ||
|
03455a3beb | ||
|
581c13c573 | ||
|
370bab462c | ||
|
139534fdb3 | ||
|
97f148c175 | ||
|
2503d35ba8 | ||
|
d281dfca3a | ||
|
6e85d496f2 | ||
|
51eca003af | ||
|
92710097f0 | ||
|
3219712019 | ||
|
22b68e5ca4 | ||
|
5d830206a2 | ||
|
516cd90677 | ||
|
e03910354e | ||
|
056699f27b | ||
|
1588b5d94f | ||
|
3cb9535fc9 | ||
|
a6354623ec | ||
|
d6a1bee93b | ||
|
1f19ac88ae | ||
|
9162867fc2 | ||
|
1056fc7200 | ||
|
daa0777182 | ||
|
94b5afa6c4 | ||
|
f70f60c0e8 | ||
|
a4aa4b80d2 | ||
|
ab81370001 | ||
|
96a755071f | ||
|
206bcfc909 | ||
cd05ca6e95 | |||
|
5c0674f1f5 | ||
|
fea53af0ee | ||
|
c2f11fb6e1 | ||
e216fd50f5 | |||
|
e01ca38fb3 | ||
|
078686a046 | ||
|
570642e56d | ||
|
7579a35f8e | ||
|
4d160b81b9 | ||
|
2d2c4bd474 | ||
|
5a108c0604 | ||
|
1b01654667 | ||
|
67aa173927 | ||
|
0365d41f31 | ||
|
df402086da | ||
|
8e9a85078e | ||
|
fa78ed1f45 | ||
|
d8ef190ed8 | ||
|
94e5ee4a6d | ||
|
510c855a65 | ||
|
b7e1349ead | ||
|
8933c820b3 | ||
|
a0534b896f | ||
|
93d3cb47be | ||
|
3535e51248 | ||
|
274be61330 | ||
|
5e94610e28 | ||
aeceb4a337 | |||
88d0c19a74 | |||
|
defaf716d7 | ||
|
c4367ac509 | ||
|
4dafb8eb49 | ||
|
6375cb5fd8 | ||
|
1fa0da2810 | ||
|
efb23591a9 | ||
248d42c4e0 | |||
90981f6a40 | |||
a3ca06a241 | |||
206e4cbcf6 | |||
05f742452d | |||
|
7c0d805018 | ||
105b84b87c | |||
|
bd3425e7a5 | ||
|
138d376289 | ||
|
70bebbe848 | ||
874875c13a | |||
|
99ee5aa54a | ||
|
0553a28ee8 | ||
b2df860381 | |||
|
f4454a6cf6 | ||
|
791f55ee8a | ||
|
7cb5cd8f71 | ||
|
f8e0d4be17 | ||
|
b227a82a80 | ||
acfdd187a4 | |||
|
b6a5fbfc14 | ||
|
f66ac653e0 | ||
|
88542cc858 | ||
484a58755f | |||
|
e4d856033a | ||
17647742a8 | |||
e8e5d98e9d | |||
179a07e034 | |||
|
913c12fb30 | ||
cceffa09e8 | |||
71ed56c2b6 | |||
|
a3ca861ebe | ||
|
50ed7ce28b | ||
|
2d2c5aa684 | ||
8c098b6033 | |||
d9743978ab | |||
0e0deaeb72 | |||
|
4e4690e510 | ||
|
04f6ef1ed0 | ||
|
39a0889123 | ||
|
7d416f55d4 | ||
|
c02f71263d | ||
|
8af2f5eb31 | ||
6c451b5ca7 | |||
e01f90b5e0 | |||
5a568c4587 | |||
0cc68e72ce | |||
8179be2f62 | |||
0aa73cd48f | |||
|
384415dc98 | ||
be9398b322 | |||
|
8f88a101d2 | ||
|
3e0d152c1b | ||
|
0911efd4aa | ||
5e6f65a181 | |||
d5ba816b7d | |||
19d3998c3b | |||
9bc8e8fbf9 | |||
|
48ad773c9d | ||
|
6b44439d43 | ||
|
2216e23273 | ||
|
171f5d5ba3 | ||
|
0ed70cc960 | ||
|
fed74dd69c | ||
|
756626c9bc | ||
|
de89ef437c | ||
|
1c02ab3471 | ||
|
5e9b2de8b0 | ||
|
850dd3f58e | ||
|
fa63b84b78 | ||
52a942dbe2 | |||
|
401ca2443d | ||
|
d562541965 | ||
|
03cc6a310b | ||
|
626d5c98fa | ||
|
70e1861e53 | ||
|
454d574ccd | ||
|
993bba3133 | ||
|
95b814e163 | ||
|
f9500f44ec | ||
|
bb4894b87e | ||
|
723e0e458e | ||
|
f449bdd58f | ||
803f298d8b | |||
fd51564628 | |||
522f39cef3 | |||
|
3e15413465 | ||
|
5c2f15da04 | ||
|
39b41cc2ae | ||
fe95c4e48e | |||
6a5ca2a115 | |||
|
940718098d | ||
|
3a37b88b5c | ||
|
6298189fb3 | ||
|
fe55856a26 | ||
|
4210481223 | ||
8ae8ebe871 | |||
|
90f4ff06fd | ||
|
ed007589cf | ||
|
fe9334d570 | ||
|
4aa1df0628 | ||
|
30bd56d0f7 | ||
|
4ec33c6857 | ||
|
a68b102e40 | ||
|
13792b07b2 | ||
|
d0cf16c8a6 | ||
|
aa69c8fde4 | ||
|
16fcc1c412 | ||
|
98171bad07 | ||
|
dc76a987e1 | ||
|
d69a04bb6e | ||
|
39f2c6c3f4 | ||
|
9210bc9198 | ||
|
9c77f8f02f | ||
|
624460c52d | ||
|
2f11660439 | ||
|
e43aad33fe | ||
|
5c54640e60 | ||
|
5a3fccb455 | ||
|
12758d589e | ||
|
f18cd9ad40 | ||
|
3c602e859d | ||
|
55909aee0d | ||
|
59b120e086 | ||
|
826ec727b7 | ||
|
612f6f0082 | ||
|
d4aa4587a9 | ||
|
0c6fff3878 | ||
|
26d81bddb5 | ||
|
b665a3a2fc | ||
|
b83293a057 | ||
|
53ebec2e01 | ||
|
e35a364aa8 | ||
|
b5fa1ed6e8 | ||
|
019f60c721 | ||
|
551d4991fb | ||
|
6fc6d124ca | ||
|
fae33ed062 | ||
|
8b9c03e616 | ||
|
a03c82f758 | ||
|
46f6d57fd9 | ||
|
8cdc596549 | ||
|
822f960e9c | ||
|
246feacd72 | ||
|
46649a1ddf | ||
|
d4226b7e7d | ||
|
5ff76209aa | ||
|
2b24bd979e | ||
|
e7b1203c2d | ||
|
28062cb096 | ||
|
bc59f8b287 | ||
|
2de9548c23 |
3
.github/CODEOWNERS
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
@altavir
|
||||
|
||||
/kmath-trajectory @ESchouten
|
115
.github/workflows/build.yml
vendored
@ -1,107 +1,24 @@
|
||||
name: Gradle build
|
||||
|
||||
on: [ push ]
|
||||
on:
|
||||
push:
|
||||
branches: [ dev, master ]
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build-ubuntu:
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Install Chrome
|
||||
run: |
|
||||
sudo apt install -y libappindicator1 fonts-liberation
|
||||
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
||||
sudo dpkg -i google-chrome*.deb
|
||||
- name: Cache gradle
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
.gradle
|
||||
build
|
||||
~/.gradle
|
||||
key: gradle
|
||||
restore-keys: gradle
|
||||
|
||||
- name: Cache konan
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.konan/dependencies
|
||||
~/.konan/kotlin-native-prebuilt-linux-*
|
||||
key: ${{ runner.os }}-konan
|
||||
restore-keys: ${{ runner.os }}-konan
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew -Dorg.gradle.daemon=false --build-cache build
|
||||
|
||||
build-osx:
|
||||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Cache gradle
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
.gradle
|
||||
build
|
||||
~/.gradle
|
||||
key: gradle
|
||||
restore-keys: gradle
|
||||
|
||||
- name: Cache konan
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.konan/dependencies
|
||||
~/.konan/kotlin-native-prebuilt-macos-*
|
||||
key: ${{ runner.os }}-konan
|
||||
restore-keys: ${{ runner.os }}-konan
|
||||
- name: Build with Gradle
|
||||
run: sudo ./gradlew -Dorg.gradle.daemon=false --build-cache build
|
||||
|
||||
build-windows:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3.5.1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Add msys to path
|
||||
run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"
|
||||
- name: Cache gradle
|
||||
uses: actions/cache@v2
|
||||
java-version: '11'
|
||||
distribution: 'liberica'
|
||||
cache: 'gradle'
|
||||
- name: Gradle Wrapper Validation
|
||||
uses: gradle/wrapper-validation-action@v1.0.4
|
||||
- name: Gradle Build
|
||||
uses: gradle/gradle-build-action@v2.4.2
|
||||
with:
|
||||
path: |
|
||||
.gradle
|
||||
build
|
||||
~/.gradle
|
||||
key: ${{ runner.os }}-gradle
|
||||
restore-keys: ${{ runner.os }}-gradle
|
||||
|
||||
- name: Cache konan
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.konan/dependencies
|
||||
~/.konan/kotlin-native-prebuilt-mingw-*
|
||||
key: ${{ runner.os }}-konan
|
||||
restore-keys: ${{ runner.os }}-konan
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew --build-cache build
|
||||
arguments: test jvmTest
|
||||
|
31
.github/workflows/pages.yml
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
name: Dokka publication
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [ created ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
timeout-minutes: 40
|
||||
steps:
|
||||
- uses: actions/checkout@v3.0.0
|
||||
- uses: actions/setup-java@v3.0.0
|
||||
with:
|
||||
java-version: 11
|
||||
distribution: liberica
|
||||
- name: Cache konan
|
||||
uses: actions/cache@v3.0.1
|
||||
with:
|
||||
path: ~/.konan
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- uses: gradle/gradle-build-action@v2.4.2
|
||||
with:
|
||||
arguments: dokkaHtmlMultiModule --no-parallel
|
||||
- uses: JamesIves/github-pages-deploy-action@v4.3.0
|
||||
with:
|
||||
branch: gh-pages
|
||||
folder: build/dokka/htmlMultiModule
|
50
.github/workflows/publish.yml
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
name: Gradle publish
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [ created ]
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
environment:
|
||||
name: publish
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ macOS-latest, windows-latest ]
|
||||
runs-on: ${{matrix.os}}
|
||||
steps:
|
||||
- uses: actions/checkout@v3.0.0
|
||||
- uses: actions/setup-java@v3.10.0
|
||||
with:
|
||||
java-version: 11
|
||||
distribution: liberica
|
||||
- name: Cache konan
|
||||
uses: actions/cache@v3.0.1
|
||||
with:
|
||||
path: ~/.konan
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Publish Windows Artifacts
|
||||
if: matrix.os == 'windows-latest'
|
||||
uses: gradle/gradle-build-action@v2.4.2
|
||||
with:
|
||||
arguments: |
|
||||
publishAllPublicationsToSpaceRepository
|
||||
-Ppublishing.targets=all
|
||||
-Ppublishing.space.user=${{ secrets.SPACE_APP_ID }}
|
||||
-Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }}
|
||||
- name: Publish Mac Artifacts
|
||||
if: matrix.os == 'macOS-latest'
|
||||
uses: gradle/gradle-build-action@v2.4.2
|
||||
with:
|
||||
arguments: |
|
||||
publishMacosX64PublicationToSpaceRepository
|
||||
publishMacosArm64PublicationToSpaceRepository
|
||||
publishIosX64PublicationToSpaceRepository
|
||||
publishIosArm64PublicationToSpaceRepository
|
||||
publishIosSimulatorArm64PublicationToSpaceRepository
|
||||
-Ppublishing.targets=all
|
||||
-Ppublishing.space.user=${{ secrets.SPACE_APP_ID }}
|
||||
-Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }}
|
117
.github/workflows/release.yml
vendored
@ -1,117 +0,0 @@
|
||||
name: Gradle release
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- created
|
||||
|
||||
jobs:
|
||||
build-ubuntu:
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Install Chrome
|
||||
run: |
|
||||
sudo apt install -y libappindicator1 fonts-liberation
|
||||
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
||||
sudo dpkg -i google-chrome*.deb
|
||||
- name: Cache gradle
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
.gradle
|
||||
build
|
||||
~/.gradle
|
||||
key: gradle
|
||||
restore-keys: gradle
|
||||
|
||||
- name: Cache konan
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.konan/dependencies
|
||||
~/.konan/kotlin-native-prebuilt-linux-*
|
||||
key: ${{ runner.os }}-konan
|
||||
restore-keys: ${{ runner.os }}-konan
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew -Dorg.gradle.daemon=false --build-cache build
|
||||
- name: Run release task
|
||||
run: ./gradlew release -PbintrayUser=${{ secrets.BINTRAY_USER }} -PbintrayApiKey=${{ secrets.BINTRAY_KEY }}
|
||||
|
||||
build-osx:
|
||||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Cache gradle
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
.gradle
|
||||
build
|
||||
~/.gradle
|
||||
key: gradle
|
||||
restore-keys: gradle
|
||||
|
||||
- name: Cache konan
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.konan/dependencies
|
||||
~/.konan/kotlin-native-prebuilt-macos-*
|
||||
key: ${{ runner.os }}-konan
|
||||
restore-keys: ${{ runner.os }}-konan
|
||||
- name: Build with Gradle
|
||||
run: sudo ./gradlew -Dorg.gradle.daemon=false --build-cache build
|
||||
- name: Run release task
|
||||
run: ./gradlew release -PbintrayUser=${{ secrets.BINTRAY_USER }} -PbintrayApiKey=${{ secrets.BINTRAY_KEY }}
|
||||
|
||||
build-windows:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Add msys to path
|
||||
run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"
|
||||
- name: Cache gradle
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
.gradle
|
||||
build
|
||||
~/.gradle
|
||||
key: ${{ runner.os }}-gradle
|
||||
restore-keys: ${{ runner.os }}-gradle
|
||||
|
||||
- name: Cache konan
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.konan/dependencies
|
||||
~/.konan/kotlin-native-prebuilt-mingw-*
|
||||
key: ${{ runner.os }}-konan
|
||||
restore-keys: ${{ runner.os }}-konan
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew --build-cache build
|
||||
- name: Run release task
|
||||
run: ./gradlew release -PbintrayUser=${{ secrets.BINTRAY_USER }} -PbintrayApiKey=${{ secrets.BINTRAY_KEY }}
|
||||
|
9
.gitignore
vendored
@ -1,8 +1,12 @@
|
||||
.gradle
|
||||
build/
|
||||
out/
|
||||
|
||||
.idea/
|
||||
.vscode/
|
||||
.fleet/
|
||||
.kotlin/
|
||||
|
||||
|
||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||
!gradle-wrapper.jar
|
||||
@ -13,3 +17,8 @@ out/
|
||||
# Generated by javac -h and runtime
|
||||
*.class
|
||||
*.log
|
||||
|
||||
!/.idea/copyright/
|
||||
!/.idea/scopes/
|
||||
/gradle/yarn.lock
|
||||
|
||||
|
7
.idea/copyright/kmath.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<component name="CopyrightManager">
|
||||
<copyright>
|
||||
<option name="allowReplaceRegexp" value="Copyright \d{4}-\d{4} KMath" />
|
||||
<option name="notice" value="Copyright 2018-&#36;today.year KMath contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file." />
|
||||
<option name="myName" value="kmath" />
|
||||
</copyright>
|
||||
</component>
|
21
.idea/copyright/profiles_settings.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<component name="CopyrightManager">
|
||||
<settings>
|
||||
<module2copyright>
|
||||
<element module="Apply copyright" copyright="kmath" />
|
||||
</module2copyright>
|
||||
<LanguageOptions name="Groovy">
|
||||
<option name="fileTypeOverride" value="1" />
|
||||
</LanguageOptions>
|
||||
<LanguageOptions name="HTML">
|
||||
<option name="fileTypeOverride" value="1" />
|
||||
<option name="prefixLines" value="false" />
|
||||
</LanguageOptions>
|
||||
<LanguageOptions name="Properties">
|
||||
<option name="fileTypeOverride" value="1" />
|
||||
</LanguageOptions>
|
||||
<LanguageOptions name="XML">
|
||||
<option name="fileTypeOverride" value="1" />
|
||||
<option name="prefixLines" value="false" />
|
||||
</LanguageOptions>
|
||||
</settings>
|
||||
</component>
|
3
.idea/scopes/Apply_copyright.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<component name="DependencyValidationManager">
|
||||
<scope name="Apply copyright" pattern="!file[*]:*//testData//*&&!file[*]:testData//*&&!file[*]:*.gradle.kts&&!file[*]:*.gradle&&!file[group:kotlin-ultimate]:*/&&!file[kotlin.libraries]:stdlib/api//*" />
|
||||
</component>
|
47
.space.kts
@ -1,3 +1,48 @@
|
||||
import kotlin.io.path.readText
|
||||
|
||||
val projectName = "kmath"
|
||||
|
||||
job("Build") {
|
||||
gradlew("openjdk:11", "build")
|
||||
//Perform only jvm tests
|
||||
gradlew("spc.registry.jetbrains.space/p/sci/containers/kotlin-ci:1.0.3", "test", "jvmTest")
|
||||
}
|
||||
|
||||
job("Publish") {
|
||||
startOn {
|
||||
gitPush { enabled = false }
|
||||
}
|
||||
container("spc.registry.jetbrains.space/p/sci/containers/kotlin-ci:1.0.3") {
|
||||
env["SPACE_USER"] = "{{ project:space_user }}"
|
||||
env["SPACE_TOKEN"] = "{{ project:space_token }}"
|
||||
kotlinScript { api ->
|
||||
|
||||
val spaceUser = System.getenv("SPACE_USER")
|
||||
val spaceToken = System.getenv("SPACE_TOKEN")
|
||||
|
||||
// write the version to the build directory
|
||||
api.gradlew("version")
|
||||
|
||||
//read the version from build file
|
||||
val version = java.nio.file.Path.of("build/project-version.txt").readText()
|
||||
|
||||
val revisionSuffix = if (version.endsWith("SNAPSHOT")) {
|
||||
"-" + api.gitRevision().take(7)
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
api.space().projects.automation.deployments.start(
|
||||
project = api.projectIdentifier(),
|
||||
targetIdentifier = TargetIdentifier.Key(projectName),
|
||||
version = version + revisionSuffix,
|
||||
// automatically update deployment status based on the status of a job
|
||||
syncWithAutomationJob = true
|
||||
)
|
||||
api.gradlew(
|
||||
"publishAllPublicationsToSpaceRepository",
|
||||
"-Ppublishing.space.user=\"$spaceUser\"",
|
||||
"-Ppublishing.space.token=\"$spaceToken\"",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
182
CHANGELOG.md
@ -1,6 +1,7 @@
|
||||
# KMath
|
||||
|
||||
## [Unreleased]
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
### Changed
|
||||
@ -13,8 +14,163 @@
|
||||
|
||||
### Security
|
||||
|
||||
## [0.2.0]
|
||||
## 0.4.0-dev-3 - 2024-02-18
|
||||
|
||||
### Added
|
||||
|
||||
- Reification. Explicit `SafeType` for algebras.
|
||||
- Integer division algebras.
|
||||
- Float32 geometries.
|
||||
- New Attributes-kt module that could be used as stand-alone. It declares. type-safe attributes containers.
|
||||
- Explicit `mutableStructureND` builders for mutable structures.
|
||||
- `Buffer.asList()` zero-copy transformation.
|
||||
- Wasm support.
|
||||
- Parallel implementation of `LinearSpace` for Float64
|
||||
- Parallel buffer factories
|
||||
|
||||
### Changed
|
||||
|
||||
- Buffer copy removed from API (added as an extension).
|
||||
- Default naming for algebra and buffers now uses IntXX/FloatXX notation instead of Java types.
|
||||
- Remove unnecessary inlines in basic algebras.
|
||||
- QuaternionField -> QuaternionAlgebra and does not implement `Field` anymore since it is non-commutative
|
||||
- kmath-geometry is split into `euclidean2d` and `euclidean3d`
|
||||
- Features replaced with Attributes.
|
||||
- Transposed refactored.
|
||||
- Kmath-memory is moved on top of core.
|
||||
|
||||
### Deprecated
|
||||
|
||||
- ND4J engine
|
||||
|
||||
### Removed
|
||||
|
||||
- `asPolynomial` function due to scope pollution
|
||||
- Codegend for ejml (450 lines of codegen for 1000 lines of code is too much)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Median statistics
|
||||
- Complex power of negative real numbers
|
||||
- Add proper mutability for MutableBufferND rows and columns
|
||||
- Generic Float32 and Float64 vectors are used in geometry algebras.
|
||||
|
||||
## 0.3.1 - 2023-04-09
|
||||
|
||||
### Added
|
||||
|
||||
- Wasm support for `memory`, `core`, `complex` and `functions` modules.
|
||||
- Generic builders for `BufferND` and `MutableBufferND`
|
||||
- `NamedMatrix` - matrix with symbol-based indexing
|
||||
- `Expression` with default arguments
|
||||
- Type-aliases for numbers like `Float64`
|
||||
- Autodiff for generic algebra elements in core!
|
||||
- Algebra now has an obligatory `bufferFactory` (#477).
|
||||
|
||||
### Changed
|
||||
|
||||
- Removed marker `Vector` type for geometry
|
||||
- Geometry uses type-safe angles
|
||||
- Tensor operations switched to prefix notation
|
||||
- Row-wise and column-wise ND shapes in the core
|
||||
- Shape is read-only
|
||||
- Major refactor of tensors (only minor API changes)
|
||||
- Kotlin 1.8.20
|
||||
- `LazyStructure` `deffered` -> `async` to comply with coroutines code style
|
||||
- Default `dot` operation in tensor algebra no longer support broadcasting. Instead `matmul` operation is added
|
||||
to `DoubleTensorAlgebra`.
|
||||
- Multik went MPP
|
||||
|
||||
### Removed
|
||||
|
||||
- Trajectory moved to https://github.com/SciProgCentre/maps-kt
|
||||
- Polynomials moved to https://github.com/SciProgCentre/kmath-polynomial
|
||||
|
||||
## 0.3.0
|
||||
|
||||
### Added
|
||||
|
||||
- `ScaleOperations` interface
|
||||
- `Field` extends `ScaleOperations`
|
||||
- Basic integration API
|
||||
- Basic MPP distributions and samplers
|
||||
- `bindSymbolOrNull`
|
||||
- Blocking chains and Statistics
|
||||
- Multiplatform integration
|
||||
- Integration for any Field element
|
||||
- Extended operations for ND4J fields
|
||||
- Jupyter Notebook integration module (kmath-jupyter)
|
||||
- `@PerformancePitfall` annotation to mark possibly slow API
|
||||
- Unified architecture for Integration and Optimization using features.
|
||||
- `BigInt` operation performance improvement and fixes by @zhelenskiy (#328)
|
||||
- Integration between `MST` and Symja `IExpr`
|
||||
- Complex power
|
||||
- Separate methods for UInt, Int and Number powers. NaN safety.
|
||||
- Tensorflow prototype
|
||||
- `ValueAndErrorField`
|
||||
- MST compilation to WASM: #286
|
||||
- Jafama integration: #176
|
||||
- `contentEquals` with tolerance: #364
|
||||
- Compilation to TeX for MST: #254
|
||||
|
||||
### Changed
|
||||
|
||||
- Annotations moved to `space.kscience.kmath`
|
||||
- Exponential operations merged with hyperbolic functions
|
||||
- Space is replaced by Group. Space is reserved for vector spaces.
|
||||
- VectorSpace is now a vector space
|
||||
- Buffer factories for primitives moved to MutableBuffer.Companion
|
||||
- Rename `NDStructure` and `NDAlgebra` to `StructureND` and `AlgebraND` respectively
|
||||
- `Real` -> `Double`
|
||||
- DataSets are moved from functions to core
|
||||
- Redesign advanced Chain API
|
||||
- Redesign `MST`. Remove `MstExpression`.
|
||||
- Move `MST` to core
|
||||
- Separated benchmarks and examples
|
||||
- Rewrite `kmath-ejml` without `ejml-simple` artifact, support sparse matrices
|
||||
- Promote stability of kmath-ast and kmath-kotlingrad to EXPERIMENTAL.
|
||||
- ColumnarData returns nullable column
|
||||
- `MST` is made sealed interface
|
||||
- Replace `MST.Symbolic` by `Symbol`, `Symbol` now implements MST
|
||||
- Remove Any restriction on polynomials
|
||||
- Add `out` variance to type parameters of `StructureND` and its implementations where possible
|
||||
- Rename `DifferentiableMstExpression` to `KotlingradExpression`
|
||||
- `FeatureSet` now accepts only `Feature`. It is possible to override keys and use interfaces.
|
||||
- Use `Symbol` factory function instead of `StringSymbol`
|
||||
- New discoverability pattern: `<Type>.algebra.<nd/etc>`
|
||||
- Adjusted commons-math API for linear solvers to match conventions.
|
||||
- Buffer algebra does not require size anymore
|
||||
- Operations -> Ops
|
||||
- Default Buffer and ND algebras are now Ops and lack neutral elements (0, 1) as well as algebra-level shapes.
|
||||
- Tensor algebra takes read-only structures as input and inherits AlgebraND
|
||||
- `UnivariateDistribution` renamed to `Distribution1D`
|
||||
- Rework of histograms.
|
||||
- `UnivariateFunction` -> `Function1D`, `MultivariateFunction` -> `FunctionND`
|
||||
|
||||
### Deprecated
|
||||
|
||||
- Specialized `DoubleBufferAlgebra`
|
||||
|
||||
### Removed
|
||||
|
||||
- Nearest in Domain. To be implemented in geometry package.
|
||||
- Number multiplication and division in main Algebra chain
|
||||
- `contentEquals` from Buffer. It moved to the companion.
|
||||
- MSTExpression
|
||||
- Expression algebra builders
|
||||
- Complex and Quaternion no longer are elements.
|
||||
- Second generic from DifferentiableExpression
|
||||
- Algebra elements are completely removed. Use algebra contexts instead.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Ring inherits RingOperations, not GroupOperations
|
||||
- Univariate histogram filling
|
||||
|
||||
## 0.2.0
|
||||
|
||||
### Added
|
||||
|
||||
- `fun` annotation for SAM interfaces in library
|
||||
- Explicit `public` visibility for all public APIs
|
||||
- Better trigonometric and hyperbolic functions for `AutoDiffField` (https://github.com/mipt-npm/kmath/pull/140)
|
||||
@ -34,6 +190,7 @@
|
||||
- Basic Quaternion vector support in `kmath-complex`.
|
||||
|
||||
### Changed
|
||||
|
||||
- Package changed from `scientifik` to `space.kscience`
|
||||
- Gradle version: 6.6 -> 6.8.2
|
||||
- Minor exceptions refactor (throwing `IllegalArgumentException` by argument checks instead of `IllegalStateException`)
|
||||
@ -57,32 +214,34 @@
|
||||
- `symbol` method in `Algebra` renamed to `bindSymbol` to avoid ambiguity
|
||||
- Add `out` projection to `Buffer` generic
|
||||
|
||||
### Deprecated
|
||||
|
||||
### Removed
|
||||
|
||||
- `kmath-koma` module because it doesn't support Kotlin 1.4.
|
||||
- Support of `legacy` JS backend (we will support only IR)
|
||||
- `toGrid` method.
|
||||
- Public visibility of `BufferAccessor2D`
|
||||
- `Real` class
|
||||
- StructureND identity and equals
|
||||
|
||||
### Fixed
|
||||
|
||||
- `symbol` method in `MstExtendedField` (https://github.com/mipt-npm/kmath/pull/140)
|
||||
|
||||
### Security
|
||||
|
||||
## [0.1.4]
|
||||
## 0.1.4
|
||||
|
||||
### Added
|
||||
|
||||
- Functional Expressions API
|
||||
- Mathematical Syntax Tree, its interpreter and API
|
||||
- String to MST parser (https://github.com/mipt-npm/kmath/pull/120)
|
||||
- MST to JVM bytecode translator (https://github.com/mipt-npm/kmath/pull/94)
|
||||
- FloatBuffer (specialized MutableBuffer over FloatArray)
|
||||
- FlaggedBuffer to associate primitive numbers buffer with flags (to mark values infinite or missing, etc.)
|
||||
- Specialized builder functions for all primitive buffers like `IntBuffer(25) { it + 1 }` (https://github.com/mipt-npm/kmath/pull/125)
|
||||
- Specialized builder functions for all primitive buffers
|
||||
like `IntBuffer(25) { it + 1 }` (https://github.com/mipt-npm/kmath/pull/125)
|
||||
- Interface `NumericAlgebra` where `number` operation is available to convert numbers to algebraic elements
|
||||
- Inverse trigonometric functions support in ExtendedField (`asin`, `acos`, `atan`) (https://github.com/mipt-npm/kmath/pull/114)
|
||||
- Inverse trigonometric functions support in
|
||||
ExtendedField (`asin`, `acos`, `atan`) (https://github.com/mipt-npm/kmath/pull/114)
|
||||
- New space extensions: `average` and `averageWith`
|
||||
- Local coding conventions
|
||||
- Geometric Domains API in `kmath-core`
|
||||
@ -91,10 +250,12 @@
|
||||
- Norm support for `Complex`
|
||||
|
||||
### Changed
|
||||
|
||||
- `readAsMemory` now has `throws IOException` in JVM signature.
|
||||
- Several functions taking functional types were made `inline`.
|
||||
- Several functions taking functional types now have `callsInPlace` contracts.
|
||||
- BigInteger and BigDecimal algebra: JBigDecimalField has companion object with default math context; minor optimizations
|
||||
- BigInteger and BigDecimal algebra: JBigDecimalField has companion object with default math context; minor
|
||||
optimizations
|
||||
- `power(T, Int)` extension function has preconditions and supports `Field<T>`
|
||||
- Memory objects have more preconditions (overflow checking)
|
||||
- `tg` function is renamed to `tan` (https://github.com/mipt-npm/kmath/pull/114)
|
||||
@ -102,6 +263,7 @@
|
||||
- Moved probability distributions to commons-rng and to `kmath-prob`
|
||||
|
||||
### Fixed
|
||||
|
||||
- Missing copy method in Memory implementation on JS (https://github.com/mipt-npm/kmath/pull/106)
|
||||
- D3.dim value in `kmath-dimensions`
|
||||
- Multiplication in integer rings in `kmath-core` (https://github.com/mipt-npm/kmath/pull/101)
|
||||
|
319
README.md
@ -1,254 +1,284 @@
|
||||
[![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
|
||||
[![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382)
|
||||
|
||||
![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg)
|
||||
|
||||
Bintray: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion)
|
||||
|
||||
Bintray-dev: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion)
|
||||
![Gradle build](https://github.com/SciProgCentre/kmath/workflows/Gradle%20build/badge.svg)
|
||||
[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22)
|
||||
[![Space](https://img.shields.io/badge/dynamic/xml?color=orange&label=Space&query=//metadata/versioning/latest&url=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/)
|
||||
|
||||
# KMath
|
||||
|
||||
Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based analog to
|
||||
Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior architecture
|
||||
designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could
|
||||
be achieved with [kmath-for-real](/kmath-for-real) extension module.
|
||||
Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based
|
||||
analog to Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior
|
||||
architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like
|
||||
experience could be achieved with [kmath-for-real](/kmath-for-real) extension module.
|
||||
|
||||
[Documentation site](https://SciProgCentre.github.io/kmath/)
|
||||
|
||||
## Publications and talks
|
||||
|
||||
* [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2)
|
||||
* [Another article about context-oriented design](https://proandroiddev.com/diving-deeper-into-context-oriented-programming-in-kotlin-3ecb4ec38814)
|
||||
* [ACAT 2019 conference paper](https://aip.scitation.org/doi/abs/10.1063/1.5130103)
|
||||
* [A talk at KotlinConf 2019 about using kotlin for science](https://youtu.be/LI_5TZ7tnOE?si=4LknX41gl_YeUbIe)
|
||||
* [A talk on architecture at Joker-2021 (in Russian)](https://youtu.be/1bZ2doHiRRM?si=9w953ro9yu98X_KJ)
|
||||
* [The same talk in English](https://youtu.be/yP5DIc2fVwQ?si=louZzQ1dcXV6gP10)
|
||||
* [A seminar on tensor API](https://youtu.be/0H99wUs0xTM?si=6c__04jrByFQtVpo)
|
||||
|
||||
# Goal
|
||||
|
||||
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native).
|
||||
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS, Native and
|
||||
Wasm).
|
||||
* Provide basic multiplatform implementations for those abstractions (without significant performance optimization).
|
||||
* Provide bindings and wrappers with those abstractions for popular optimized platform libraries.
|
||||
|
||||
## Non-goals
|
||||
|
||||
* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in terms of API.
|
||||
* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in API.
|
||||
* Provide the best performance out of the box. We have specialized libraries for that. Need only API wrappers for them.
|
||||
* Cover all cases as immediately and in one bundle. We will modularize everything and add new features gradually.
|
||||
* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like
|
||||
for `Double` in the core. For that we will have specialization modules like `kmath-for-real`, which will give better
|
||||
experience for those, who want to work with specific types.
|
||||
* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like
|
||||
for `Double` in the core. For that we will have specialization modules like `kmath-for-real`, which will give better
|
||||
experience for those, who want to work with specific types.
|
||||
|
||||
## Features and stability
|
||||
|
||||
KMath is a modular library. Different modules provide different features with different API stability guarantees. All core modules are released with the same version, but with different API change policy. The features are described in module definitions below. The module stability could have following levels:
|
||||
KMath is a modular library. Different modules provide different features with different API stability guarantees. All
|
||||
core modules are released with the same version, but with different API change policy. The features are described in
|
||||
module definitions below. The module stability could have the following levels:
|
||||
|
||||
* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could break any moment. You can still use it, but be sure to fix the specific version.
|
||||
* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked with `@UnstableKmathAPI` or other stability warning annotations.
|
||||
* **DEVELOPMENT**. API breaking genrally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
|
||||
* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could
|
||||
break any moment. You can still use it, but be sure to fix the specific version.
|
||||
* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked
|
||||
with `@UnstableKMathAPI` or other stability warning annotations.
|
||||
* **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor
|
||||
versions, but not in patch versions. API is protected
|
||||
with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
|
||||
* **STABLE**. The API stabilized. Breaking changes are allowed only in major releases.
|
||||
|
||||
<!--Current feature list is [here](/docs/features.md)-->
|
||||
|
||||
|
||||
<!--* **Array-like structures** Full support of many-dimensional array-like structures -->
|
||||
<!--including mixed arithmetic operations and function operations over arrays and numbers (with the added benefit of static type checking).-->
|
||||
|
||||
<!--* **Histograms** Fast multi-dimensional histograms.-->
|
||||
|
||||
<!--* **Streaming** Streaming operations on mathematical objects and objects buffers.-->
|
||||
|
||||
<!--* **Type-safe dimensions** Type-safe dimensions for matrix operations.-->
|
||||
|
||||
<!--* **Commons-math wrapper** It is planned to gradually wrap most parts of -->
|
||||
<!--[Apache commons-math](http://commons.apache.org/proper/commons-math/) library in Kotlin code and maybe rewrite some -->
|
||||
<!--parts to better suit the Kotlin programming paradigm, however there is no established roadmap for that. Feel free to -->
|
||||
<!--submit a feature request if you want something to be implemented first.-->
|
||||
<!-- -->
|
||||
<!--## Planned features-->
|
||||
|
||||
<!--* **Messaging** A mathematical notation to support multi-language and multi-node communication for mathematical tasks.-->
|
||||
|
||||
<!--* **Array statistics** -->
|
||||
|
||||
<!--* **Integration** Univariate and multivariate integration framework.-->
|
||||
|
||||
<!--* **Probability and distributions**-->
|
||||
|
||||
<!--* **Fitting** Non-linear curve fitting facilities-->
|
||||
|
||||
## Modules
|
||||
|
||||
<hr/>
|
||||
|
||||
* ### [examples](examples)
|
||||
>
|
||||
### [attributes-kt](attributes-kt)
|
||||
> An API and basic implementation for arranging objects in a continuous memory block.
|
||||
>
|
||||
> **Maturity**: DEVELOPMENT
|
||||
|
||||
### [benchmarks](benchmarks)
|
||||
>
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-ast](kmath-ast)
|
||||
>
|
||||
### [examples](examples)
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
|
||||
### [kmath-ast](kmath-ast)
|
||||
>
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
>
|
||||
> **Features:**
|
||||
> - [expression-language](kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt) : Expression language and its parser
|
||||
> - [mst](kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation
|
||||
> - [mst-building](kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure
|
||||
> - [mst-interpreter](kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST interpreter
|
||||
> - [mst-jvm-codegen](kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler
|
||||
> - [mst-js-codegen](kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler
|
||||
> - [expression-language](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
|
||||
> - [mst-jvm-codegen](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler
|
||||
> - [mst-js-codegen](kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler
|
||||
> - [rendering](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt) : Extendable MST rendering
|
||||
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-commons](kmath-commons)
|
||||
>
|
||||
### [kmath-commons](kmath-commons)
|
||||
> Commons math binding for kmath
|
||||
>
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-complex](kmath-complex)
|
||||
### [kmath-complex](kmath-complex)
|
||||
> Complex numbers and quaternions.
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
>
|
||||
> **Features:**
|
||||
> - [complex](kmath-complex/src/commonMain/kotlin/kscience/kmath/complex/Complex.kt) : Complex Numbers
|
||||
> - [quaternion](kmath-complex/src/commonMain/kotlin/kscience/kmath/complex/Quaternion.kt) : Quaternions
|
||||
> - [complex](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex numbers operations
|
||||
> - [quaternion](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions and their composition
|
||||
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-core](kmath-core)
|
||||
### [kmath-core](kmath-core)
|
||||
> Core classes, algebra definitions, basic linear algebra
|
||||
>
|
||||
> **Maturity**: DEVELOPMENT
|
||||
>
|
||||
> **Features:**
|
||||
> - [algebras](kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields.
|
||||
> - [nd](kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Many-dimensional structures and operations on them.
|
||||
> - [linear](kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. Advanced linear algebra operations like matrix inversion and LU decomposition.
|
||||
> - [buffers](kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : One-dimensional structure
|
||||
> - [expressions](kmath-core/src/commonMain/kotlin/kscience/kmath/expressions) : By writing a single mathematical expression once, users will be able to apply different types of
|
||||
> - [algebras](kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields.
|
||||
> - [nd](kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/StructureND.kt) : Many-dimensional structures and operations on them.
|
||||
> - [linear](kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. Advanced linear algebra operations like matrix inversion and LU decomposition.
|
||||
> - [buffers](kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffers.kt) : One-dimensional structure
|
||||
> - [expressions](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions) : By writing a single mathematical expression once, users will be able to apply different types of
|
||||
objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high
|
||||
performance calculations to code generation.
|
||||
> - [domains](kmath-core/src/commonMain/kotlin/kscience/kmath/domains) : Domains
|
||||
> - [autodif](kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
|
||||
> - [domains](kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains) : Domains
|
||||
> - [autodiff](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
|
||||
> - [Parallel linear algebra](kmath-core/#) : Parallel implementation for `LinearAlgebra`
|
||||
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-coroutines](kmath-coroutines)
|
||||
>
|
||||
### [kmath-coroutines](kmath-coroutines)
|
||||
>
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-dimensions](kmath-dimensions)
|
||||
>
|
||||
### [kmath-dimensions](kmath-dimensions)
|
||||
> A proof of concept module for adding type-safe dimensions to structures
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-ejml](kmath-ejml)
|
||||
>
|
||||
### [kmath-ejml](kmath-ejml)
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
<hr/>
|
||||
>
|
||||
> **Features:**
|
||||
> - [ejml-vector](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : Point implementations.
|
||||
> - [ejml-matrix](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : Matrix implementation.
|
||||
> - [ejml-linear-space](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : LinearSpace implementations.
|
||||
|
||||
* ### [kmath-for-real](kmath-for-real)
|
||||
> Extension module that should be used to achieve numpy-like behavior.
|
||||
|
||||
### [kmath-for-real](kmath-for-real)
|
||||
> Extension module that should be used to achieve numpy-like behavior.
|
||||
All operations are specialized to work with `Double` numbers without declaring algebraic contexts.
|
||||
One can still use generic algebras though.
|
||||
>
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
>
|
||||
> **Features:**
|
||||
> - [RealVector](kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt) : Numpy-like operations for Buffers/Points
|
||||
> - [RealMatrix](kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt) : Numpy-like operations for 2d real structures
|
||||
> - [grids](kmath-for-real/src/commonMain/kotlin/kscience/kmath/structures/grids.kt) : Uniform grid generators
|
||||
> - [DoubleVector](kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt) : Numpy-like operations for Buffers/Points
|
||||
> - [DoubleMatrix](kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleMatrix.kt) : Numpy-like operations for 2d real structures
|
||||
> - [grids](kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/structures/grids.kt) : Uniform grid generators
|
||||
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-functions](kmath-functions)
|
||||
> Functions and interpolation
|
||||
### [kmath-functions](kmath-functions)
|
||||
> Functions, integration and interpolation
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
>
|
||||
> **Features:**
|
||||
> - [piecewise](kmath-functions/Piecewise functions.) : src/commonMain/kotlin/kscience/kmath/functions/Piecewise.kt
|
||||
> - [polynomials](kmath-functions/Polynomial functions.) : src/commonMain/kotlin/kscience/kmath/functions/Polynomial.kt
|
||||
> - [linear interpolation](kmath-functions/Linear XY interpolator.) : src/commonMain/kotlin/kscience/kmath/interpolation/LinearInterpolator.kt
|
||||
> - [spline interpolation](kmath-functions/Cubic spline XY interpolator.) : src/commonMain/kotlin/kscience/kmath/interpolation/SplineInterpolator.kt
|
||||
> - [piecewise](kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt) : Piecewise functions.
|
||||
> - [polynomials](kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt) : Polynomial functions.
|
||||
> - [linear interpolation](kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt) : Linear XY interpolator.
|
||||
> - [spline interpolation](kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt) : Cubic spline XY interpolator.
|
||||
> - [integration](kmath-functions/#) : Univariate and multivariate quadratures
|
||||
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-geometry](kmath-geometry)
|
||||
>
|
||||
### [kmath-geometry](kmath-geometry)
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-histograms](kmath-histograms)
|
||||
>
|
||||
### [kmath-histograms](kmath-histograms)
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-kotlingrad](kmath-kotlingrad)
|
||||
>
|
||||
### [kmath-jafama](kmath-jafama)
|
||||
> Jafama integration module
|
||||
>
|
||||
> **Maturity**: DEPRECATED
|
||||
>
|
||||
> **Features:**
|
||||
> - [jafama-double](kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/) : Double ExtendedField implementations based on Jafama
|
||||
|
||||
|
||||
### [kmath-jupyter](kmath-jupyter)
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-memory](kmath-memory)
|
||||
> An API and basic implementation for arranging objects in a continous memory block.
|
||||
### [kmath-kotlingrad](kmath-kotlingrad)
|
||||
> Kotlin∇ integration module
|
||||
>
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
>
|
||||
> **Features:**
|
||||
> - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt) : MST based DifferentiableExpression.
|
||||
> - [scalars-adapters](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/scalarsAdapters.kt) : Conversions between Kotlin∇'s SFun and MST
|
||||
|
||||
|
||||
### [kmath-memory](kmath-memory)
|
||||
> An API and basic implementation for arranging objects in a continuous memory block.
|
||||
>
|
||||
> **Maturity**: DEVELOPMENT
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-nd4j](kmath-nd4j)
|
||||
### [kmath-multik](kmath-multik)
|
||||
> JetBrains Multik connector
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
|
||||
### [kmath-nd4j](kmath-nd4j)
|
||||
> ND4J NDStructure implementation and according NDAlgebra classes
|
||||
>
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
> **Maturity**: DEPRECATED
|
||||
>
|
||||
> **Features:**
|
||||
> - [nd4jarraystructure](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : NDStructure wrapper for INDArray
|
||||
> - [nd4jarrayrings](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Rings over Nd4jArrayStructure of Int and Long
|
||||
> - [nd4jarrayfields](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : Fields over Nd4jArrayStructure of Float and Double
|
||||
> - [nd4jarraystructure](kmath-nd4j/#) : NDStructure wrapper for INDArray
|
||||
> - [nd4jarrayrings](kmath-nd4j/#) : Rings over Nd4jArrayStructure of Int and Long
|
||||
> - [nd4jarrayfields](kmath-nd4j/#) : Fields over Nd4jArrayStructure of Float and Double
|
||||
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-stat](kmath-stat)
|
||||
>
|
||||
### [kmath-optimization](kmath-optimization)
|
||||
>
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-viktor](kmath-viktor)
|
||||
>
|
||||
### [kmath-stat](kmath-stat)
|
||||
>
|
||||
> **Maturity**: DEVELOPMENT
|
||||
<hr/>
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
|
||||
### [kmath-symja](kmath-symja)
|
||||
> Symja integration module
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
|
||||
### [kmath-tensorflow](kmath-tensorflow)
|
||||
> Google tensorflow connector
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
|
||||
### [kmath-tensors](kmath-tensors)
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
>
|
||||
> **Features:**
|
||||
> - [tensor algebra](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.)
|
||||
> - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting.
|
||||
> - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc.
|
||||
|
||||
|
||||
### [kmath-viktor](kmath-viktor)
|
||||
> Binding for https://github.com/JetBrains-Research/viktor
|
||||
>
|
||||
> **Maturity**: DEPRECATED
|
||||
|
||||
### [test-utils](test-utils)
|
||||
>
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
|
||||
|
||||
## Multi-platform support
|
||||
|
||||
KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the
|
||||
[common source sets](/kmath-core/src/commonMain) and implemented there wherever it is possible. In some cases, features
|
||||
are delegated to platform-specific implementations even if they could be provided in the common module for performance
|
||||
reasons. Currently, the Kotlin/JVM is the primary platform, however Kotlin/Native and Kotlin/JS contributions and
|
||||
KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the
|
||||
[common source sets](/kmath-core/src/commonMain) and implemented there wherever it is possible. In some cases, features
|
||||
are delegated to platform-specific implementations even if they could be provided in the common module for performance
|
||||
reasons. Currently, Kotlin/JVM is the primary platform, however, Kotlin/Native and Kotlin/JS contributions and
|
||||
feedback are also welcome.
|
||||
|
||||
## Performance
|
||||
|
||||
Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve
|
||||
both performance and flexibility.
|
||||
Calculation of performance is one of the major goals of KMath in the future, but in some cases it is impossible to
|
||||
achieve both
|
||||
performance and flexibility.
|
||||
|
||||
We expect to focus on creating convenient universal API first and then work on increasing performance for specific
|
||||
cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized
|
||||
native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be
|
||||
We expect to focus on creating a convenient universal API first and then work on increasing performance for specific
|
||||
cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized
|
||||
native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be
|
||||
better than SciPy.
|
||||
|
||||
## Requirements
|
||||
|
||||
KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend using GraalVM-CE or
|
||||
Oracle GraalVM for execution to get better performance.
|
||||
|
||||
### Repositories
|
||||
|
||||
Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/) repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
|
||||
[Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) for more details). The repository could be reached through [repo.kotlin.link](https://repo.kotlin.link) proxy:
|
||||
Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/)
|
||||
repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
|
||||
[Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) for more details). The repository could
|
||||
be reached through [repo.kotlin.link](https://repo.kotlin.link) proxy:
|
||||
|
||||
```kotlin
|
||||
repositories {
|
||||
@ -256,16 +286,15 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api("kscience.kmath:kmath-core:() -> kotlin.Any")
|
||||
// api("kscience.kmath:kmath-core-jvm:() -> kotlin.Any") for jvm-specific version
|
||||
api("space.kscience:kmath-core:$version")
|
||||
// api("space.kscience:kmath-core-jvm:$version") for jvm-specific version
|
||||
}
|
||||
```
|
||||
|
||||
Gradle `6.0+` is required for multiplatform artifacts.
|
||||
|
||||
## Contributing
|
||||
|
||||
The project requires a lot of additional work. The most important thing we need is a feedback about what features are
|
||||
required the most. Feel free to create feature requests. We are also welcome to code contributions,
|
||||
especially in issues marked with
|
||||
[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label.
|
||||
The project requires a lot of additional work. The most important thing we need is feedback about what features are
|
||||
required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues
|
||||
marked
|
||||
with [good first issue](hhttps://github.com/SciProgCentre/kmath/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
|
||||
label.
|
21
attributes-kt/README.md
Normal file
@ -0,0 +1,21 @@
|
||||
# Module attributes-kt
|
||||
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
## Artifact:
|
||||
|
||||
The Maven coordinates of this project are `space.kscience:attributes-kt:0.1.0`.
|
||||
|
||||
**Gradle Kotlin DSL:**
|
||||
```kotlin
|
||||
repositories {
|
||||
maven("https://repo.kotlin.link")
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("space.kscience:attributes-kt:0.1.0")
|
||||
}
|
||||
```
|
104
attributes-kt/api/attributes-kt.api
Normal file
@ -0,0 +1,104 @@
|
||||
public abstract interface class space/kscience/attributes/Attribute {
|
||||
}
|
||||
|
||||
public abstract interface class space/kscience/attributes/AttributeContainer {
|
||||
public abstract fun getAttributes ()Lspace/kscience/attributes/Attributes;
|
||||
}
|
||||
|
||||
public abstract interface class space/kscience/attributes/AttributeScope {
|
||||
}
|
||||
|
||||
public abstract interface class space/kscience/attributes/AttributeWithDefault : space/kscience/attributes/Attribute {
|
||||
public abstract fun getDefault ()Ljava/lang/Object;
|
||||
}
|
||||
|
||||
public abstract interface class space/kscience/attributes/Attributes {
|
||||
public static final field Companion Lspace/kscience/attributes/Attributes$Companion;
|
||||
public abstract fun equals (Ljava/lang/Object;)Z
|
||||
public fun get (Lspace/kscience/attributes/Attribute;)Ljava/lang/Object;
|
||||
public abstract fun getContent ()Ljava/util/Map;
|
||||
public fun getKeys ()Ljava/util/Set;
|
||||
public abstract fun hashCode ()I
|
||||
public abstract fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class space/kscience/attributes/Attributes$Companion {
|
||||
public final fun equals (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/Attributes;)Z
|
||||
public final fun getEMPTY ()Lspace/kscience/attributes/Attributes;
|
||||
}
|
||||
|
||||
public final class space/kscience/attributes/AttributesBuilder : space/kscience/attributes/Attributes {
|
||||
public final fun add (Lspace/kscience/attributes/SetAttribute;Ljava/lang/Object;)V
|
||||
public final fun build ()Lspace/kscience/attributes/Attributes;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public fun getContent ()Ljava/util/Map;
|
||||
public fun hashCode ()I
|
||||
public final fun invoke (Lspace/kscience/attributes/Attribute;Ljava/lang/Object;)V
|
||||
public final fun put (Lspace/kscience/attributes/Attribute;Ljava/lang/Object;)V
|
||||
public final fun putAll (Lspace/kscience/attributes/Attributes;)V
|
||||
public final fun remove (Lspace/kscience/attributes/SetAttribute;Ljava/lang/Object;)V
|
||||
public final fun set (Lspace/kscience/attributes/Attribute;Ljava/lang/Object;)V
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class space/kscience/attributes/AttributesBuilderKt {
|
||||
public static final fun Attributes (Lkotlin/jvm/functions/Function1;)Lspace/kscience/attributes/Attributes;
|
||||
}
|
||||
|
||||
public final class space/kscience/attributes/AttributesKt {
|
||||
public static final fun Attributes (Lspace/kscience/attributes/Attribute;)Lspace/kscience/attributes/Attributes;
|
||||
public static final fun Attributes (Lspace/kscience/attributes/Attribute;Ljava/lang/Object;)Lspace/kscience/attributes/Attributes;
|
||||
public static final fun getOrDefault (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/AttributeWithDefault;)Ljava/lang/Object;
|
||||
public static final fun isEmpty (Lspace/kscience/attributes/Attributes;)Z
|
||||
public static final fun modified (Lspace/kscience/attributes/Attributes;Lkotlin/jvm/functions/Function1;)Lspace/kscience/attributes/Attributes;
|
||||
public static final fun plus (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/Attributes;)Lspace/kscience/attributes/Attributes;
|
||||
public static final fun withAttribute (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/Attribute;)Lspace/kscience/attributes/Attributes;
|
||||
public static final fun withAttribute (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/Attribute;Ljava/lang/Object;)Lspace/kscience/attributes/Attributes;
|
||||
public static final fun withAttributeElement (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/SetAttribute;Ljava/lang/Object;)Lspace/kscience/attributes/Attributes;
|
||||
public static final fun withoutAttribute (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/Attribute;)Lspace/kscience/attributes/Attributes;
|
||||
public static final fun withoutAttributeElement (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/SetAttribute;Ljava/lang/Object;)Lspace/kscience/attributes/Attributes;
|
||||
}
|
||||
|
||||
public abstract interface class space/kscience/attributes/FlagAttribute : space/kscience/attributes/Attribute {
|
||||
}
|
||||
|
||||
public abstract class space/kscience/attributes/PolymorphicAttribute : space/kscience/attributes/Attribute {
|
||||
public synthetic fun <init> (Lkotlin/reflect/KType;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getType-V0oMfBY ()Lkotlin/reflect/KType;
|
||||
public fun hashCode ()I
|
||||
}
|
||||
|
||||
public final class space/kscience/attributes/PolymorphicAttributeKt {
|
||||
public static final fun get (Lspace/kscience/attributes/Attributes;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;
|
||||
public static final fun set (Lspace/kscience/attributes/AttributesBuilder;Lkotlin/jvm/functions/Function0;Ljava/lang/Object;)V
|
||||
}
|
||||
|
||||
public final class space/kscience/attributes/SafeType {
|
||||
public static final synthetic fun box-impl (Lkotlin/reflect/KType;)Lspace/kscience/attributes/SafeType;
|
||||
public static fun constructor-impl (Lkotlin/reflect/KType;)Lkotlin/reflect/KType;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public static fun equals-impl (Lkotlin/reflect/KType;Ljava/lang/Object;)Z
|
||||
public static final fun equals-impl0 (Lkotlin/reflect/KType;Lkotlin/reflect/KType;)Z
|
||||
public final fun getKType ()Lkotlin/reflect/KType;
|
||||
public fun hashCode ()I
|
||||
public static fun hashCode-impl (Lkotlin/reflect/KType;)I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
public static fun toString-impl (Lkotlin/reflect/KType;)Ljava/lang/String;
|
||||
public final synthetic fun unbox-impl ()Lkotlin/reflect/KType;
|
||||
}
|
||||
|
||||
public final class space/kscience/attributes/SafeTypeKt {
|
||||
public static final fun getKClass-X0YbwmU (Lkotlin/reflect/KType;)Lkotlin/reflect/KClass;
|
||||
}
|
||||
|
||||
public abstract interface class space/kscience/attributes/SetAttribute : space/kscience/attributes/Attribute {
|
||||
}
|
||||
|
||||
public abstract interface annotation class space/kscience/attributes/UnstableAttributesAPI : java/lang/annotation/Annotation {
|
||||
}
|
||||
|
||||
public abstract interface class space/kscience/attributes/WithType {
|
||||
public abstract fun getType-V0oMfBY ()Lkotlin/reflect/KType;
|
||||
}
|
||||
|
20
attributes-kt/build.gradle.kts
Normal file
@ -0,0 +1,20 @@
|
||||
plugins {
|
||||
id("space.kscience.gradle.mpp")
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
version = rootProject.extra.get("attributesVersion").toString()
|
||||
|
||||
kscience {
|
||||
jvm()
|
||||
js()
|
||||
native()
|
||||
wasm()
|
||||
}
|
||||
|
||||
readme {
|
||||
maturity = space.kscience.gradle.Maturity.DEVELOPMENT
|
||||
description = """
|
||||
An API and basic implementation for arranging objects in a continuous memory block.
|
||||
""".trimIndent()
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2018-2023 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.attributes
|
||||
|
||||
/**
|
||||
* A marker interface for an attribute. Attributes are used as keys to access contents of type [T] in the container.
|
||||
*/
|
||||
public interface Attribute<T>
|
||||
|
||||
/**
|
||||
* An attribute that could be either present or absent
|
||||
*/
|
||||
public interface FlagAttribute : Attribute<Unit>
|
||||
|
||||
/**
|
||||
* An attribute with a default value
|
||||
*/
|
||||
public interface AttributeWithDefault<T> : Attribute<T> {
|
||||
public val default: T
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute containing a set of values
|
||||
*/
|
||||
public interface SetAttribute<V> : Attribute<Set<V>>
|
||||
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2018-2023 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.attributes
|
||||
|
||||
/**
|
||||
* A container for [Attributes]
|
||||
*/
|
||||
public interface AttributeContainer {
|
||||
public val attributes: Attributes
|
||||
}
|
||||
|
||||
/**
|
||||
* A scope, where attribute keys could be resolved.
|
||||
* [O] is used only to resolve types in compile-time.
|
||||
*/
|
||||
public interface AttributeScope<O>
|
||||
|
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 2018-2023 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.attributes
|
||||
|
||||
/**
|
||||
* A set of attributes. The implementation must guarantee that [content] keys correspond to their value types.
|
||||
*/
|
||||
public interface Attributes {
|
||||
/**
|
||||
* Raw content for this [Attributes]
|
||||
*/
|
||||
public val content: Map<out Attribute<*>, Any?>
|
||||
|
||||
/**
|
||||
* Attribute keys contained in this [Attributes]
|
||||
*/
|
||||
public val keys: Set<Attribute<*>> get() = content.keys
|
||||
|
||||
/**
|
||||
* Provide an attribute value. Return null if attribute is not present or if its value is null.
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public operator fun <T> get(attribute: Attribute<T>): T? = content[attribute] as? T
|
||||
|
||||
override fun toString(): String
|
||||
override fun equals(other: Any?): Boolean
|
||||
override fun hashCode(): Int
|
||||
|
||||
public companion object {
|
||||
public val EMPTY: Attributes = object : Attributes {
|
||||
override val content: Map<out Attribute<*>, Any?> get() = emptyMap()
|
||||
|
||||
override fun toString(): String = "Attributes.EMPTY"
|
||||
|
||||
override fun equals(other: Any?): Boolean = (other as? Attributes)?.isEmpty() ?: false
|
||||
|
||||
override fun hashCode(): Int = Unit.hashCode()
|
||||
}
|
||||
|
||||
public fun equals(a1: Attributes, a2: Attributes): Boolean =
|
||||
a1.keys == a2.keys && a1.keys.all { a1[it] == a2[it] }
|
||||
}
|
||||
}
|
||||
|
||||
internal class MapAttributes(override val content: Map<out Attribute<*>, Any?>) : Attributes {
|
||||
override fun toString(): String = "Attributes(value=${content.entries})"
|
||||
override fun equals(other: Any?): Boolean = other is Attributes && Attributes.equals(this, other)
|
||||
override fun hashCode(): Int = content.hashCode()
|
||||
}
|
||||
|
||||
public fun Attributes.isEmpty(): Boolean = keys.isEmpty()
|
||||
|
||||
/**
|
||||
* Get attribute value or default
|
||||
*/
|
||||
public fun <T> Attributes.getOrDefault(attribute: AttributeWithDefault<T>): T = get(attribute) ?: attribute.default
|
||||
|
||||
/**
|
||||
* Check if there is an attribute that matches given key by type and adheres to [predicate].
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public inline fun <T, reified A : Attribute<T>> Attributes.hasAny(predicate: (value: T) -> Boolean): Boolean =
|
||||
content.any { (mapKey, mapValue) -> mapKey is A && predicate(mapValue as T) }
|
||||
|
||||
/**
|
||||
* Check if there is an attribute of given type (subtypes included)
|
||||
*/
|
||||
public inline fun <reified A : Attribute<*>> Attributes.hasAny(): Boolean =
|
||||
content.any { (mapKey, _) -> mapKey is A }
|
||||
|
||||
/**
|
||||
* Check if [Attributes] contains a flag. Multiple keys that are instances of a flag could be present
|
||||
*/
|
||||
public inline fun <reified A : FlagAttribute> Attributes.hasFlag(): Boolean =
|
||||
content.keys.any { it is A }
|
||||
|
||||
/**
|
||||
* Create [Attributes] with an added or replaced attribute key.
|
||||
*/
|
||||
public fun <T, A : Attribute<T>> Attributes.withAttribute(
|
||||
attribute: A,
|
||||
attrValue: T,
|
||||
): Attributes = MapAttributes(content + (attribute to attrValue))
|
||||
|
||||
public fun <A : Attribute<Unit>> Attributes.withAttribute(attribute: A): Attributes =
|
||||
withAttribute(attribute, Unit)
|
||||
|
||||
/**
|
||||
* Create a new [Attributes] by modifying the current one
|
||||
*/
|
||||
public fun <O> Attributes.modified(block: AttributesBuilder<O>.() -> Unit): Attributes = Attributes<O> {
|
||||
putAll(this@modified)
|
||||
block()
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new [Attributes] by removing [attribute] key
|
||||
*/
|
||||
public fun Attributes.withoutAttribute(attribute: Attribute<*>): Attributes = MapAttributes(content.minus(attribute))
|
||||
|
||||
/**
|
||||
* Add an element to a [SetAttribute]
|
||||
*/
|
||||
public fun <T, A : SetAttribute<T>> Attributes.withAttributeElement(
|
||||
attribute: A,
|
||||
attrValue: T,
|
||||
): Attributes {
|
||||
val currentSet: Set<T> = get(attribute) ?: emptySet()
|
||||
return MapAttributes(
|
||||
content + (attribute to (currentSet + attrValue))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an element from [SetAttribute]
|
||||
*/
|
||||
public fun <T, A : SetAttribute<T>> Attributes.withoutAttributeElement(
|
||||
attribute: A,
|
||||
attrValue: T,
|
||||
): Attributes {
|
||||
val currentSet: Set<T> = get(attribute) ?: emptySet()
|
||||
return MapAttributes(content + (attribute to (currentSet - attrValue)))
|
||||
}
|
||||
|
||||
/**
|
||||
* Create [Attributes] with a single key
|
||||
*/
|
||||
public fun <T, A : Attribute<T>> Attributes(
|
||||
attribute: A,
|
||||
attrValue: T,
|
||||
): Attributes = MapAttributes(mapOf(attribute to attrValue))
|
||||
|
||||
/**
|
||||
* Create Attributes with a single [Unit] valued attribute
|
||||
*/
|
||||
public fun <A : Attribute<Unit>> Attributes(
|
||||
attribute: A,
|
||||
): Attributes = MapAttributes(mapOf(attribute to Unit))
|
||||
|
||||
public operator fun Attributes.plus(other: Attributes): Attributes = MapAttributes(content + other.content)
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2018-2023 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.attributes
|
||||
|
||||
/**
|
||||
* A builder for [Attributes].
|
||||
* The builder is not thread safe
|
||||
*
|
||||
* @param O type marker of an owner object, for which these attributes are made
|
||||
*/
|
||||
public class AttributesBuilder<out O> internal constructor() : Attributes {
|
||||
|
||||
private val map = mutableMapOf<Attribute<*>, Any?>()
|
||||
|
||||
override fun toString(): String = "Attributes(value=${map.entries})"
|
||||
override fun equals(other: Any?): Boolean = other is Attributes && Attributes.equals(this, other)
|
||||
override fun hashCode(): Int = map.hashCode()
|
||||
|
||||
override val content: Map<out Attribute<*>, Any?> get() = map
|
||||
|
||||
public operator fun <T> set(attribute: Attribute<T>, value: T?) {
|
||||
if (value == null) {
|
||||
map.remove(attribute)
|
||||
} else {
|
||||
map[attribute] = value
|
||||
}
|
||||
}
|
||||
|
||||
public operator fun <V> Attribute<V>.invoke(value: V?) {
|
||||
set(this, value)
|
||||
}
|
||||
|
||||
public infix fun <V> Attribute<V>.put(value: V?) {
|
||||
set(this, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Put all attributes for given [attributes]
|
||||
*/
|
||||
public fun putAll(attributes: Attributes) {
|
||||
map.putAll(attributes.content)
|
||||
}
|
||||
|
||||
public infix fun <V> SetAttribute<V>.add(attrValue: V) {
|
||||
val currentSet: Set<V> = get(this) ?: emptySet()
|
||||
map[this] = currentSet + attrValue
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an element from [SetAttribute]
|
||||
*/
|
||||
public infix fun <V> SetAttribute<V>.remove(attrValue: V) {
|
||||
val currentSet: Set<V> = get(this) ?: emptySet()
|
||||
map[this] = currentSet - attrValue
|
||||
}
|
||||
|
||||
public fun build(): Attributes = MapAttributes(map)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create [Attributes] with a given [builder]
|
||||
* @param O the type for which attributes are built. The type is used only during compilation phase for static extension dispatch
|
||||
*/
|
||||
public fun <O> Attributes(builder: AttributesBuilder<O>.() -> Unit): Attributes =
|
||||
AttributesBuilder<O>().apply(builder).build()
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2018-2023 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.attributes
|
||||
|
||||
/**
|
||||
* An attribute that has a type parameter for value
|
||||
* @param type parameter-type
|
||||
*/
|
||||
public abstract class PolymorphicAttribute<T>(public val type: SafeType<T>) : Attribute<T> {
|
||||
override fun equals(other: Any?): Boolean = other != null &&
|
||||
(this::class == other::class) &&
|
||||
(other as? PolymorphicAttribute<*>)?.type == this.type
|
||||
|
||||
override fun hashCode(): Int = this::class.hashCode() + type.hashCode()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a polymorphic attribute using attribute factory
|
||||
*/
|
||||
@UnstableAttributesAPI
|
||||
public operator fun <T> Attributes.get(attributeKeyBuilder: () -> PolymorphicAttribute<T>): T? =
|
||||
get(attributeKeyBuilder())
|
||||
|
||||
/**
|
||||
* Set a polymorphic attribute using its factory
|
||||
*/
|
||||
@UnstableAttributesAPI
|
||||
public operator fun <O, T> AttributesBuilder<O>.set(attributeKeyBuilder: () -> PolymorphicAttribute<T>, value: T) {
|
||||
set(attributeKeyBuilder(), value)
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2018-2023 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.attributes
|
||||
|
||||
import kotlin.jvm.JvmInline
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
/**
|
||||
* Safe variant ok Kotlin [KType] that ensures that the type parameter is of the same type as [kType]
|
||||
*
|
||||
* @param kType raw [KType]
|
||||
*/
|
||||
@JvmInline
|
||||
public value class SafeType<out T> @PublishedApi internal constructor(public val kType: KType)
|
||||
|
||||
public inline fun <reified T> safeTypeOf(): SafeType<T> = SafeType(typeOf<T>())
|
||||
|
||||
/**
|
||||
* Derive Kotlin [KClass] from this type and fail if the type is not a class (should not happen)
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@UnstableAttributesAPI
|
||||
public val <T> SafeType<T>.kClass: KClass<T & Any> get() = kType.classifier as KClass<T & Any>
|
||||
|
||||
/**
|
||||
* An interface containing [type] for dynamic type checking.
|
||||
*/
|
||||
public interface WithType<out T> {
|
||||
public val type: SafeType<T>
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2018-2023 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.attributes
|
||||
|
||||
/**
|
||||
* Marks declarations that are still experimental in the Attributes-kt APIs, which means that the design of the corresponding
|
||||
* declarations has open issues that may (or may not) lead to their changes in the future. Roughly speaking, there is
|
||||
* a chance of those declarations will be deprecated in the future or the semantics of their behavior may change
|
||||
* in some way that may break some code.
|
||||
*/
|
||||
@MustBeDocumented
|
||||
@Retention(value = AnnotationRetention.BINARY)
|
||||
@RequiresOptIn("This API is unstable and could change in future", RequiresOptIn.Level.WARNING)
|
||||
public annotation class UnstableAttributesAPI
|
4
benchmarks/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Module benchmarks
|
||||
|
||||
|
||||
|
174
benchmarks/build.gradle.kts
Normal file
@ -0,0 +1,174 @@
|
||||
@file:Suppress("UNUSED_VARIABLE")
|
||||
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
|
||||
import space.kscience.kmath.benchmarks.addBenchmarkProperties
|
||||
|
||||
plugins {
|
||||
kotlin("multiplatform")
|
||||
alias(spclibs.plugins.kotlin.plugin.allopen)
|
||||
id("org.jetbrains.kotlinx.benchmark")
|
||||
}
|
||||
|
||||
allOpen.annotation("org.openjdk.jmh.annotations.State")
|
||||
sourceSets.register("benchmarks")
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
val multikVersion: String by rootProject.extra
|
||||
|
||||
kotlin {
|
||||
jvm()
|
||||
|
||||
js(IR) {
|
||||
nodejs()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
all {
|
||||
languageSettings {
|
||||
progressiveMode = true
|
||||
optIn("kotlin.contracts.ExperimentalContracts")
|
||||
optIn("kotlin.ExperimentalUnsignedTypes")
|
||||
optIn("space.kscience.kmath.UnstableKMathAPI")
|
||||
}
|
||||
}
|
||||
|
||||
val commonMain by getting {
|
||||
dependencies {
|
||||
implementation(project(":kmath-ast"))
|
||||
implementation(project(":kmath-core"))
|
||||
implementation(project(":kmath-coroutines"))
|
||||
implementation(project(":kmath-complex"))
|
||||
implementation(project(":kmath-stat"))
|
||||
implementation(project(":kmath-dimensions"))
|
||||
implementation(project(":kmath-for-real"))
|
||||
implementation(project(":kmath-tensors"))
|
||||
implementation(project(":kmath-multik"))
|
||||
implementation("org.jetbrains.kotlinx:multik-default:$multikVersion")
|
||||
implementation(spclibs.kotlinx.benchmark.runtime)
|
||||
}
|
||||
}
|
||||
|
||||
val jvmMain by getting {
|
||||
dependencies {
|
||||
implementation(project(":kmath-commons"))
|
||||
implementation(project(":kmath-ejml"))
|
||||
implementation(project(":kmath-nd4j"))
|
||||
implementation(project(":kmath-kotlingrad"))
|
||||
implementation(project(":kmath-viktor"))
|
||||
implementation(project(":kmath-jafama"))
|
||||
implementation(projects.kmath.kmathTensorflow)
|
||||
implementation("org.tensorflow:tensorflow-core-platform:0.4.0")
|
||||
implementation("org.nd4j:nd4j-native:1.0.0-M1")
|
||||
// uncomment if your system supports AVX2
|
||||
// val os = System.getProperty("os.name")
|
||||
//
|
||||
// if (System.getProperty("os.arch") in arrayOf("x86_64", "amd64")) when {
|
||||
// os.startsWith("Windows") -> implementation("org.nd4j:nd4j-native:1.0.0-beta7:windows-x86_64-avx2")
|
||||
// os == "Linux" -> implementation("org.nd4j:nd4j-native:1.0.0-beta7:linux-x86_64-avx2")
|
||||
// os == "Mac OS X" -> implementation("org.nd4j:nd4j-native:1.0.0-beta7:macosx-x86_64-avx2")
|
||||
// } else
|
||||
// implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Configure benchmark
|
||||
benchmark {
|
||||
// Setup configurations
|
||||
targets {
|
||||
register("jvm")
|
||||
register("js")
|
||||
}
|
||||
|
||||
fun kotlinx.benchmark.gradle.BenchmarkConfiguration.commonConfiguration() {
|
||||
warmups = 2
|
||||
iterations = 5
|
||||
iterationTime = 2000
|
||||
iterationTimeUnit = "ms"
|
||||
}
|
||||
|
||||
configurations.register("buffer") {
|
||||
commonConfiguration()
|
||||
include("BufferBenchmark")
|
||||
}
|
||||
|
||||
configurations.register("nd") {
|
||||
commonConfiguration()
|
||||
include("NDFieldBenchmark")
|
||||
}
|
||||
|
||||
configurations.register("dot") {
|
||||
commonConfiguration()
|
||||
include("DotBenchmark")
|
||||
}
|
||||
|
||||
configurations.register("expressions") {
|
||||
// Some extra precision
|
||||
warmups = 2
|
||||
iterations = 10
|
||||
iterationTime = 10
|
||||
iterationTimeUnit = "s"
|
||||
outputTimeUnit = "s"
|
||||
include("ExpressionsInterpretersBenchmark")
|
||||
}
|
||||
|
||||
configurations.register("matrixInverse") {
|
||||
commonConfiguration()
|
||||
include("MatrixInverseBenchmark")
|
||||
}
|
||||
|
||||
configurations.register("bigInt") {
|
||||
commonConfiguration()
|
||||
include("BigIntBenchmark")
|
||||
}
|
||||
|
||||
configurations.register("jafamaDouble") {
|
||||
commonConfiguration()
|
||||
include("JafamaBenchmark")
|
||||
}
|
||||
|
||||
configurations.register("tensorAlgebra") {
|
||||
commonConfiguration()
|
||||
include("TensorAlgebraBenchmark")
|
||||
}
|
||||
|
||||
configurations.register("viktor") {
|
||||
commonConfiguration()
|
||||
include("ViktorBenchmark")
|
||||
}
|
||||
|
||||
configurations.register("viktorLog") {
|
||||
commonConfiguration()
|
||||
include("ViktorLogBenchmark")
|
||||
}
|
||||
|
||||
configurations.register("integration") {
|
||||
commonConfiguration()
|
||||
include("IntegrationBenchmark")
|
||||
}
|
||||
}
|
||||
|
||||
kotlin.sourceSets.all {
|
||||
with(languageSettings) {
|
||||
optIn("kotlin.contracts.ExperimentalContracts")
|
||||
optIn("kotlin.ExperimentalUnsignedTypes")
|
||||
optIn("space.kscience.kmath.UnstableKMathAPI")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<KotlinJvmCompile> {
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xlambdas=indy"
|
||||
}
|
||||
}
|
||||
|
||||
readme {
|
||||
maturity = space.kscience.gradle.Maturity.EXPERIMENTAL
|
||||
}
|
||||
|
||||
addBenchmarkProperties()
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import kotlinx.benchmark.Benchmark
|
||||
import kotlinx.benchmark.Blackhole
|
||||
import kotlinx.benchmark.Scope
|
||||
import kotlinx.benchmark.State
|
||||
import space.kscience.kmath.UnstableKMathAPI
|
||||
import space.kscience.kmath.expressions.*
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.math.sin
|
||||
import kotlin.random.Random
|
||||
import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression
|
||||
import space.kscience.kmath.wasm.compileToExpression as wasmCompileToExpression
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
class ExpressionsInterpretersBenchmark {
|
||||
/**
|
||||
* Benchmark case for [Expression] created with [expressionInExtendedField].
|
||||
*/
|
||||
@Benchmark
|
||||
fun functionalExpression(blackhole: Blackhole) = invokeAndSum(functional, blackhole)
|
||||
|
||||
/**
|
||||
* Benchmark case for [Expression] created with [toExpression].
|
||||
*/
|
||||
@Benchmark
|
||||
fun mstExpression(blackhole: Blackhole) = invokeAndSum(mst, blackhole)
|
||||
|
||||
/**
|
||||
* Benchmark case for [Expression] created with [compileToExpression].
|
||||
*/
|
||||
@Benchmark
|
||||
fun wasmExpression(blackhole: Blackhole) = invokeAndSum(wasm, blackhole)
|
||||
|
||||
/**
|
||||
* Benchmark case for [Expression] created with [compileToExpression].
|
||||
*/
|
||||
@Benchmark
|
||||
fun estreeExpression(blackhole: Blackhole) = invokeAndSum(estree, blackhole)
|
||||
|
||||
/**
|
||||
* Benchmark case for [Expression] implemented manually with `kotlin.math` functions.
|
||||
*/
|
||||
@Benchmark
|
||||
fun rawExpression(blackhole: Blackhole) = invokeAndSum(raw, blackhole)
|
||||
|
||||
/**
|
||||
* Benchmark case for direct computation w/o [Expression].
|
||||
*/
|
||||
@Benchmark
|
||||
fun justCalculate(blackhole: Blackhole) {
|
||||
val random = Random(0)
|
||||
var sum = 0.0
|
||||
|
||||
repeat(times) {
|
||||
val x = random.nextDouble()
|
||||
sum += x * 2.0 + 2.0 / x - 16.0 / sin(x)
|
||||
}
|
||||
|
||||
blackhole.consume(sum)
|
||||
}
|
||||
|
||||
private fun invokeAndSum(expr: Expression<Double>, blackhole: Blackhole) {
|
||||
val random = Random(0)
|
||||
var sum = 0.0
|
||||
val m = HashMap<Symbol, Double>()
|
||||
|
||||
repeat(times) {
|
||||
m[x] = random.nextDouble()
|
||||
sum += expr(m)
|
||||
}
|
||||
|
||||
blackhole.consume(sum)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
private const val times = 1_000_000
|
||||
|
||||
private val functional = Float64Field.expression {
|
||||
val x = bindSymbol(Symbol.x)
|
||||
x * number(2.0) + 2.0 / x - 16.0 / sin(x)
|
||||
}
|
||||
|
||||
private val node = MstExtendedField {
|
||||
x * 2.0 + number(2.0) / x - number(16.0) / sin(x)
|
||||
}
|
||||
|
||||
private val mst = node.toExpression(Float64Field)
|
||||
|
||||
@OptIn(UnstableKMathAPI::class)
|
||||
private val wasm = node.wasmCompileToExpression(Float64Field)
|
||||
private val estree = node.estreeCompileToExpression(Float64Field)
|
||||
|
||||
private val raw = Expression<Double> { args ->
|
||||
val x = args.getValue(x)
|
||||
x * 2.0 + 2.0 / x - 16.0 / sin(x)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import kotlinx.benchmark.Benchmark
|
||||
import kotlinx.benchmark.Blackhole
|
||||
import kotlinx.benchmark.Scope
|
||||
import kotlinx.benchmark.State
|
||||
import java.nio.IntBuffer
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class ArrayBenchmark {
|
||||
@Benchmark
|
||||
fun benchmarkArrayRead(blackhole: Blackhole) {
|
||||
var res = 0
|
||||
for (i in 1..size) res += array[size - i]
|
||||
blackhole.consume(res)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun benchmarkBufferRead(blackhole: Blackhole) {
|
||||
var res = 0
|
||||
for (i in 1..size) res += arrayBuffer[size - i]
|
||||
blackhole.consume(res)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun nativeBufferRead(blackhole: Blackhole) {
|
||||
var res = 0
|
||||
for (i in 1..size) res += nativeBuffer[size - i]
|
||||
blackhole.consume(res)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val size = 1000
|
||||
private val array = IntArray(size) { it }
|
||||
private val arrayBuffer = IntBuffer.wrap(array)
|
||||
private val nativeBuffer = IntBuffer.allocate(size).also { for (i in 0 until size) it.put(i, i) }
|
||||
}
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
|
||||
import kotlinx.benchmark.Blackhole
|
||||
import org.openjdk.jmh.annotations.Benchmark
|
||||
import org.openjdk.jmh.annotations.Scope
|
||||
import org.openjdk.jmh.annotations.State
|
||||
import space.kscience.kmath.UnstableKMathAPI
|
||||
import space.kscience.kmath.operations.BigIntField
|
||||
import space.kscience.kmath.operations.JBigIntegerField
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import space.kscience.kmath.operations.parseBigInteger
|
||||
import java.math.BigInteger
|
||||
|
||||
|
||||
@UnstableKMathAPI
|
||||
@State(Scope.Benchmark)
|
||||
internal class BigIntBenchmark {
|
||||
|
||||
val kmSmallNumber = BigIntField.number(100)
|
||||
val jvmSmallNumber = JBigIntegerField.number(100)
|
||||
val kmNumber = BigIntField.number(Int.MAX_VALUE)
|
||||
val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE)
|
||||
val kmLargeNumber = BigIntField { number(11).pow(100_000U) }
|
||||
val jvmLargeNumber: BigInteger = JBigIntegerField { number(11).pow(100_000) }
|
||||
val bigExponent = 50_000
|
||||
|
||||
@Benchmark
|
||||
fun kmSmallAdd(blackhole: Blackhole) = BigIntField {
|
||||
blackhole.consume(kmSmallNumber + kmSmallNumber + kmSmallNumber)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun jvmSmallAdd(blackhole: Blackhole) = JBigIntegerField {
|
||||
blackhole.consume(jvmSmallNumber + jvmSmallNumber + jvmSmallNumber)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun kmAdd(blackhole: Blackhole) = BigIntField {
|
||||
blackhole.consume(kmNumber + kmNumber + kmNumber)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun jvmAdd(blackhole: Blackhole) = JBigIntegerField {
|
||||
blackhole.consume(jvmNumber + jvmNumber + jvmNumber)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun kmAddLarge(blackhole: Blackhole) = BigIntField {
|
||||
blackhole.consume(kmLargeNumber + kmLargeNumber + kmLargeNumber)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun jvmAddLarge(blackhole: Blackhole) = JBigIntegerField {
|
||||
blackhole.consume(jvmLargeNumber + jvmLargeNumber + jvmLargeNumber)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun kmMultiply(blackhole: Blackhole) = BigIntField {
|
||||
blackhole.consume(kmNumber * kmNumber * kmNumber)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun kmMultiplyLarge(blackhole: Blackhole) = BigIntField {
|
||||
blackhole.consume(kmLargeNumber * kmLargeNumber)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun jvmMultiply(blackhole: Blackhole) = JBigIntegerField {
|
||||
blackhole.consume(jvmNumber * jvmNumber * jvmNumber)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun jvmMultiplyLarge(blackhole: Blackhole) = JBigIntegerField {
|
||||
blackhole.consume(jvmLargeNumber * jvmLargeNumber)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun kmPower(blackhole: Blackhole) = BigIntField {
|
||||
blackhole.consume(kmNumber.pow(bigExponent.toUInt()))
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun jvmPower(blackhole: Blackhole) = JBigIntegerField {
|
||||
blackhole.consume(jvmNumber.pow(bigExponent))
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun kmParsing16(blackhole: Blackhole) = JBigIntegerField {
|
||||
blackhole.consume("0x7f57ed8b89c29a3b9a85c7a5b84ca3929c7b7488593".parseBigInteger())
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun kmParsing10(blackhole: Blackhole) = JBigIntegerField {
|
||||
blackhole.consume("236656783929183747565738292847574838922010".parseBigInteger())
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun jvmParsing10(blackhole: Blackhole) = JBigIntegerField {
|
||||
blackhole.consume("236656783929183747565738292847574838922010".toBigInteger(10))
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun jvmParsing16(blackhole: Blackhole) = JBigIntegerField {
|
||||
blackhole.consume("7f57ed8b89c29a3b9a85c7a5b84ca3929c7b7488593".toBigInteger(16))
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import kotlinx.benchmark.Benchmark
|
||||
import kotlinx.benchmark.Blackhole
|
||||
import kotlinx.benchmark.Scope
|
||||
import kotlinx.benchmark.State
|
||||
import space.kscience.kmath.complex.Complex
|
||||
import space.kscience.kmath.complex.ComplexField
|
||||
import space.kscience.kmath.complex.complex
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.Float64Buffer
|
||||
import space.kscience.kmath.structures.getDouble
|
||||
import space.kscience.kmath.structures.permute
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class BufferBenchmark {
|
||||
|
||||
@Benchmark
|
||||
fun doubleArrayReadWrite(blackhole: Blackhole) {
|
||||
val buffer = DoubleArray(size) { it.toDouble() }
|
||||
var res = 0.0
|
||||
(0 until size).forEach {
|
||||
res += buffer[it]
|
||||
}
|
||||
blackhole.consume(res)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun doubleBufferReadWrite(blackhole: Blackhole) {
|
||||
val buffer = Float64Buffer(size) { it.toDouble() }
|
||||
var res = 0.0
|
||||
(0 until size).forEach {
|
||||
res += buffer[it]
|
||||
}
|
||||
blackhole.consume(res)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun bufferViewReadWrite(blackhole: Blackhole) {
|
||||
val buffer = Float64Buffer(size) { it.toDouble() }.permute(reversedIndices)
|
||||
var res = 0.0
|
||||
(0 until size).forEach {
|
||||
res += buffer[it]
|
||||
}
|
||||
blackhole.consume(res)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun bufferViewReadWriteSpecialized(blackhole: Blackhole) {
|
||||
val buffer = Float64Buffer(size) { it.toDouble() }.permute(reversedIndices)
|
||||
var res = 0.0
|
||||
(0 until size).forEach {
|
||||
res += buffer.getDouble(it)
|
||||
}
|
||||
blackhole.consume(res)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun complexBufferReadWrite(blackhole: Blackhole) = ComplexField {
|
||||
val buffer = Buffer.complex(size / 2) { Complex(it.toDouble(), -it.toDouble()) }
|
||||
|
||||
var res = zero
|
||||
(0 until size / 2).forEach {
|
||||
res += buffer[it]
|
||||
}
|
||||
|
||||
blackhole.consume(res)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val size = 100
|
||||
private val reversedIndices = IntArray(size) { it }.apply { reverse() }
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import kotlinx.benchmark.Benchmark
|
||||
import kotlinx.benchmark.Blackhole
|
||||
import kotlinx.benchmark.Scope
|
||||
import kotlinx.benchmark.State
|
||||
import space.kscience.kmath.commons.linear.CMLinearSpace
|
||||
import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
|
||||
import space.kscience.kmath.linear.Float64ParallelLinearSpace
|
||||
import space.kscience.kmath.linear.invoke
|
||||
import space.kscience.kmath.linear.linearSpace
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.tensorflow.produceWithTF
|
||||
import space.kscience.kmath.tensors.core.tensorAlgebra
|
||||
import kotlin.random.Random
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class DotBenchmark {
|
||||
companion object {
|
||||
val random = Random(12224)
|
||||
const val dim = 1000
|
||||
|
||||
//creating invertible matrix
|
||||
val matrix1 = Float64Field.linearSpace.buildMatrix(dim, dim) { _, _ ->
|
||||
random.nextDouble()
|
||||
}
|
||||
val matrix2 = Float64Field.linearSpace.buildMatrix(dim, dim) { _, _ ->
|
||||
random.nextDouble()
|
||||
}
|
||||
|
||||
val cmMatrix1 = CMLinearSpace { matrix1.toCM() }
|
||||
val cmMatrix2 = CMLinearSpace { matrix2.toCM() }
|
||||
|
||||
val ejmlMatrix1 = EjmlLinearSpaceDDRM { matrix1.toEjml() }
|
||||
val ejmlMatrix2 = EjmlLinearSpaceDDRM { matrix2.toEjml() }
|
||||
}
|
||||
|
||||
|
||||
@Benchmark
|
||||
fun tfDot(blackhole: Blackhole) {
|
||||
blackhole.consume(
|
||||
Float64Field.produceWithTF {
|
||||
matrix1 dot matrix1
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun cmDotWithConversion(blackhole: Blackhole) = CMLinearSpace {
|
||||
blackhole.consume(matrix1 dot matrix2)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun cmDot(blackhole: Blackhole) = CMLinearSpace {
|
||||
blackhole.consume(cmMatrix1 dot cmMatrix2)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun ejmlDot(blackhole: Blackhole) = EjmlLinearSpaceDDRM {
|
||||
blackhole.consume(ejmlMatrix1 dot ejmlMatrix2)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun ejmlDotWithConversion(blackhole: Blackhole) = EjmlLinearSpaceDDRM {
|
||||
blackhole.consume(matrix1 dot matrix2)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun multikDot(blackhole: Blackhole) = with(multikAlgebra) {
|
||||
blackhole.consume(matrix1 dot matrix2)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun tensorDot(blackhole: Blackhole) = with(Float64Field.tensorAlgebra) {
|
||||
blackhole.consume(matrix1 dot matrix2)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun bufferedDot(blackhole: Blackhole) = with(Float64Field.linearSpace) {
|
||||
blackhole.consume(matrix1 dot matrix2)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun parallelDot(blackhole: Blackhole) = with(Float64ParallelLinearSpace) {
|
||||
blackhole.consume(matrix1 dot matrix2)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import kotlinx.benchmark.Benchmark
|
||||
import kotlinx.benchmark.Blackhole
|
||||
import kotlinx.benchmark.Scope
|
||||
import kotlinx.benchmark.State
|
||||
import space.kscience.kmath.asm.compileToExpression
|
||||
import space.kscience.kmath.expressions.*
|
||||
import space.kscience.kmath.operations.Algebra
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.math.sin
|
||||
import kotlin.random.Random
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class ExpressionsInterpretersBenchmark {
|
||||
/**
|
||||
* Benchmark case for [Expression] created with [expressionInExtendedField].
|
||||
*/
|
||||
@Benchmark
|
||||
fun functionalExpression(blackhole: Blackhole) = invokeAndSum(functional, blackhole)
|
||||
|
||||
/**
|
||||
* Benchmark case for [Expression] created with [toExpression].
|
||||
*/
|
||||
@Benchmark
|
||||
fun mstExpression(blackhole: Blackhole) = invokeAndSum(mst, blackhole)
|
||||
|
||||
/**
|
||||
* Benchmark case for [Expression] created with [compileToExpression].
|
||||
*/
|
||||
@Benchmark
|
||||
fun asmGenericExpression(blackhole: Blackhole) = invokeAndSum(asmGeneric, blackhole)
|
||||
|
||||
/**
|
||||
* Benchmark case for [Expression] created with [compileToExpression].
|
||||
*/
|
||||
@Benchmark
|
||||
fun asmPrimitiveExpressionArray(blackhole: Blackhole) {
|
||||
val random = Random(0)
|
||||
var sum = 0.0
|
||||
val m = DoubleArray(1)
|
||||
|
||||
repeat(times) {
|
||||
m[xIdx] = random.nextDouble()
|
||||
sum += asmPrimitive(m)
|
||||
}
|
||||
|
||||
blackhole.consume(sum)
|
||||
}
|
||||
|
||||
/**
|
||||
* Benchmark case for [Expression] created with [compileToExpression].
|
||||
*/
|
||||
@Benchmark
|
||||
fun asmPrimitiveExpression(blackhole: Blackhole) = invokeAndSum(asmPrimitive, blackhole)
|
||||
|
||||
/**
|
||||
* Benchmark case for [Expression] implemented manually with `kotlin.math` functions.
|
||||
*/
|
||||
@Benchmark
|
||||
fun rawExpression(blackhole: Blackhole) = invokeAndSum(raw, blackhole)
|
||||
|
||||
/**
|
||||
* Benchmark case for direct computation w/o [Expression].
|
||||
*/
|
||||
@Benchmark
|
||||
fun justCalculate(blackhole: Blackhole) {
|
||||
val random = Random(0)
|
||||
var sum = 0.0
|
||||
|
||||
repeat(times) {
|
||||
val x = random.nextDouble()
|
||||
sum += x * 2.0 + 2.0 / x - 16.0 / sin(x)
|
||||
}
|
||||
|
||||
blackhole.consume(sum)
|
||||
}
|
||||
|
||||
private fun invokeAndSum(expr: Expression<Double>, blackhole: Blackhole) {
|
||||
val random = Random(0)
|
||||
var sum = 0.0
|
||||
val m = HashMap<Symbol, Double>()
|
||||
|
||||
repeat(times) {
|
||||
m[x] = random.nextDouble()
|
||||
sum += expr(m)
|
||||
}
|
||||
|
||||
blackhole.consume(sum)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val x by symbol
|
||||
private const val times = 1_000_000
|
||||
|
||||
private val functional = Float64Field.expression {
|
||||
val x = bindSymbol(Symbol.x)
|
||||
x * number(2.0) + 2.0 / x - 16.0 / sin(x)
|
||||
}
|
||||
|
||||
private val node = MstExtendedField {
|
||||
x * 2.0 + number(2.0) / x - number(16.0) / sin(x)
|
||||
}
|
||||
|
||||
private val mst = node.toExpression(Float64Field)
|
||||
|
||||
private val asmPrimitive = node.compileToExpression(Float64Field)
|
||||
private val xIdx = asmPrimitive.indexer.indexOf(x)
|
||||
|
||||
private val asmGeneric = node.compileToExpression(Float64Field as Algebra<Double>)
|
||||
|
||||
private val raw = Expression<Double> { args ->
|
||||
val x = args[x]!!
|
||||
x * 2.0 + 2.0 / x - 16.0 / sin(x)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import org.openjdk.jmh.annotations.Benchmark
|
||||
import org.openjdk.jmh.annotations.Scope
|
||||
import org.openjdk.jmh.annotations.State
|
||||
import org.openjdk.jmh.infra.Blackhole
|
||||
import space.kscience.kmath.complex.Complex
|
||||
import space.kscience.kmath.complex.algebra
|
||||
import space.kscience.kmath.integration.gaussIntegrator
|
||||
import space.kscience.kmath.integration.integrate
|
||||
import space.kscience.kmath.integration.value
|
||||
import space.kscience.kmath.operations.algebra
|
||||
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class IntegrationBenchmark {
|
||||
|
||||
@Benchmark
|
||||
fun doubleIntegration(blackhole: Blackhole) {
|
||||
val res = Double.algebra.gaussIntegrator.integrate(0.0..1.0, intervals = 1000) { x: Double ->
|
||||
//sin(1 / x)
|
||||
1 / x
|
||||
}.value
|
||||
blackhole.consume(res)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun complexIntegration(blackhole: Blackhole) = with(Complex.algebra) {
|
||||
val res = gaussIntegrator.integrate(0.0..1.0, intervals = 1000) { x: Double ->
|
||||
// sin(1 / x) + i * cos(1 / x)
|
||||
1 / x - i / x
|
||||
}.value
|
||||
blackhole.consume(res)
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import kotlinx.benchmark.Blackhole
|
||||
import org.openjdk.jmh.annotations.Benchmark
|
||||
import org.openjdk.jmh.annotations.Scope
|
||||
import org.openjdk.jmh.annotations.State
|
||||
import space.kscience.kmath.jafama.JafamaDoubleField
|
||||
import space.kscience.kmath.jafama.StrictJafamaDoubleField
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.random.Random
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class JafamaBenchmark {
|
||||
@Benchmark
|
||||
fun jafama(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x ->
|
||||
JafamaDoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) }
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun core(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x ->
|
||||
Float64Field { x * power(x, 4) * exp(x) / cos(x) + sin(x) }
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun strictJafama(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x ->
|
||||
StrictJafamaDoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) }
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun invokeBenchmarks(blackhole: Blackhole, expr: (Double) -> Double) {
|
||||
val rng = Random(0)
|
||||
repeat(1000000) { blackhole.consume(expr(rng.nextDouble())) }
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import kotlinx.benchmark.Benchmark
|
||||
import kotlinx.benchmark.Blackhole
|
||||
import kotlinx.benchmark.Scope
|
||||
import kotlinx.benchmark.State
|
||||
import space.kscience.kmath.commons.linear.CMLinearSpace
|
||||
import space.kscience.kmath.commons.linear.lupSolver
|
||||
import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
|
||||
import space.kscience.kmath.linear.invoke
|
||||
import space.kscience.kmath.linear.linearSpace
|
||||
import space.kscience.kmath.linear.lupSolver
|
||||
import space.kscience.kmath.linear.parallel
|
||||
import space.kscience.kmath.operations.algebra
|
||||
import kotlin.random.Random
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class MatrixInverseBenchmark {
|
||||
private companion object {
|
||||
private val random = Random(1224)
|
||||
private const val dim = 100
|
||||
|
||||
private val space = Double.algebra.linearSpace
|
||||
|
||||
//creating invertible matrix
|
||||
private val u = space.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
|
||||
private val l = space.buildMatrix(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 }
|
||||
private val matrix = space { l dot u }
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun kmathLupInversion(blackhole: Blackhole) {
|
||||
blackhole.consume(Double.algebra.linearSpace.lupSolver().inverse(matrix))
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun kmathParallelLupInversion(blackhole: Blackhole) {
|
||||
blackhole.consume(Double.algebra.linearSpace.parallel.lupSolver().inverse(matrix))
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun cmLUPInversion(blackhole: Blackhole) = CMLinearSpace {
|
||||
blackhole.consume(lupSolver().inverse(matrix))
|
||||
}
|
||||
|
||||
|
||||
@Benchmark
|
||||
fun ejmlInverse(blackhole: Blackhole) = EjmlLinearSpaceDDRM {
|
||||
blackhole.consume(matrix.toEjml().inverted())
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import kotlinx.benchmark.Benchmark
|
||||
import kotlinx.benchmark.Blackhole
|
||||
import kotlinx.benchmark.Scope
|
||||
import kotlinx.benchmark.State
|
||||
import org.jetbrains.kotlinx.multik.api.Multik
|
||||
import org.jetbrains.kotlinx.multik.api.ones
|
||||
import org.jetbrains.kotlinx.multik.ndarray.data.DN
|
||||
import org.jetbrains.kotlinx.multik.ndarray.data.DataType
|
||||
import space.kscience.kmath.UnsafeKMathAPI
|
||||
import space.kscience.kmath.nd.*
|
||||
import space.kscience.kmath.nd4j.nd4j
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.tensors.core.DoubleTensor
|
||||
import space.kscience.kmath.tensors.core.one
|
||||
import space.kscience.kmath.tensors.core.tensorAlgebra
|
||||
import space.kscience.kmath.viktor.viktorAlgebra
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class NDFieldBenchmark {
|
||||
|
||||
private companion object {
|
||||
private const val dim = 1000
|
||||
private const val n = 100
|
||||
private val shape = ShapeND(dim, dim)
|
||||
private val specializedField = Float64Field.ndAlgebra
|
||||
private val genericField = BufferedFieldOpsND(Float64Field)
|
||||
private val nd4jField = Float64Field.nd4j
|
||||
private val viktorField = Float64Field.viktorAlgebra
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun specializedFieldAdd(blackhole: Blackhole) = with(specializedField) {
|
||||
var res: StructureND<Double> = one(shape)
|
||||
repeat(n) { res += 1.0 }
|
||||
blackhole.consume(res)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun boxingFieldAdd(blackhole: Blackhole) = with(genericField) {
|
||||
var res: StructureND<Double> = one(shape)
|
||||
repeat(n) { res += 1.0 }
|
||||
blackhole.consume(res)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun multikAdd(blackhole: Blackhole) = with(multikAlgebra) {
|
||||
var res: StructureND<Double> = one(shape)
|
||||
repeat(n) { res += 1.0 }
|
||||
blackhole.consume(res)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun viktorAdd(blackhole: Blackhole) = with(viktorField) {
|
||||
var res: StructureND<Double> = one(shape)
|
||||
repeat(n) { res += 1.0 }
|
||||
blackhole.consume(res)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun tensorAdd(blackhole: Blackhole) = with(Double.tensorAlgebra) {
|
||||
var res: DoubleTensor = one(shape)
|
||||
repeat(n) { res = res + 1.0 }
|
||||
blackhole.consume(res)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun tensorInPlaceAdd(blackhole: Blackhole) = with(Double.tensorAlgebra) {
|
||||
val res: DoubleTensor = one(shape)
|
||||
repeat(n) { res += 1.0 }
|
||||
blackhole.consume(res)
|
||||
}
|
||||
|
||||
@OptIn(UnsafeKMathAPI::class)
|
||||
@Benchmark
|
||||
fun multikInPlaceAdd(blackhole: Blackhole) = with(multikAlgebra) {
|
||||
val res = Multik.ones<Double, DN>(shape.asArray(), DataType.DoubleDataType).wrap()
|
||||
repeat(n) { res += 1.0 }
|
||||
blackhole.consume(res)
|
||||
}
|
||||
|
||||
// @Benchmark
|
||||
// fun nd4jAdd(blackhole: Blackhole) = with(nd4jField) {
|
||||
// var res: StructureND<Double> = one(dim, dim)
|
||||
// repeat(n) { res += 1.0 }
|
||||
// blackhole.consume(res)
|
||||
// }
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import kotlinx.benchmark.Benchmark
|
||||
import kotlinx.benchmark.Blackhole
|
||||
import kotlinx.benchmark.Scope
|
||||
import kotlinx.benchmark.State
|
||||
import space.kscience.kmath.linear.linearSpace
|
||||
import space.kscience.kmath.linear.matrix
|
||||
import space.kscience.kmath.linear.symmetric
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.tensors.core.symEigJacobi
|
||||
import space.kscience.kmath.tensors.core.symEigSvd
|
||||
import space.kscience.kmath.tensors.core.tensorAlgebra
|
||||
import kotlin.random.Random
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class TensorAlgebraBenchmark {
|
||||
companion object {
|
||||
private val random = Random(12224)
|
||||
private const val dim = 30
|
||||
|
||||
private val matrix = Float64Field.linearSpace.matrix(dim, dim).symmetric { _, _ -> random.nextDouble() }
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun tensorSymEigSvd(blackhole: Blackhole) = with(Double.tensorAlgebra) {
|
||||
blackhole.consume(symEigSvd(matrix, 1e-10))
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun tensorSymEigJacobi(blackhole: Blackhole) = with(Double.tensorAlgebra) {
|
||||
blackhole.consume(symEigJacobi(matrix, 50, 1e-10))
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import kotlinx.benchmark.Benchmark
|
||||
import kotlinx.benchmark.Blackhole
|
||||
import kotlinx.benchmark.Scope
|
||||
import kotlinx.benchmark.State
|
||||
import org.jetbrains.bio.viktor.F64Array
|
||||
import space.kscience.kmath.nd.ShapeND
|
||||
import space.kscience.kmath.nd.StructureND
|
||||
import space.kscience.kmath.nd.ndAlgebra
|
||||
import space.kscience.kmath.nd.one
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.viktor.ViktorFieldND
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class ViktorBenchmark {
|
||||
|
||||
@Benchmark
|
||||
fun doubleFieldAddition(blackhole: Blackhole) {
|
||||
with(doubleField) {
|
||||
var res: StructureND<Double> = one(shape)
|
||||
repeat(n) { res += 1.0 }
|
||||
blackhole.consume(res)
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun viktorFieldAddition(blackhole: Blackhole) {
|
||||
with(viktorField) {
|
||||
var res = one(shape)
|
||||
repeat(n) { res += 1.0 }
|
||||
blackhole.consume(res)
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun rawViktor(blackhole: Blackhole) {
|
||||
val one = F64Array.full(init = 1.0, shape = intArrayOf(dim, dim))
|
||||
var res = one
|
||||
repeat(n) { res = res + one }
|
||||
blackhole.consume(res)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val dim = 1000
|
||||
private const val n = 100
|
||||
private val shape = ShapeND(dim, dim)
|
||||
|
||||
// automatically build context most suited for given type.
|
||||
private val doubleField = Float64Field.ndAlgebra
|
||||
private val viktorField = ViktorFieldND(dim, dim)
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import kotlinx.benchmark.Benchmark
|
||||
import kotlinx.benchmark.Blackhole
|
||||
import kotlinx.benchmark.Scope
|
||||
import kotlinx.benchmark.State
|
||||
import org.jetbrains.bio.viktor.F64Array
|
||||
import space.kscience.kmath.nd.ShapeND
|
||||
import space.kscience.kmath.nd.ndAlgebra
|
||||
import space.kscience.kmath.nd.one
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.viktor.ViktorFieldND
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class ViktorLogBenchmark {
|
||||
@Benchmark
|
||||
fun realFieldLog(blackhole: Blackhole) {
|
||||
with(doubleField) {
|
||||
val fortyTwo = structureND(shape) { 42.0 }
|
||||
var res = one(shape)
|
||||
repeat(n) { res = ln(fortyTwo) }
|
||||
blackhole.consume(res)
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun viktorFieldLog(blackhole: Blackhole) {
|
||||
with(viktorField) {
|
||||
val fortyTwo = structureND(shape) { 42.0 }
|
||||
var res = one
|
||||
repeat(n) { res = ln(fortyTwo) }
|
||||
blackhole.consume(res)
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun rawViktorLog(blackhole: Blackhole) {
|
||||
val fortyTwo = F64Array.full(dim, dim, init = 42.0)
|
||||
lateinit var res: F64Array
|
||||
repeat(n) { res = fortyTwo.log() }
|
||||
blackhole.consume(res)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val dim = 1000
|
||||
private const val n = 100
|
||||
private val shape = ShapeND(dim, dim)
|
||||
|
||||
// automatically build context most suited for given type.
|
||||
private val doubleField = Float64Field.ndAlgebra
|
||||
private val viktorField = ViktorFieldND(dim, dim)
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import org.jetbrains.kotlinx.multik.default.DefaultEngine
|
||||
import space.kscience.kmath.multik.MultikDoubleAlgebra
|
||||
|
||||
val multikAlgebra = MultikDoubleAlgebra(DefaultEngine())
|
@ -1,40 +1,74 @@
|
||||
import space.kscience.gradle.useApache2Licence
|
||||
import space.kscience.gradle.useSPCTeam
|
||||
|
||||
plugins {
|
||||
id("ru.mipt.npm.gradle.project")
|
||||
id("space.kscience.gradle.project")
|
||||
id("org.jetbrains.kotlinx.kover") version "0.7.6"
|
||||
}
|
||||
|
||||
val attributesVersion by extra("0.2.0")
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven("https://clojars.org/repo")
|
||||
maven("https://dl.bintray.com/egor-bogomolov/astminer/")
|
||||
maven("https://dl.bintray.com/hotkeytlt/maven")
|
||||
maven("https://dl.bintray.com/kotlin/kotlin-eap")
|
||||
maven("https://dl.bintray.com/kotlin/kotlinx")
|
||||
maven("https://dl.bintray.com/mipt-npm/dev")
|
||||
maven("https://dl.bintray.com/mipt-npm/kscience")
|
||||
maven("https://jitpack.io")
|
||||
maven("http://logicrunch.research.it.uu.se/maven/")
|
||||
maven("https://repo.kotlin.link")
|
||||
maven("https://oss.sonatype.org/content/repositories/snapshots")
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
group = "space.kscience"
|
||||
version = "0.2.0"
|
||||
version = "0.4.0"
|
||||
}
|
||||
|
||||
subprojects {
|
||||
if (name.startsWith("kmath")) apply<ru.mipt.npm.gradle.KSciencePublishingPlugin>()
|
||||
if (name.startsWith("kmath")) apply<MavenPublishPlugin>()
|
||||
|
||||
plugins.withId("org.jetbrains.dokka") {
|
||||
tasks.withType<org.jetbrains.dokka.gradle.DokkaTaskPartial> {
|
||||
dependsOn(tasks["assemble"])
|
||||
|
||||
dokkaSourceSets.all {
|
||||
val readmeFile = this@subprojects.projectDir.resolve("README.md")
|
||||
if (readmeFile.exists()) includes.from(readmeFile)
|
||||
val kotlinDirPath = "src/$name/kotlin"
|
||||
val kotlinDir = file(kotlinDirPath)
|
||||
|
||||
if (kotlinDir.exists()) sourceLink {
|
||||
localDirectory.set(kotlinDir)
|
||||
|
||||
remoteUrl.set(
|
||||
uri("https://github.com/SciProgCentre/kmath/tree/master/${this@subprojects.name}/$kotlinDirPath").toURL()
|
||||
)
|
||||
}
|
||||
|
||||
externalDocumentationLink("https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/")
|
||||
externalDocumentationLink("https://deeplearning4j.org/api/latest/")
|
||||
externalDocumentationLink("https://axelclk.bitbucket.io/symja/javadoc/")
|
||||
|
||||
externalDocumentationLink(
|
||||
"https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/",
|
||||
"https://kotlin.github.io/kotlinx.coroutines/package-list",
|
||||
)
|
||||
|
||||
externalDocumentationLink(
|
||||
"https://breandan.net/kotlingrad/kotlingrad/",
|
||||
"https://breandan.net/kotlingrad/kotlingrad/kotlingrad/package-list",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readme {
|
||||
readmeTemplate = file("docs/templates/README-TEMPLATE.md")
|
||||
}
|
||||
readme.readmeTemplate = file("docs/templates/README-TEMPLATE.md")
|
||||
|
||||
ksciencePublish {
|
||||
spaceRepo = "https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven"
|
||||
bintrayRepo = "kscience"
|
||||
githubProject = "kmath"
|
||||
pom("https://github.com/SciProgCentre/kmath") {
|
||||
useApache2Licence()
|
||||
useSPCTeam()
|
||||
}
|
||||
repository("spc", "https://maven.sciprog.center/kscience")
|
||||
sonatype("https://oss.sonatype.org")
|
||||
}
|
||||
|
||||
apiValidation{
|
||||
nonPublicMarkers.add("space.kscience.kmath.misc.UnstableKMathAPI")
|
||||
}
|
||||
apiValidation.nonPublicMarkers.add("space.kscience.kmath.UnstableKMathAPI")
|
||||
|
||||
val multikVersion by extra("0.2.3")
|
||||
|
34
buildSrc/build.gradle.kts
Normal file
@ -0,0 +1,34 @@
|
||||
plugins {
|
||||
`kotlin-dsl`
|
||||
`version-catalog`
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven("https://repo.kotlin.link")
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
|
||||
val toolsVersion = spclibs.versions.tools.get()
|
||||
val kotlinVersion = spclibs.versions.kotlin.asProvider().get()
|
||||
val benchmarksVersion = spclibs.versions.kotlinx.benchmark.get()
|
||||
|
||||
dependencies {
|
||||
api("space.kscience:gradle-tools:$toolsVersion")
|
||||
//plugins form benchmarks
|
||||
api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:$benchmarksVersion")
|
||||
//api("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion")
|
||||
//to be used inside build-script only
|
||||
//implementation(spclibs.kotlinx.serialization.json)
|
||||
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.+")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(11))
|
||||
}
|
||||
sourceSets.all {
|
||||
languageSettings.optIn("kotlin.OptIn")
|
||||
}
|
||||
}
|
38
buildSrc/settings.gradle.kts
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2018-2021 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
|
||||
|
||||
plugins {
|
||||
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
|
||||
}
|
||||
|
||||
dependencyResolutionManagement {
|
||||
val projectProperties = java.util.Properties()
|
||||
file("../gradle.properties").inputStream().use {
|
||||
projectProperties.load(it)
|
||||
}
|
||||
|
||||
projectProperties.forEach { key, value ->
|
||||
extra.set(key.toString(), value)
|
||||
}
|
||||
|
||||
|
||||
val toolsVersion: String = projectProperties["toolsVersion"].toString()
|
||||
|
||||
@Suppress("UnstableApiUsage")
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven("https://repo.kotlin.link")
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
|
||||
versionCatalogs {
|
||||
create("spclibs") {
|
||||
from("space.kscience:version-catalog:$toolsVersion")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
data class JmhReport(
|
||||
val jmhVersion: String,
|
||||
val benchmark: String,
|
||||
val mode: String,
|
||||
val threads: Int,
|
||||
val forks: Int,
|
||||
val jvm: String,
|
||||
val jvmArgs: List<String>,
|
||||
val jdkVersion: String,
|
||||
val vmName: String,
|
||||
val vmVersion: String,
|
||||
val warmupIterations: Int,
|
||||
val warmupTime: String,
|
||||
val warmupBatchSize: Int,
|
||||
val measurementIterations: Int,
|
||||
val measurementTime: String,
|
||||
val measurementBatchSize: Int,
|
||||
val params: Map<String, String> = emptyMap(),
|
||||
val primaryMetric: PrimaryMetric,
|
||||
val secondaryMetrics: Map<String, SecondaryMetric>,
|
||||
) {
|
||||
interface Metric {
|
||||
val score: Double
|
||||
val scoreError: Double
|
||||
val scoreConfidence: List<Double>
|
||||
val scorePercentiles: Map<Double, Double>
|
||||
val scoreUnit: String
|
||||
}
|
||||
|
||||
data class PrimaryMetric(
|
||||
override val score: Double,
|
||||
override val scoreError: Double,
|
||||
override val scoreConfidence: List<Double>,
|
||||
override val scorePercentiles: Map<Double, Double>,
|
||||
override val scoreUnit: String,
|
||||
val rawDataHistogram: List<List<List<List<Double>>>>? = null,
|
||||
val rawData: List<List<Double>>? = null,
|
||||
) : Metric
|
||||
|
||||
data class SecondaryMetric(
|
||||
override val score: Double,
|
||||
override val scoreError: Double,
|
||||
override val scoreConfidence: List<Double>,
|
||||
override val scorePercentiles: Map<Double, Double>,
|
||||
override val scoreUnit: String,
|
||||
val rawData: List<List<Double>>,
|
||||
) : Metric
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import com.fasterxml.jackson.module.kotlin.readValue
|
||||
import kotlinx.benchmark.gradle.BenchmarksExtension
|
||||
import org.gradle.api.Project
|
||||
import space.kscience.gradle.KScienceReadmeExtension
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneId
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.format.DateTimeFormatterBuilder
|
||||
import java.time.format.SignStyle
|
||||
import java.time.temporal.ChronoField.*
|
||||
import java.util.*
|
||||
|
||||
private val ISO_DATE_TIME: DateTimeFormatter = DateTimeFormatterBuilder().run {
|
||||
parseCaseInsensitive()
|
||||
appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
|
||||
appendLiteral('-')
|
||||
appendValue(MONTH_OF_YEAR, 2)
|
||||
appendLiteral('-')
|
||||
appendValue(DAY_OF_MONTH, 2)
|
||||
appendLiteral('T')
|
||||
appendValue(HOUR_OF_DAY, 2)
|
||||
appendLiteral('.')
|
||||
appendValue(MINUTE_OF_HOUR, 2)
|
||||
optionalStart()
|
||||
appendLiteral('.')
|
||||
appendValue(SECOND_OF_MINUTE, 2)
|
||||
optionalStart()
|
||||
appendFraction(NANO_OF_SECOND, 0, 9, true)
|
||||
optionalStart()
|
||||
appendOffsetId()
|
||||
optionalStart()
|
||||
appendLiteral('[')
|
||||
parseCaseSensitive()
|
||||
appendZoneRegionId()
|
||||
appendLiteral(']')
|
||||
toFormatter()
|
||||
}
|
||||
|
||||
private fun noun(number: Number, singular: String, plural: String) = if (number.toLong() == 1L) singular else plural
|
||||
|
||||
private val jsonMapper = jacksonObjectMapper()
|
||||
|
||||
fun Project.addBenchmarkProperties() {
|
||||
val benchmarksProject = this
|
||||
rootProject.subprojects.forEach { p ->
|
||||
p.extensions.findByType(KScienceReadmeExtension::class.java)?.run {
|
||||
benchmarksProject.extensions.findByType(BenchmarksExtension::class.java)?.configurations?.forEach { cfg ->
|
||||
property("benchmark${cfg.name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }}") {
|
||||
val launches = benchmarksProject.layout.buildDirectory.dir("reports/benchmarks/${cfg.name}").get()
|
||||
|
||||
val resDirectory = launches.files().maxByOrNull {
|
||||
LocalDateTime.parse(it.name, ISO_DATE_TIME).atZone(ZoneId.systemDefault()).toInstant()
|
||||
}
|
||||
|
||||
if (resDirectory == null || !(resDirectory.resolve("jvm.json")).exists()) {
|
||||
"> **Can't find appropriate benchmark data. Try generating readme files after running benchmarks**."
|
||||
} else {
|
||||
val reports: List<JmhReport> =
|
||||
jsonMapper.readValue<List<JmhReport>>(resDirectory.resolve("jvm.json"))
|
||||
|
||||
buildString {
|
||||
appendLine("<details>")
|
||||
appendLine("<summary>")
|
||||
appendLine("Report for benchmark configuration <code>${cfg.name}</code>")
|
||||
appendLine("</summary>")
|
||||
appendLine()
|
||||
val first = reports.first()
|
||||
|
||||
appendLine("* Run on ${first.vmName} (build ${first.vmVersion}) with Java process:")
|
||||
appendLine()
|
||||
appendLine("```")
|
||||
appendLine(
|
||||
"${first.jvm} ${
|
||||
first.jvmArgs.joinToString(" ")
|
||||
}"
|
||||
)
|
||||
appendLine("```")
|
||||
|
||||
appendLine(
|
||||
"* JMH ${first.jmhVersion} was used in `${first.mode}` mode with ${first.warmupIterations} warmup ${
|
||||
noun(first.warmupIterations, "iteration", "iterations")
|
||||
} by ${first.warmupTime} and ${first.measurementIterations} measurement ${
|
||||
noun(first.measurementIterations, "iteration", "iterations")
|
||||
} by ${first.measurementTime}."
|
||||
)
|
||||
|
||||
appendLine()
|
||||
appendLine("| Benchmark | Score |")
|
||||
appendLine("|:---------:|:-----:|")
|
||||
|
||||
reports.forEach { report ->
|
||||
appendLine("|`${report.benchmark}`|${report.primaryMetric.score} ± ${report.primaryMetric.scoreError} ${report.primaryMetric.scoreUnit}|")
|
||||
}
|
||||
|
||||
appendLine("</details>")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,85 +1,45 @@
|
||||
# Algebraic Structures and Algebraic Elements
|
||||
|
||||
The mathematical operations in KMath are generally separated from mathematical objects. This means that to perform an
|
||||
operation, say `+`, one needs two objects of a type `T` and an algebra context, which draws appropriate operation up,
|
||||
say `Space<T>`. Next one needs to run the actual operation in the context:
|
||||
The mathematical operations in KMath are generally separated from mathematical objects. This means that to perform an
|
||||
operation, say `+`, one needs two objects of a type `T` and an algebra context, which draws appropriate operation up,
|
||||
say `Group<T>`. Next one needs to run the actual operation in the context:
|
||||
|
||||
```kotlin
|
||||
import space.kscience.kmath.operations.*
|
||||
|
||||
val a: T = ...
|
||||
val b: T = ...
|
||||
val space: Space<T> = ...
|
||||
val group: Group<T> = ...
|
||||
|
||||
val c = space { a + b }
|
||||
val c = group { a + b }
|
||||
```
|
||||
|
||||
At first glance, this distinction seems to be a needless complication, but in fact one needs to remember that in
|
||||
mathematics, one could draw up different operations on same objects. For example, one could use different types of
|
||||
At first glance, this distinction seems to be a needless complication, but in fact one needs to remember that in
|
||||
mathematics, one could draw up different operations on same objects. For example, one could use different types of
|
||||
geometry for vectors.
|
||||
|
||||
## Algebraic Structures
|
||||
|
||||
Mathematical contexts have the following hierarchy:
|
||||
Primary mathematical contexts have the following hierarchy:
|
||||
|
||||
**Algebra** ← **Space** ← **Ring** ← **Field**
|
||||
`Field <: Ring <: Group <: Algebra`
|
||||
|
||||
These interfaces follow real algebraic structures:
|
||||
|
||||
- [Space](https://mathworld.wolfram.com/VectorSpace.html) defines addition, its neutral element (i.e. 0) and scalar
|
||||
multiplication;
|
||||
- [Ring](http://mathworld.wolfram.com/Ring.html) adds multiplication and its neutral element (i.e. 1);
|
||||
- [Group](https://mathworld.wolfram.com/Group.html) defines addition, its identity element (i.e., 0) and additive
|
||||
inverse (-x);
|
||||
- [Ring](http://mathworld.wolfram.com/Ring.html) adds multiplication and its identity element (i.e., 1);
|
||||
- [Field](http://mathworld.wolfram.com/Field.html) adds division operation.
|
||||
|
||||
A typical implementation of `Field<T>` is the `RealField` which works on doubles, and `VectorSpace` for `Space<T>`.
|
||||
A typical implementation of `Field<T>` is the `DoubleField` which works on doubles, and `VectorSpace` for `Space<T>`.
|
||||
|
||||
In some cases algebra context can hold additional operations like `exp` or `sin`, and then it inherits appropriate
|
||||
interface. Also, contexts may have operations, which produce elements outside of the context. For example, `Matrix.dot`
|
||||
operation produces a matrix with new dimensions, which can be incompatible with initial matrix in terms of linear
|
||||
operations.
|
||||
|
||||
## Algebraic Element
|
||||
|
||||
To achieve more familiar behavior (where you apply operations directly to mathematical objects), without involving
|
||||
contexts KMath submits special type objects called `MathElement`. A `MathElement` is basically some object coupled to
|
||||
a mathematical context. For example `Complex` is the pair of real numbers representing real and imaginary parts,
|
||||
but it also holds reference to the `ComplexField` singleton, which allows performing direct operations on `Complex`
|
||||
numbers without explicit involving the context like:
|
||||
|
||||
```kotlin
|
||||
import space.kscience.kmath.operations.*
|
||||
|
||||
// Using elements
|
||||
val c1 = Complex(1.0, 1.0)
|
||||
val c2 = Complex(1.0, -1.0)
|
||||
val c3 = c1 + c2 + 3.0.toComplex()
|
||||
|
||||
// Using context
|
||||
val c4 = ComplexField { c1 + i - 2.0 }
|
||||
```
|
||||
|
||||
Both notations have their pros and cons.
|
||||
|
||||
The hierarchy for algebraic elements follows the hierarchy for the corresponding algebraic structures.
|
||||
|
||||
**MathElement** ← **SpaceElement** ← **RingElement** ← **FieldElement**
|
||||
|
||||
`MathElement<C>` is the generic common ancestor of the class with context.
|
||||
|
||||
One major distinction between algebraic elements and algebraic contexts is that elements have three type
|
||||
parameters:
|
||||
|
||||
1. The type of elements, the field operates on.
|
||||
2. The self-type of the element returned from operation (which has to be an algebraic element).
|
||||
3. The type of the algebra over first type-parameter.
|
||||
|
||||
The middle type is needed for of algebra members do not store context. For example, it is impossible to add a context
|
||||
to regular `Double`. The element performs automatic conversions from context types and back. One should use context
|
||||
operations in all performance-critical places. The performance of element operations is not guaranteed.
|
||||
interface. Also, contexts may have operations, which produce elements outside the context. For example, `Matrix.dot`
|
||||
operation produces a matrix with new dimensions, which can be incompatible with initial matrix in linear operations.
|
||||
|
||||
## Spaces and Fields
|
||||
|
||||
KMath submits both contexts and elements for builtin algebraic structures:
|
||||
KMath introduces contexts for builtin algebraic structures:
|
||||
|
||||
```kotlin
|
||||
import space.kscience.kmath.operations.*
|
||||
@ -102,13 +62,13 @@ val c2 = ComplexField { c1 - 1.0 } // Returns: Complex(re=0.0, im=2.0)
|
||||
val c3 = ComplexField { c1 - i * 2.0 }
|
||||
```
|
||||
|
||||
**Note**: In theory it is possible to add behaviors directly to the context, but as for now Kotlin does not support
|
||||
that. Watch [KT-10468](https://youtrack.jetbrains.com/issue/KT-10468) and
|
||||
**Note**: In theory it is possible to add behaviors directly to the context, but as for now Kotlin does not support
|
||||
that. Watch [KT-10468](https://youtrack.jetbrains.com/issue/KT-10468) and
|
||||
[KEEP-176](https://github.com/Kotlin/KEEP/pull/176) for updates.
|
||||
|
||||
## Nested fields
|
||||
|
||||
Contexts allow one to build more complex structures. For example, it is possible to create a `Matrix` from complex
|
||||
Contexts allow one to build more complex structures. For example, it is possible to create a `Matrix` from complex
|
||||
elements like so:
|
||||
|
||||
```kotlin
|
||||
@ -118,8 +78,9 @@ val element = NDElement.complex(shape = intArrayOf(2, 2)) { index: IntArray ->
|
||||
```
|
||||
|
||||
The `element` in this example is a member of the `Field` of 2D structures, each element of which is a member of its own
|
||||
`ComplexField`. It is important one does not need to create a special n-d class to hold complex
|
||||
numbers and implement operations on it, one just needs to provide a field for its elements.
|
||||
`ComplexField`. It is important one does not need to create a special n-d class to hold complex numbers and implement
|
||||
operations on it, one just needs to provide a field for its elements.
|
||||
|
||||
**Note**: Fields themselves do not solve the problem of JVM boxing, but it is possible to solve with special contexts like
|
||||
**Note**: Fields themselves do not solve the problem of JVM boxing, but it is possible to solve with special contexts
|
||||
like
|
||||
`MemorySpec`.
|
||||
|
@ -1,17 +1,20 @@
|
||||
# Buffers
|
||||
|
||||
Buffer is one of main building blocks of kmath. It is a basic interface allowing random-access read and write (with `MutableBuffer`).
|
||||
There are different types of buffers:
|
||||
Buffer is one of main building blocks of kmath. It is a basic interface allowing random-access read and write (
|
||||
with `MutableBuffer`). There are different types of buffers:
|
||||
|
||||
* Primitive buffers wrapping like `RealBuffer` which are wrapping primitive arrays.
|
||||
* Primitive buffers wrapping like `DoubleBuffer` which are wrapping primitive arrays.
|
||||
* Boxing `ListBuffer` wrapping a list
|
||||
* Functionally defined `VirtualBuffer` which does not hold a state itself, but provides a function to calculate value
|
||||
* `MemoryBuffer` allows direct allocation of objects in continuous memory block.
|
||||
|
||||
Some kmath features require a `BufferFactory` class to operate properly. A general convention is to use functions defined in
|
||||
`Buffer` and `MutableBuffer` companion classes. For example factory `Buffer.Companion::auto` in most cases creates the most suitable
|
||||
buffer for given reified type (for types with custom memory buffer it still better to use their own `MemoryBuffer.create()` factory).
|
||||
Some kmath features require a `BufferFactory` class to operate properly. A general convention is to use functions
|
||||
defined in
|
||||
`Buffer` and `MutableBuffer` companion classes. For example factory `Buffer.Companion::auto` in most cases creates the
|
||||
most suitable buffer for given reified type (for types with custom memory buffer it still better to use their
|
||||
own `MemoryBuffer.create()` factory).
|
||||
|
||||
## Buffer performance
|
||||
|
||||
One should avoid using default boxing buffer wherever it is possible. Try to use primitive buffers or memory buffers instead
|
||||
One should avoid using default boxing buffer wherever it is possible. Try to use primitive buffers or memory buffers
|
||||
instead.
|
||||
|
@ -1,34 +1,35 @@
|
||||
# Coding Conventions
|
||||
|
||||
KMath code follows general [Kotlin conventions](https://kotlinlang.org/docs/reference/coding-conventions.html), but
|
||||
with a number of small changes and clarifications.
|
||||
Generally, KMath code follows
|
||||
general [Kotlin coding conventions](https://kotlinlang.org/docs/reference/coding-conventions.html), but with a number of
|
||||
small changes and clarifications.
|
||||
|
||||
## Utility Class Naming
|
||||
|
||||
Filename should coincide with a name of one of the classes contained in the file or start with small letter and
|
||||
describe its contents.
|
||||
Filename should coincide with a name of one of the classes contained in the file or start with small letter and describe
|
||||
its contents.
|
||||
|
||||
The code convention [here](https://kotlinlang.org/docs/reference/coding-conventions.html#source-file-names) says that
|
||||
file names should start with a capital letter even if file does not contain classes. Yet starting utility classes and
|
||||
The code convention [here](https://kotlinlang.org/docs/reference/coding-conventions.html#source-file-names) says that
|
||||
file names should start with a capital letter even if file does not contain classes. Yet starting utility classes and
|
||||
aggregators with a small letter seems to be a good way to visually separate those files.
|
||||
|
||||
This convention could be changed in future in a non-breaking way.
|
||||
|
||||
## Private Variable Naming
|
||||
|
||||
Private variables' names may start with underscore `_` for of the private mutable variable is shadowed by the public
|
||||
Private variables' names may start with underscore `_` for of the private mutable variable is shadowed by the public
|
||||
read-only value with the same meaning.
|
||||
|
||||
This rule does not permit underscores in names, but it is sometimes useful to "underscore" the fact that public and
|
||||
This rule does not permit underscores in names, but it is sometimes useful to "underscore" the fact that public and
|
||||
private versions draw up the same entity. It is allowed only for private variables.
|
||||
|
||||
This convention could be changed in future in a non-breaking way.
|
||||
|
||||
## Functions and Properties One-liners
|
||||
|
||||
Use one-liners when they occupy single code window line both for functions and properties with getters like
|
||||
`val b: String get() = "fff"`. The same should be performed with multiline expressions when they could be
|
||||
Use one-liners when they occupy single code window line both for functions and properties with getters like
|
||||
`val b: String get() = "fff"`. The same should be performed with multiline expressions when they could be
|
||||
cleanly separated.
|
||||
|
||||
There is no universal consensus whenever use `fun a() = ...` or `fun a() { return ... }`. Yet from reader outlook
|
||||
There is no universal consensus whenever use `fun a() = ...` or `fun a() { return ... }`. Yet from reader outlook
|
||||
one-lines seem to better show that the property or function is easily calculated.
|
||||
|
@ -2,18 +2,17 @@
|
||||
|
||||
## The problem
|
||||
|
||||
A known problem for implementing mathematics in statically-typed languages (but not only in them) is that different
|
||||
sets of mathematical operators can be defined on the same mathematical objects. Sometimes there is no single way to
|
||||
treat some operations, including basic arithmetic operations, on a Java/Kotlin `Number`. Sometimes there are different ways to
|
||||
define the same structure, such as Euclidean and elliptic geometry vector spaces over real vectors. Another problem arises when
|
||||
one wants to add some kind of behavior to an existing entity. In dynamic languages those problems are usually solved
|
||||
by adding dynamic context-specific behaviors at runtime, but this solution has a lot of drawbacks.
|
||||
A known problem for implementing mathematics in statically-typed languages (but not only in them) is that different sets
|
||||
of mathematical operators can be defined on the same mathematical objects. Sometimes there is no single way to treat
|
||||
some operations, including basic arithmetic operations, on a Java/Kotlin `Number`. Sometimes there are different ways to
|
||||
define the same structure, such as Euclidean and elliptic geometry vector spaces over real vectors. Another problem
|
||||
arises when one wants to add some kind of behavior to an existing entity. In dynamic languages those problems are
|
||||
usually solved by adding dynamic context-specific behaviors at runtime, but this solution has a lot of drawbacks.
|
||||
|
||||
## Context-oriented approach
|
||||
|
||||
One possible solution to these problems is to divorce numerical representations from behaviors.
|
||||
For example in Kotlin one can define a separate class which represents some entity without any operations,
|
||||
ex. a complex number:
|
||||
One possible solution to these problems is to divorce numerical representations from behaviors. For example in Kotlin
|
||||
one can define a separate class representing some entity without any operations, ex. a complex number:
|
||||
|
||||
```kotlin
|
||||
data class Complex(val re: Double, val im: Double)
|
||||
@ -28,9 +27,10 @@ object ComplexOperations {
|
||||
}
|
||||
```
|
||||
|
||||
In Java, applying such external operations could be very cumbersome, but Kotlin has a unique feature which allows us
|
||||
implement this naturally: [extensions with receivers](https://kotlinlang.org/docs/reference/extensions.html#extension-functions).
|
||||
In Kotlin, an operation on complex number could be implemented as:
|
||||
In Java, applying such external operations could be cumbersome, but Kotlin has a unique feature that allows us
|
||||
implement this
|
||||
naturally: [extensions with receivers](https://kotlinlang.org/docs/reference/extensions.html#extension-functions). In
|
||||
Kotlin, an operation on complex number could be implemented as:
|
||||
|
||||
```kotlin
|
||||
with(ComplexOperations) { c1 + c2 - c3 }
|
||||
@ -52,20 +52,20 @@ In KMath, contexts are not only responsible for operations, but also for raw obj
|
||||
|
||||
### Type classes
|
||||
|
||||
An obvious candidate to get more or less the same functionality is the type class, which allows one to bind a behavior to
|
||||
a specific type without modifying the type itself. On the plus side, type classes do not require explicit context
|
||||
An obvious candidate to get more or less the same functionality is the type class, which allows one to bind a behavior
|
||||
to a specific type without modifying the type itself. On the plus side, type classes do not require explicit context
|
||||
declaration, so the code looks cleaner. On the minus side, if there are different sets of behaviors for the same types,
|
||||
it is impossible to combine them into one module. Also, unlike type classes, context can have parameters or even
|
||||
state. For example in KMath, sizes and strides for `NDElement` or `Matrix` could be moved to context to optimize
|
||||
performance in case of a large amount of structures.
|
||||
it is impossible to combine them into one module. Also, unlike type classes, context can have parameters or even state.
|
||||
For example in KMath, sizes and strides for `NDElement` or `Matrix` could be moved to context to optimize performance in
|
||||
case of a large amount of structures.
|
||||
|
||||
### Wildcard imports and importing-on-demand
|
||||
|
||||
Sometimes, one may wish to use a single context throughout a file. In this case, is possible to import all members
|
||||
from a package or file, via `import context.complex.*`. Effectively, this is the same as enclosing an entire file
|
||||
with a single context. However when using multiple contexts, this technique can introduce operator ambiguity, due to
|
||||
namespace pollution. If there are multiple scoped contexts which define the same operation, it is still possible to
|
||||
to import specific operations as needed, without using an explicit context with extension functions, for example:
|
||||
Sometimes, one may wish to use a single context throughout a file. In this case, is possible to import all members from
|
||||
a package or file, via `import context.complex.*`. Effectively, this is the same as enclosing an entire file with a
|
||||
single context. However, when using multiple contexts, this technique can introduce operator ambiguity, due to namespace
|
||||
pollution. If there are multiple scoped contexts that define the same operation, it is still possible to import
|
||||
specific operations as needed, without using an explicit context with extension functions, for example:
|
||||
|
||||
```
|
||||
import context.complex.op1
|
||||
|
1020
docs/diagrams/core.puml
Normal file
@ -1,26 +1,24 @@
|
||||
# Expressions
|
||||
|
||||
**Experimental: this API is in early stage and could change any time**
|
||||
|
||||
Expressions is an experimental feature which allows to construct lazily or immediately calculated parametric mathematical
|
||||
Expressions is a feature, which allows constructing lazily or immediately calculated parametric mathematical
|
||||
expressions.
|
||||
|
||||
The potential use-cases for it (so far) are following:
|
||||
|
||||
* Lazy evaluation (in general simple lambda is better, but there are some border cases)
|
||||
* lazy evaluation (in general simple lambda is better, but there are some border cases);
|
||||
* automatic differentiation in single-dimension and in multiple dimensions;
|
||||
* generation of mathematical syntax trees with subsequent code generation for other languages;
|
||||
* symbolic computations, especially differentiation (and some other actions with `kmath-symja` integration with
|
||||
Symja's `IExpr`—integration, simplification, and more);
|
||||
* visualization with `kmath-jupyter`.
|
||||
|
||||
* Automatic differentiation in single-dimension and in multiple dimensions
|
||||
|
||||
* Generation of mathematical syntax trees with subsequent code generation for other languages
|
||||
|
||||
* Maybe symbolic computations (needs additional research)
|
||||
|
||||
The workhorse of this API is `Expression` interface which exposes single `operator fun invoke(arguments: Map<String, T>): T`
|
||||
method. `ExpressionContext` is used to generate expressions and introduce variables.
|
||||
The workhorse of this API is `Expression` interface, which exposes
|
||||
single `operator fun invoke(arguments: Map<Symbol, T>): T`
|
||||
method. `ExpressionAlgebra` is used to generate expressions and introduce variables.
|
||||
|
||||
Currently there are two implementations:
|
||||
|
||||
* Generic `ExpressionField` in `kmath-core` which allows construction of custom lazy expressions
|
||||
|
||||
* Auto-differentiation expression in `kmath-commons` module allows to use full power of `DerivativeStructure`
|
||||
from commons-math. **TODO: add example**
|
||||
* Auto-differentiation expression in `kmath-commons` module allows using full power of `DerivativeStructure`
|
||||
from commons-math. **TODO: add example**
|
||||
|
@ -1,14 +0,0 @@
|
||||
# Features
|
||||
|
||||
* [Algebra](algebra.md) - [Context-based](contexts.md) operations on different primitives and structures.
|
||||
|
||||
* [NDStructures](nd-structure.md)
|
||||
|
||||
* [Linear algebra](linear.md) - Matrices, operations and linear equations solving. To be moved to separate module. Currently supports basic
|
||||
api and multiple library back-ends.
|
||||
|
||||
* [Histograms](histograms.md) - Multidimensional histogram calculation and operations.
|
||||
|
||||
* [Expressions](expressions.md)
|
||||
|
||||
* Commons math integration
|
@ -1,4 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!--
|
||||
- Copyright 2018-2024 KMath contributors.
|
||||
- Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
@ -13,27 +18,30 @@
|
||||
version="1.1"><metadata
|
||||
id="metadata8"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs6"><clipPath
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata>
|
||||
<defs
|
||||
id="defs6"><clipPath
|
||||
id="clipPath24"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path22"
|
||||
d="M 0,1590 H 6720 V 4400 H 0 Z" /></clipPath><clipPath
|
||||
id="clipPath36"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="M 0,1590 H 6720 V 4400 H 0 Z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath36"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path34"
|
||||
d="M 3410,0 H 6720 V 1590 H 3410 Z" /></clipPath></defs><g
|
||||
transform="matrix(1.3333333,0,0,-1.3333333,0,586.66667)"
|
||||
id="g10"><g
|
||||
d="M 3410,0 H 6720 V 1590 H 3410 Z" /></clipPath></defs>
|
||||
<g
|
||||
transform="matrix(1.3333333,0,0,-1.3333333,0,586.66667)"
|
||||
id="g10"><g
|
||||
transform="scale(0.1)"
|
||||
id="g12"><path
|
||||
id="path14"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 1299.34,651.602 h 4653.75 v 3208.87 H 1299.34 Z" /><path
|
||||
id="path16"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 1651.48,1093.71 h 4076.99 v 114.609 H 1651.48 Z" /><g
|
||||
id="g18"><g
|
||||
id="path16"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 1651.48,1093.71 h 4076.99 v 114.609 H 1651.48 Z"/><g
|
||||
id="g18"><g
|
||||
clip-path="url(#clipPath24)"
|
||||
id="g20"><g
|
||||
transform="matrix(6720,0,0,2810.4,0,1589.6)"
|
||||
@ -45,7 +53,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g30"><g
|
||||
id="g30"><g
|
||||
clip-path="url(#clipPath36)"
|
||||
id="g32"><g
|
||||
transform="matrix(3312,0,0,1591.2,3410,-1.19998)"
|
||||
|
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 249 KiB |
@ -1,4 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!--
|
||||
- Copyright 2018-2024 KMath contributors.
|
||||
- Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
@ -13,35 +18,37 @@
|
||||
version="1.1"><metadata
|
||||
id="metadata8"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs6"><clipPath
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata>
|
||||
<defs
|
||||
id="defs6"><clipPath
|
||||
id="clipPath32"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path30"
|
||||
d="M 1780,1750 H 3830 V 3800 H 1780 Z" /></clipPath></defs><g
|
||||
transform="matrix(1.3333333,0,0,-1.3333333,0,633.33333)"
|
||||
id="g10"><g
|
||||
d="M 1780,1750 H 3830 V 3800 H 1780 Z" /></clipPath></defs>
|
||||
<g
|
||||
transform="matrix(1.3333333,0,0,-1.3333333,0,633.33333)"
|
||||
id="g10"><g
|
||||
transform="scale(0.1)"
|
||||
id="g12"><path
|
||||
id="path14"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="M 318.789,2616.17 6643.05,4723.79 c 239.45,79.76 496.44,-48.75 576.29,-288.17 79.8,-239.41 -48.72,-496.4 -288.13,-576.21 L 606.949,1751.84 c -239.449,-79.81 -496.437,48.71 -576.2888,288.12 -79.8008,239.45 48.7187,496.45 288.1288,576.21 z" /><path
|
||||
id="path16"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="M 3751.56,538.199 6636.91,4443.95 c 109.22,147.89 316.21,178.98 464.11,69.76 147.89,-109.22 178.98,-316.21 69.76,-464.06 L 4285.43,143.91 C 4176.17,-3.98047 3969.18,-35.0781 3821.29,74.1406 3673.44,183.359 3642.3,390.309 3751.56,538.199 Z" /><path
|
||||
id="path18"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="M 1400.43,708.48 H 6418.24 V 4168.4 H 1400.43 Z" /><path
|
||||
id="path20"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 6145.16,1753.83 h -358.6 V 3271.02 L 5158.28,1753.83 H 5005 L 4379.69,3271.02 V 1753.83 h -358.6 v 2044.53 h 505.79 l 554.68,-1345.63 557.97,1345.63 h 505.63 z" /><path
|
||||
id="path22"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 1780.12,1185.24 h 4395.94 v 123.551 H 1780.12 Z" /><path
|
||||
id="path24"
|
||||
style="fill:none;stroke:#000000;stroke-width:22.00740051;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 1780.12,3798.09 c 0,-2044.73 0,-2044.73 0,-2044.73 H 3824.84 L 2806.17,2778.24 3824.84,3798.09" /><g
|
||||
id="g26"><g
|
||||
id="path16"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="M 3751.56,538.199 6636.91,4443.95 c 109.22,147.89 316.21,178.98 464.11,69.76 147.89,-109.22 178.98,-316.21 69.76,-464.06 L 4285.43,143.91 C 4176.17,-3.98047 3969.18,-35.0781 3821.29,74.1406 3673.44,183.359 3642.3,390.309 3751.56,538.199 Z"/><path
|
||||
id="path18"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="M 1400.43,708.48 H 6418.24 V 4168.4 H 1400.43 Z"/><path
|
||||
id="path20"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 6145.16,1753.83 h -358.6 V 3271.02 L 5158.28,1753.83 H 5005 L 4379.69,3271.02 V 1753.83 h -358.6 v 2044.53 h 505.79 l 554.68,-1345.63 557.97,1345.63 h 505.63 z"/><path
|
||||
id="path22"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 1780.12,1185.24 h 4395.94 v 123.551 H 1780.12 Z"/><path
|
||||
id="path24"
|
||||
style="fill:none;stroke:#000000;stroke-width:22.00740051;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 1780.12,3798.09 c 0,-2044.73 0,-2044.73 0,-2044.73 H 3824.84 L 2806.17,2778.24 3824.84,3798.09"/><g
|
||||
id="g26"><g
|
||||
clip-path="url(#clipPath32)"
|
||||
id="g28"><g
|
||||
transform="matrix(2052,0,0,2052,1780,1748)"
|
||||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 19 KiB |
@ -1,4 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!--
|
||||
- Copyright 2018-2024 KMath contributors.
|
||||
- Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
@ -13,35 +18,40 @@
|
||||
version="1.1"><metadata
|
||||
id="metadata8"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs6"><clipPath
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata>
|
||||
<defs
|
||||
id="defs6"><clipPath
|
||||
id="clipPath24"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path22"
|
||||
d="M 0,3010 H 6470 V 4280 H 0 Z" /></clipPath><clipPath
|
||||
id="clipPath36"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="M 0,3010 H 6470 V 4280 H 0 Z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath36"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path34"
|
||||
d="M 0,1590 H 7000 V 3010 H 0 Z" /></clipPath><clipPath
|
||||
id="clipPath48"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="M 0,1590 H 7000 V 3010 H 0 Z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath48"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path46"
|
||||
d="m 0,1580 h 6470 v 10 H 0 Z" /></clipPath><clipPath
|
||||
id="clipPath60"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 0,1580 h 6470 v 10 H 0 Z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath60"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path58"
|
||||
d="M 3280,0 H 6460 V 1580 H 3280 Z" /></clipPath></defs><g
|
||||
transform="matrix(1.3333333,0,0,-1.3333333,0,570.66667)"
|
||||
id="g10"><g
|
||||
d="M 3280,0 H 6460 V 1580 H 3280 Z" /></clipPath></defs>
|
||||
<g
|
||||
transform="matrix(1.3333333,0,0,-1.3333333,0,570.66667)"
|
||||
id="g10"><g
|
||||
transform="scale(0.1)"
|
||||
id="g12"><path
|
||||
id="path14"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 791.328,957.73 h 6401.56 V 3245.31 H 791.328 Z" /><path
|
||||
id="path16"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 1049.45,1214.42 h 2988.24 v 86.9883 H 1049.45 Z" /><g
|
||||
id="g18"><g
|
||||
id="path16"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 1049.45,1214.42 h 2988.24 v 86.9883 H 1049.45 Z"/><g
|
||||
id="g18"><g
|
||||
clip-path="url(#clipPath24)"
|
||||
id="g20"><g
|
||||
transform="matrix(6470.4,0,0,1272,0,3008)"
|
||||
@ -53,7 +63,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g30"><g
|
||||
id="g30"><g
|
||||
clip-path="url(#clipPath36)"
|
||||
id="g32"><g
|
||||
transform="matrix(7000.8,0,0,1420.8,0,1589.2)"
|
||||
@ -65,7 +75,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g42"><g
|
||||
id="g42"><g
|
||||
clip-path="url(#clipPath48)"
|
||||
id="g44"><g
|
||||
transform="matrix(6470.4,0,0,12,0,1578)"
|
||||
@ -77,7 +87,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g54"><g
|
||||
id="g54"><g
|
||||
clip-path="url(#clipPath60)"
|
||||
id="g56"><g
|
||||
transform="matrix(3180,0,0,1581.6,3280,-1.59972)"
|
||||
|
Before Width: | Height: | Size: 278 KiB After Width: | Height: | Size: 278 KiB |
@ -1,4 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!--
|
||||
- Copyright 2018-2024 KMath contributors.
|
||||
- Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
@ -13,123 +18,144 @@
|
||||
version="1.1"><metadata
|
||||
id="metadata8"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs6"><clipPath
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata>
|
||||
<defs
|
||||
id="defs6"><clipPath
|
||||
id="clipPath40"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path38"
|
||||
d="m 2370,2780 h 1370 v 10 H 2370 Z" /></clipPath><clipPath
|
||||
id="clipPath52"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 2370,2780 h 1370 v 10 H 2370 Z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath52"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path50"
|
||||
d="m 5630,2780 h 860 v 10 h -860 z" /></clipPath><clipPath
|
||||
id="clipPath64"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 5630,2780 h 860 v 10 h -860 z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath64"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path62"
|
||||
d="m 970,2690 h 1300 v 90 H 970 Z" /></clipPath><clipPath
|
||||
id="clipPath76"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 970,2690 h 1300 v 90 H 970 Z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath76"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path74"
|
||||
d="m 2370,2690 h 1370 v 90 H 2370 Z" /></clipPath><clipPath
|
||||
id="clipPath88"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 2370,2690 h 1370 v 90 H 2370 Z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath88"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path86"
|
||||
d="m 5630,2690 h 860 v 90 h -860 z" /></clipPath><clipPath
|
||||
id="clipPath100"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 5630,2690 h 860 v 90 h -860 z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath100"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path98"
|
||||
d="m 970,2460 h 1300 v 230 H 970 Z" /></clipPath><clipPath
|
||||
id="clipPath112"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 970,2460 h 1300 v 230 H 970 Z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath112"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path110"
|
||||
d="m 2370,2460 h 1370 v 230 H 2370 Z" /></clipPath><clipPath
|
||||
id="clipPath124"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 2370,2460 h 1370 v 230 H 2370 Z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath124"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path122"
|
||||
d="m 4900,2460 h 620 v 230 h -620 z" /></clipPath><clipPath
|
||||
id="clipPath136"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 4900,2460 h 620 v 230 h -620 z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath136"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path134"
|
||||
d="m 5630,2460 h 860 v 230 h -860 z" /></clipPath><clipPath
|
||||
id="clipPath148"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 5630,2460 h 860 v 230 h -860 z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath148"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path146"
|
||||
d="m 970,1480 h 1300 v 980 H 970 Z" /></clipPath><clipPath
|
||||
id="clipPath160"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 970,1480 h 1300 v 980 H 970 Z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath160"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path158"
|
||||
d="m 2370,1480 h 1370 v 980 H 2370 Z" /></clipPath><clipPath
|
||||
id="clipPath172"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 2370,1480 h 1370 v 980 H 2370 Z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath172"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path170"
|
||||
d="m 3920,1480 h 860 v 980 h -860 z" /></clipPath><clipPath
|
||||
id="clipPath184"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 3920,1480 h 860 v 980 h -860 z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath184"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path182"
|
||||
d="m 4900,1480 h 620 v 980 h -620 z" /></clipPath><clipPath
|
||||
id="clipPath196"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 4900,1480 h 620 v 980 h -620 z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath196"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path194"
|
||||
d="m 5630,1480 h 860 v 980 h -860 z" /></clipPath><clipPath
|
||||
id="clipPath208"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 5630,1480 h 860 v 980 h -860 z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath208"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path206"
|
||||
d="m 2370,1470 h 1370 v 10 H 2370 Z" /></clipPath><clipPath
|
||||
id="clipPath220"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 2370,1470 h 1370 v 10 H 2370 Z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath220"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path218"
|
||||
d="m 3920,1470 h 860 v 10 h -860 z" /></clipPath><clipPath
|
||||
id="clipPath232"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 3920,1470 h 860 v 10 h -860 z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath232"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path230"
|
||||
d="m 4900,1470 h 620 v 10 h -620 z" /></clipPath><clipPath
|
||||
id="clipPath244"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 4900,1470 h 620 v 10 h -620 z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath244"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path242"
|
||||
d="m 5630,1470 h 860 v 10 h -860 z" /></clipPath><clipPath
|
||||
id="clipPath256"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 5630,1470 h 860 v 10 h -860 z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath256"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path254"
|
||||
d="m 3920,1450 h 860 v 20 h -860 z" /></clipPath><clipPath
|
||||
id="clipPath268"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
d="m 3920,1450 h 860 v 20 h -860 z" /></clipPath>
|
||||
<clipPath
|
||||
id="clipPath268"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path266"
|
||||
d="m 4900,1450 h 620 v 20 h -620 z" /></clipPath></defs><g
|
||||
transform="matrix(1.3333333,0,0,-1.3333333,0,529.33333)"
|
||||
id="g10"><g
|
||||
d="m 4900,1450 h 620 v 20 h -620 z" /></clipPath></defs>
|
||||
<g
|
||||
transform="matrix(1.3333333,0,0,-1.3333333,0,529.33333)"
|
||||
id="g10"><g
|
||||
transform="scale(0.1)"
|
||||
id="g12"><path
|
||||
id="path14"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="M 265.859,2205.39 5500.51,3949.84 c 198.16,66.06 410.9,-40.31 476.99,-238.51 66.05,-198.17 -40.31,-410.86 -238.48,-476.92 L 504.379,1489.96 c -198.168,-66.05 -410.8985,40.31 -476.9571,238.48 -66.0938,198.16 40.2773,410.9 238.4371,476.95 z" /><path
|
||||
id="path16"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 3096.33,444.379 2388.2,3232.811 c 90.43,122.38 261.76,148.12 384.18,57.73 122.38,-90.39 148.13,-261.72 57.74,-384.1 L 3538.2,117.969 C 3447.77,-4.41016 3276.45,-30.1602 3154.06,60.2305 3031.64,150.66 3005.9,321.949 3096.33,444.379 Z" /><path
|
||||
id="path18"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 734.691,901.211 h 5982.5 v 2109.69 h -5982.5 z" /><path
|
||||
id="path20"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 3724.45,1489.53 h -225.93 v 956.09 l -395.94,-956.09 h -96.56 l -394.07,956.09 v -956.09 h -225.93 v 1288.28 h 318.59 l 349.69,-847.97 351.4,847.97 h 318.75 z" /><path
|
||||
id="path22"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="M 4767.23,1489.53 H 4564.41 V 1590 c -72.11,-82.42 -172.5,-123.59 -301.25,-123.59 -85,0 -160.39,27.34 -226.09,82.03 -65.62,54.68 -98.44,130.31 -98.44,226.87 0,99.14 32.5,174.46 97.5,225.94 65.08,51.56 140.78,77.34 227.03,77.34 132.58,0 233.01,-39.92 301.25,-119.68 v 139.06 c 0,54.06 -19.96,96.48 -59.84,127.34 -39.92,30.94 -92.73,46.41 -158.44,46.41 -104.29,0 -196.33,-39.3 -276.09,-117.81 L 3986.91,2295 c 105.63,100.39 236.29,150.62 392.04,150.62 114.68,0 208.04,-27.1 280.15,-81.24 72.07,-54.07 108.13,-139.65 108.13,-256.72 z m -424.85,115.94 c 101.64,0 175.67,32.19 222.03,96.56 v 140.94 c -46.36,64.37 -120.39,96.56 -222.03,96.56 -58.04,0 -105.74,-15.47 -143.12,-46.41 -37.31,-30.85 -55.94,-71.36 -55.94,-121.56 0,-50.23 18.63,-90.47 55.94,-120.78 37.38,-30.23 85.08,-45.31 143.12,-45.31 z" /><path
|
||||
id="path24"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 5308.32,1466.41 c -78.55,0 -138.12,20.58 -178.75,61.71 -40.55,41.26 -60.78,100.47 -60.78,177.66 v 538.91 h -154.53 v 177.65 h 154.53 v 255 h 202.81 v -255 h 189.22 V 2244.69 H 5271.6 v -488.6 c 0,-33.55 7.7,-60.31 23.13,-80.31 15.5,-19.92 37.42,-29.84 65.78,-29.84 41.13,0 71.4,10.94 90.78,32.81 l 48.28,-152.5 c -42.5,-39.88 -106.25,-59.84 -191.25,-59.84 z" /><path
|
||||
id="path26"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 6477.38,1489.53 h -202.65 v 587.19 c 0,68.2 -16.49,116.8 -49.38,145.78 -32.81,28.95 -79.49,43.44 -140,43.44 -47.62,0 -92.65,-12.27 -135.15,-36.72 -42.5,-24.49 -77.31,-54.06 -104.38,-88.75 v -650.94 h -202.66 v 1288.28 h 202.66 V 2295 c 34.77,41.13 81.45,76.48 140,106.09 58.63,29.69 122.07,44.53 190.31,44.53 200.82,0 301.25,-98.55 301.25,-295.62 z" /><path
|
||||
id="path28"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 973.949,1128.48 h 2769.84 v 80.6211 H 973.949 Z" /><path
|
||||
id="path30"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 978.828,2781.72 c 0,-1292.5 0,-1292.5 0,-1292.5 H 2262.3 l -639.45,647.85 639.45,644.65" /><path
|
||||
id="path32"
|
||||
style="fill:none;stroke:#000000;stroke-width:13.86260033;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 978.828,2781.72 c 0,-1292.5 0,-1292.5 0,-1292.5 H 2262.3 l -639.45,647.85 639.45,644.65" /><g
|
||||
id="g34"><g
|
||||
id="path16"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 3096.33,444.379 2388.2,3232.811 c 90.43,122.38 261.76,148.12 384.18,57.73 122.38,-90.39 148.13,-261.72 57.74,-384.1 L 3538.2,117.969 C 3447.77,-4.41016 3276.45,-30.1602 3154.06,60.2305 3031.64,150.66 3005.9,321.949 3096.33,444.379 Z"/><path
|
||||
id="path18"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 734.691,901.211 h 5982.5 v 2109.69 h -5982.5 z"/><path
|
||||
id="path20"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 3724.45,1489.53 h -225.93 v 956.09 l -395.94,-956.09 h -96.56 l -394.07,956.09 v -956.09 h -225.93 v 1288.28 h 318.59 l 349.69,-847.97 351.4,847.97 h 318.75 z"/><path
|
||||
id="path22"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="M 4767.23,1489.53 H 4564.41 V 1590 c -72.11,-82.42 -172.5,-123.59 -301.25,-123.59 -85,0 -160.39,27.34 -226.09,82.03 -65.62,54.68 -98.44,130.31 -98.44,226.87 0,99.14 32.5,174.46 97.5,225.94 65.08,51.56 140.78,77.34 227.03,77.34 132.58,0 233.01,-39.92 301.25,-119.68 v 139.06 c 0,54.06 -19.96,96.48 -59.84,127.34 -39.92,30.94 -92.73,46.41 -158.44,46.41 -104.29,0 -196.33,-39.3 -276.09,-117.81 L 3986.91,2295 c 105.63,100.39 236.29,150.62 392.04,150.62 114.68,0 208.04,-27.1 280.15,-81.24 72.07,-54.07 108.13,-139.65 108.13,-256.72 z m -424.85,115.94 c 101.64,0 175.67,32.19 222.03,96.56 v 140.94 c -46.36,64.37 -120.39,96.56 -222.03,96.56 -58.04,0 -105.74,-15.47 -143.12,-46.41 -37.31,-30.85 -55.94,-71.36 -55.94,-121.56 0,-50.23 18.63,-90.47 55.94,-120.78 37.38,-30.23 85.08,-45.31 143.12,-45.31 z"/><path
|
||||
id="path24"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 5308.32,1466.41 c -78.55,0 -138.12,20.58 -178.75,61.71 -40.55,41.26 -60.78,100.47 -60.78,177.66 v 538.91 h -154.53 v 177.65 h 154.53 v 255 h 202.81 v -255 h 189.22 V 2244.69 H 5271.6 v -488.6 c 0,-33.55 7.7,-60.31 23.13,-80.31 15.5,-19.92 37.42,-29.84 65.78,-29.84 41.13,0 71.4,10.94 90.78,32.81 l 48.28,-152.5 c -42.5,-39.88 -106.25,-59.84 -191.25,-59.84 z"/><path
|
||||
id="path26"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 6477.38,1489.53 h -202.65 v 587.19 c 0,68.2 -16.49,116.8 -49.38,145.78 -32.81,28.95 -79.49,43.44 -140,43.44 -47.62,0 -92.65,-12.27 -135.15,-36.72 -42.5,-24.49 -77.31,-54.06 -104.38,-88.75 v -650.94 h -202.66 v 1288.28 h 202.66 V 2295 c 34.77,41.13 81.45,76.48 140,106.09 58.63,29.69 122.07,44.53 190.31,44.53 200.82,0 301.25,-98.55 301.25,-295.62 z"/><path
|
||||
id="path28"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 973.949,1128.48 h 2769.84 v 80.6211 H 973.949 Z"/><path
|
||||
id="path30"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 978.828,2781.72 c 0,-1292.5 0,-1292.5 0,-1292.5 H 2262.3 l -639.45,647.85 639.45,644.65"/><path
|
||||
id="path32"
|
||||
style="fill:none;stroke:#000000;stroke-width:13.86260033;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 978.828,2781.72 c 0,-1292.5 0,-1292.5 0,-1292.5 H 2262.3 l -639.45,647.85 639.45,644.65"/><g
|
||||
id="g34"><g
|
||||
clip-path="url(#clipPath40)"
|
||||
id="g36"><g
|
||||
transform="matrix(1370.4,0,0,12,2370,2778)"
|
||||
@ -141,7 +167,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g46"><g
|
||||
id="g46"><g
|
||||
clip-path="url(#clipPath52)"
|
||||
id="g48"><g
|
||||
transform="matrix(861.6,0,0,12,5630,2778)"
|
||||
@ -153,7 +179,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g58"><g
|
||||
id="g58"><g
|
||||
clip-path="url(#clipPath64)"
|
||||
id="g60"><g
|
||||
transform="matrix(1300.8,0,0,91.2,970,2688.8)"
|
||||
@ -165,7 +191,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g70"><g
|
||||
id="g70"><g
|
||||
clip-path="url(#clipPath76)"
|
||||
id="g72"><g
|
||||
transform="matrix(1370.4,0,0,91.2,2370,2688.8)"
|
||||
@ -177,7 +203,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g82"><g
|
||||
id="g82"><g
|
||||
clip-path="url(#clipPath88)"
|
||||
id="g84"><g
|
||||
transform="matrix(861.6,0,0,91.2,5630,2688.8)"
|
||||
@ -189,7 +215,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g94"><g
|
||||
id="g94"><g
|
||||
clip-path="url(#clipPath100)"
|
||||
id="g96"><g
|
||||
transform="matrix(1300.8,0,0,230.4,970,2459.6)"
|
||||
@ -201,7 +227,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g106"><g
|
||||
id="g106"><g
|
||||
clip-path="url(#clipPath112)"
|
||||
id="g108"><g
|
||||
transform="matrix(1370.4,0,0,230.4,2370,2459.6)"
|
||||
@ -213,7 +239,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g118"><g
|
||||
id="g118"><g
|
||||
clip-path="url(#clipPath124)"
|
||||
id="g120"><g
|
||||
transform="matrix(621.6,0,0,230.4,4900,2459.6)"
|
||||
@ -225,7 +251,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g130"><g
|
||||
id="g130"><g
|
||||
clip-path="url(#clipPath136)"
|
||||
id="g132"><g
|
||||
transform="matrix(861.6,0,0,230.4,5630,2459.6)"
|
||||
@ -237,7 +263,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g142"><g
|
||||
id="g142"><g
|
||||
clip-path="url(#clipPath148)"
|
||||
id="g144"><g
|
||||
transform="matrix(1300.8,0,0,981.6,970,1478.4)"
|
||||
@ -249,7 +275,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g154"><g
|
||||
id="g154"><g
|
||||
clip-path="url(#clipPath160)"
|
||||
id="g156"><g
|
||||
transform="matrix(1370.4,0,0,981.6,2370,1478.4)"
|
||||
@ -261,7 +287,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g166"><g
|
||||
id="g166"><g
|
||||
clip-path="url(#clipPath172)"
|
||||
id="g168"><g
|
||||
transform="matrix(861.6,0,0,981.6,3920,1478.4)"
|
||||
@ -273,7 +299,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g178"><g
|
||||
id="g178"><g
|
||||
clip-path="url(#clipPath184)"
|
||||
id="g180"><g
|
||||
transform="matrix(621.6,0,0,981.6,4900,1478.4)"
|
||||
@ -285,7 +311,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g190"><g
|
||||
id="g190"><g
|
||||
clip-path="url(#clipPath196)"
|
||||
id="g192"><g
|
||||
transform="matrix(861.6,0,0,981.6,5630,1478.4)"
|
||||
@ -297,7 +323,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g202"><g
|
||||
id="g202"><g
|
||||
clip-path="url(#clipPath208)"
|
||||
id="g204"><g
|
||||
transform="matrix(1370.4,0,0,12,2370,1468)"
|
||||
@ -309,7 +335,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g214"><g
|
||||
id="g214"><g
|
||||
clip-path="url(#clipPath220)"
|
||||
id="g216"><g
|
||||
transform="matrix(861.6,0,0,12,3920,1468)"
|
||||
@ -321,7 +347,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g226"><g
|
||||
id="g226"><g
|
||||
clip-path="url(#clipPath232)"
|
||||
id="g228"><g
|
||||
transform="matrix(621.6,0,0,12,4900,1468)"
|
||||
@ -333,7 +359,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g238"><g
|
||||
id="g238"><g
|
||||
clip-path="url(#clipPath244)"
|
||||
id="g240"><g
|
||||
transform="matrix(861.6,0,0,12,5630,1468)"
|
||||
@ -345,7 +371,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g250"><g
|
||||
id="g250"><g
|
||||
clip-path="url(#clipPath256)"
|
||||
id="g252"><g
|
||||
transform="matrix(861.6,0,0,21.6,3920,1448.4)"
|
||||
@ -357,7 +383,7 @@
|
||||
style="image-rendering:optimizeSpeed"
|
||||
height="1"
|
||||
width="1" /></g></g></g><g
|
||||
id="g262"><g
|
||||
id="g262"><g
|
||||
clip-path="url(#clipPath268)"
|
||||
id="g264"><g
|
||||
transform="matrix(621.6,0,0,21.6,4900,1448.4)"
|
||||
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 118 KiB |
@ -1,19 +1,36 @@
|
||||
## Basic linear algebra layout
|
||||
|
||||
KMath support for linear algebra organized in a context-oriented way. Meaning that operations are in most cases declared
|
||||
in context classes, and are not the members of classes that store data. This allows more flexible approach to maintain multiple
|
||||
back-ends. The new operations added as extensions to contexts instead of being member functions of data structures.
|
||||
KMath support for linear algebra organized in a context-oriented way, which means that operations are in most cases
|
||||
declared in context classes, and are not the members of classes that store data. This allows more flexible approach to
|
||||
maintain multiple back-ends. The new operations added as extensions to contexts instead of being member functions of
|
||||
data structures.
|
||||
|
||||
Two major contexts used for linear algebra and hyper-geometry:
|
||||
The main context for linear algebra over matrices and vectors is `LinearSpace`, which defines addition and dot products
|
||||
of matrices and vectors:
|
||||
|
||||
* `VectorSpace` forms a mathematical space on top of array-like structure (`Buffer` and its type alias `Point` used for geometry).
|
||||
```kotlin
|
||||
import space.kscience.kmath.linear.*
|
||||
|
||||
* `MatrixContext` forms a space-like context for 2d-structures. It does not store matrix size and therefore does not implement
|
||||
`Space` interface (it is impossible to create zero element without knowing the matrix size).
|
||||
LinearSpace.Companion.real {
|
||||
val vec = buildVector(10) { i -> i.toDouble() }
|
||||
val mat = buildMatrix(10, 10) { i, j -> i.toDouble() + j }
|
||||
|
||||
## Vector spaces
|
||||
// Addition
|
||||
vec + vec
|
||||
mat + mat
|
||||
|
||||
// Multiplication by scalar
|
||||
vec * 2.0
|
||||
mat * 2.0
|
||||
|
||||
## Matrix operations
|
||||
// Dot product
|
||||
mat dot vec
|
||||
mat dot mat
|
||||
}
|
||||
```
|
||||
|
||||
## Back-end overview
|
||||
## Backends overview
|
||||
|
||||
### EJML
|
||||
|
||||
### Commons Math
|
||||
|
@ -8,23 +8,27 @@ One of the most sought after features of mathematical libraries is the high-perf
|
||||
structures. In `kmath` performance depends on which particular context was used for operation.
|
||||
|
||||
Let us consider following contexts:
|
||||
|
||||
```kotlin
|
||||
// automatically build context most suited for given type.
|
||||
val autoField = NDField.auto(RealField, dim, dim)
|
||||
// specialized nd-field for Double. It works as generic Double field as well
|
||||
val autoField = NDField.auto(DoubleField, dim, dim)
|
||||
// specialized nd-field for Double. It works as generic Double field as well.
|
||||
val specializedField = NDField.real(dim, dim)
|
||||
//A generic boxing field. It should be used for objects, not primitives.
|
||||
val genericField = NDField.buffered(RealField, dim, dim)
|
||||
val genericField = NDField.buffered(DoubleField, dim, dim)
|
||||
```
|
||||
Now let us perform several tests and see which implementation is best suited for each case:
|
||||
|
||||
Now let us perform several tests and see, which implementation is best suited for each case:
|
||||
|
||||
## Test case
|
||||
|
||||
In order to test performance we will take 2d-structures with `dim = 1000` and add a structure filled with `1.0`
|
||||
To test performance we will take 2d-structures with `dim = 1000` and add a structure filled with `1.0`
|
||||
to it `n = 1000` times.
|
||||
|
||||
## Specialized
|
||||
|
||||
The code to run this looks like:
|
||||
|
||||
```kotlin
|
||||
specializedField.run {
|
||||
var res: NDBuffer<Double> = one
|
||||
@ -33,13 +37,16 @@ The code to run this looks like:
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The performance of this code is the best of all tests since it inlines all operations and is specialized for operation
|
||||
with doubles. We will measure everything else relative to this one, so time for this test will be `1x` (real time
|
||||
on my computer is about 4.5 seconds). The only problem with this approach is that it requires to specify type
|
||||
from the beginning. Everyone do so anyway, so it is the recommended approach.
|
||||
on my computer is about 4.5 seconds). The only problem with this approach is that it requires specifying type
|
||||
from the beginning. Everyone does so anyway, so it is the recommended approach.
|
||||
|
||||
## Automatic
|
||||
|
||||
Let's do the same with automatic field inference:
|
||||
|
||||
```kotlin
|
||||
autoField.run {
|
||||
var res = one
|
||||
@ -48,13 +55,16 @@ Let's do the same with automatic field inference:
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Ths speed of this operation is approximately the same as for specialized case since `NDField.auto` just
|
||||
returns the same `RealNDField` in this case. Of course it is usually better to use specialized method to be sure.
|
||||
returns the same `RealNDField` in this case. Of course, it is usually better to use specialized method to be sure.
|
||||
|
||||
## Lazy
|
||||
|
||||
Lazy field does not produce a structure when asked, instead it generates an empty structure and fills it on-demand
|
||||
using coroutines to parallelize computations.
|
||||
When one calls
|
||||
|
||||
```kotlin
|
||||
lazyField.run {
|
||||
var res = one
|
||||
@ -63,12 +73,14 @@ When one calls
|
||||
}
|
||||
}
|
||||
```
|
||||
The result will be calculated almost immediately but the result will be empty. In order to get the full result
|
||||
|
||||
The result will be calculated almost immediately but the result will be empty. To get the full result
|
||||
structure one needs to call all its elements. In this case computation overhead will be huge. So this field never
|
||||
should be used if one expects to use the full result structure. Though if one wants only small fraction, it could
|
||||
save a lot of time.
|
||||
|
||||
This field still could be used with reasonable performance if call code is changed:
|
||||
|
||||
```kotlin
|
||||
lazyField.run {
|
||||
val res = one.map {
|
||||
@ -82,10 +94,13 @@ This field still could be used with reasonable performance if call code is chang
|
||||
res.elements().forEach { it.second }
|
||||
}
|
||||
```
|
||||
|
||||
In this case it completes in about `4x-5x` time due to boxing.
|
||||
|
||||
## Boxing
|
||||
|
||||
The boxing field produced by
|
||||
|
||||
```kotlin
|
||||
genericField.run {
|
||||
var res: NDBuffer<Double> = one
|
||||
@ -94,18 +109,22 @@ The boxing field produced by
|
||||
}
|
||||
}
|
||||
```
|
||||
obviously is the slowest one, because it requires to box and unbox the `double` on each operation. It takes about
|
||||
|
||||
is the slowest one, because it requires boxing and unboxing the `double` on each operation. It takes about
|
||||
`15x` time (**TODO: there seems to be a problem here, it should be slow, but not that slow**). This field should
|
||||
never be used for primitives.
|
||||
|
||||
## Element operation
|
||||
|
||||
Let us also check the speed for direct operations on elements:
|
||||
|
||||
```kotlin
|
||||
var res = genericField.one
|
||||
repeat(n) {
|
||||
res += 1.0
|
||||
}
|
||||
```
|
||||
|
||||
One would expect to be at least as slow as field operation, but in fact, this one takes only `2x` time to complete.
|
||||
It happens, because in this particular case it does not use actual `NDField` but instead calculated directly
|
||||
via extension function.
|
||||
@ -114,13 +133,18 @@ via extension function.
|
||||
|
||||
Usually it is bad idea to compare the direct numerical operation performance in different languages, but it hard to
|
||||
work completely without frame of reference. In this case, simple numpy code:
|
||||
|
||||
```python
|
||||
import numpy as np
|
||||
|
||||
res = np.ones((1000,1000))
|
||||
for i in range(1000):
|
||||
res = res + 1.0
|
||||
```
|
||||
gives the completion time of about `1.1x`, which means that specialized kotlin code in fact is working faster (I think it is
|
||||
|
||||
gives the completion time of about `1.1x`, which means that specialized kotlin code in fact is working faster (I think
|
||||
it is
|
||||
because better memory management). Of course if one writes `res += 1.0`, the performance will be different,
|
||||
but it would be differenc case, because numpy overrides `+=` with in-place operations. In-place operations are
|
||||
but it would be different case, because numpy overrides `+=` with in-place operations. In-place operations are
|
||||
available in `kmath` with `MutableNDStructure` but there is no field for it (one can still work with mapping
|
||||
functions).
|
223
docs/polynomials.md
Normal file
@ -0,0 +1,223 @@
|
||||
# Polynomials and Rational Functions
|
||||
|
||||
KMath provides a way to work with uni- and multivariate polynomials and rational functions. It includes full support of
|
||||
arithmetic operations of integers, **constants** (elements of ring polynomials are build over), variables (for certain
|
||||
multivariate implementations), polynomials and rational functions encapsulated in so-called **polynomial space** and *
|
||||
*rational function space** and some other utilities such as algebraic differentiation and substitution.
|
||||
|
||||
## Concrete realizations
|
||||
|
||||
There are 3 approaches to represent polynomials:
|
||||
|
||||
1. For univariate polynomials one can represent and store polynomial as a list of coefficients for each power of the
|
||||
variable. I.e. polynomial $a_0 + \dots + a_n x^n $ can be represented as a finite sequence $(a_0; \dots; a_n)$. (
|
||||
Compare to sequential definition of polynomials.)
|
||||
2. For multivariate polynomials one can represent and store polynomial as a matching (in programming it is called "map"
|
||||
or "dictionary", in math it is
|
||||
called [functional relation](https://en.wikipedia.org/wiki/Binary_relation#Special_types_of_binary_relations)) of
|
||||
each "**term signature**" (that describes what variables and in what powers appear in the term) with corresponding
|
||||
coefficient of the term. But there are 2 possible approaches of term signature representation:
|
||||
1. One can number all the variables, so term signature can be represented as a sequence describing powers of the
|
||||
variables. I.e. signature of term $c \\; x_0^{d_0} \dots x_n^{d_n} $ (for natural or zero $d_i $) can be
|
||||
represented as a finite sequence $(d_0; \dots; d_n)$.
|
||||
2. One can represent variables as objects ("**labels**"), so term signature can be also represented as a matching of
|
||||
each appeared variable with its power in the term. I.e. signature of term $c \\; x_0^{d_0} \dots x_n^{d_n} $ (for
|
||||
natural non-zero $d_i $) can be represented as a finite matching $(x_0 \to d_1; \dots; x_n \to d_n)$.
|
||||
|
||||
All that three approaches are implemented by "list", "numbered", and "labeled" versions of polynomials and polynomial
|
||||
spaces respectively. Whereas all rational functions are represented as fractions with corresponding polynomial numerator
|
||||
and denominator, and rational functions' spaces are implemented in the same way as usual field of rational numbers (or
|
||||
more precisely, as any field of fractions over integral domain) should be implemented.
|
||||
|
||||
So here are a bit of details. Let `C` by type of constants. Then:
|
||||
|
||||
1. `ListPolynomial`, `ListPolynomialSpace`, `ListRationalFunction` and `ListRationalFunctionSpace` implement the first
|
||||
scenario. `ListPolynomial` stores polynomial $a_0 + \dots + a_n x^n $ as a coefficients
|
||||
list `listOf(a_0, ..., a_n)` (of type `List<C>`).
|
||||
|
||||
They also have variation `ScalableListPolynomialSpace` that replaces former polynomials and
|
||||
implements `ScaleOperations`.
|
||||
2. `NumberedPolynomial`, `NumberedPolynomialSpace`, `NumberedRationalFunction` and `NumberedRationalFunctionSpace`
|
||||
implement second scenario. `NumberedPolynomial` stores polynomials as structures of type `Map<List<UInt>, C>`.
|
||||
Signatures are stored as `List<UInt>`. To prevent ambiguity signatures should not end with zeros.
|
||||
3. `LabeledPolynomial`, `LabeledPolynomialSpace`, `LabeledRationalFunction` and `LabeledRationalFunctionSpace` implement
|
||||
third scenario using common `Symbol` as variable type. `LabeledPolynomial` stores polynomials as structures of
|
||||
type `Map<Map<Symbol, UInt>, C>`. Signatures are stored as `Map<Symbol, UInt>`. To prevent ambiguity each signature
|
||||
should not map any variable to zero.
|
||||
|
||||
### Example: `ListPolynomial`
|
||||
|
||||
For example, polynomial $2 - 3x + x^2 $ (with `Int` coefficients) is represented
|
||||
|
||||
```kotlin
|
||||
val polynomial: ListPolynomial<Int> = ListPolynomial(listOf(2, -3, 1))
|
||||
// or
|
||||
val polynomial: ListPolynomial<Int> = ListPolynomial(2, -3, 1)
|
||||
```
|
||||
|
||||
All algebraic operations can be used in corresponding space:
|
||||
|
||||
```kotlin
|
||||
val computationResult = Int.algebra.listPolynomialSpace {
|
||||
ListPolynomial(2, -3, 1) + ListPolynomial(0, 6) == ListPolynomial(2, 3, 1)
|
||||
}
|
||||
|
||||
println(computationResult) // true
|
||||
```
|
||||
|
||||
For more see [examples](../examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt).
|
||||
|
||||
### Example: `NumberedPolynomial`
|
||||
|
||||
For example, polynomial $3 + 5 x_1 - 7 x_0^2 x_2 $ (with `Int` coefficients) is represented
|
||||
|
||||
```kotlin
|
||||
val polynomial: NumberedPolynomial<Int> = NumberedPolynomial(
|
||||
mapOf(
|
||||
listOf<UInt>() to 3,
|
||||
listOf(0u, 1u) to 5,
|
||||
listOf(2u, 0u, 1u) to -7,
|
||||
)
|
||||
)
|
||||
// or
|
||||
val polynomial: NumberedPolynomial<Int> = NumberedPolynomial(
|
||||
listOf<UInt>() to 3,
|
||||
listOf(0u, 1u) to 5,
|
||||
listOf(2u, 0u, 1u) to -7,
|
||||
)
|
||||
```
|
||||
|
||||
All algebraic operations can be used in corresponding space:
|
||||
|
||||
```kotlin
|
||||
val computationResult = Int.algebra.numberedPolynomialSpace {
|
||||
NumberedPolynomial(
|
||||
listOf<UInt>() to 3,
|
||||
listOf(0u, 1u) to 5,
|
||||
listOf(2u, 0u, 1u) to -7,
|
||||
) + NumberedPolynomial(
|
||||
listOf(0u, 1u) to -5,
|
||||
listOf(0u, 0u, 0u, 4u) to 4,
|
||||
) == NumberedPolynomial(
|
||||
listOf<UInt>() to 3,
|
||||
listOf(0u, 1u) to 0,
|
||||
listOf(2u, 0u, 1u) to -7,
|
||||
listOf(0u, 0u, 0u, 4u) to 4,
|
||||
)
|
||||
}
|
||||
|
||||
println(computationResult) // true
|
||||
```
|
||||
|
||||
For more see [examples](../examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt).
|
||||
|
||||
### Example: `LabeledPolynomial`
|
||||
|
||||
For example, polynomial $3 + 5 y - 7 x^2 z $ (with `Int` coefficients) is represented
|
||||
|
||||
```kotlin
|
||||
val polynomial: LabeledPolynomial<Int> = LabeledPolynomial(
|
||||
mapOf(
|
||||
mapOf<Symbol, UInt>() to 3,
|
||||
mapOf(y to 1u) to 5,
|
||||
mapOf(x to 2u, z to 1u) to -7,
|
||||
)
|
||||
)
|
||||
// or
|
||||
val polynomial: LabeledPolynomial<Int> = LabeledPolynomial(
|
||||
mapOf<Symbol, UInt>() to 3,
|
||||
mapOf(y to 1u) to 5,
|
||||
mapOf(x to 2u, z to 1u) to -7,
|
||||
)
|
||||
```
|
||||
|
||||
All algebraic operations can be used in corresponding space:
|
||||
|
||||
```kotlin
|
||||
val computationResult = Int.algebra.labeledPolynomialSpace {
|
||||
LabeledPolynomial(
|
||||
listOf<UInt>() to 3,
|
||||
listOf(0u, 1u) to 5,
|
||||
listOf(2u, 0u, 1u) to -7,
|
||||
) + LabeledPolynomial(
|
||||
listOf(0u, 1u) to -5,
|
||||
listOf(0u, 0u, 0u, 4u) to 4,
|
||||
) == LabeledPolynomial(
|
||||
listOf<UInt>() to 3,
|
||||
listOf(0u, 1u) to 0,
|
||||
listOf(2u, 0u, 1u) to -7,
|
||||
listOf(0u, 0u, 0u, 4u) to 4,
|
||||
)
|
||||
}
|
||||
|
||||
println(computationResult) // true
|
||||
```
|
||||
|
||||
For more see [examples](../examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt).
|
||||
|
||||
## Abstract entities (interfaces and abstract classes)
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
Polynomial <|-- ListPolynomial
|
||||
Polynomial <|-- NumberedPolynomial
|
||||
Polynomial <|-- LabeledPolynomial
|
||||
|
||||
RationalFunction <|-- ListRationalFunction
|
||||
RationalFunction <|-- NumberedRationalFunction
|
||||
RationalFunction <|-- LabeledRationalFunction
|
||||
|
||||
Ring <|-- PolynomialSpace
|
||||
PolynomialSpace <|-- MultivariatePolynomialSpace
|
||||
PolynomialSpace <|-- PolynomialSpaceOverRing
|
||||
|
||||
Ring <|-- RationalFunctionSpace
|
||||
RationalFunctionSpace <|-- MultivariateRationalFunctionSpace
|
||||
RationalFunctionSpace <|-- RationalFunctionSpaceOverRing
|
||||
RationalFunctionSpace <|-- RationalFunctionSpaceOverPolynomialSpace
|
||||
RationalFunctionSpace <|-- PolynomialSpaceOfFractions
|
||||
RationalFunctionSpaceOverPolynomialSpace <|-- MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpace
|
||||
MultivariateRationalFunctionSpace <|-- MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpace
|
||||
MultivariateRationalFunctionSpace <|-- MultivariatePolynomialSpaceOfFractions
|
||||
PolynomialSpaceOfFractions <|-- MultivariatePolynomialSpaceOfFractions
|
||||
```
|
||||
|
||||
There are implemented `Polynomial` and `RationalFunction` interfaces as abstractions of polynomials and rational
|
||||
functions respectively (although, there is not a lot of logic in them) and `PolynomialSpace`
|
||||
and `RationalFunctionSpace` (that implement `Ring` interface) as abstractions of polynomials' and rational functions'
|
||||
spaces respectively. More precisely, that means they allow to declare common logic of interaction with such objects and
|
||||
spaces:
|
||||
|
||||
- `Polynomial` does not provide any logic. It is marker interface.
|
||||
- `RationalFunction` provides numerator and denominator of rational function and destructuring declaration for them.
|
||||
- `PolynomialSpace` provides all possible arithmetic interactions of integers, constants (of type `C`), and
|
||||
polynomials (of type `P`) like addition, subtraction, multiplication, and some others and common properties like
|
||||
degree of polynomial.
|
||||
- `RationalFunctionSpace` provides the same as `PolynomialSpace` but also for rational functions: all possible
|
||||
arithmetic interactions of integers, constants (of type `C`), polynomials (of type `P`), and rational functions (of
|
||||
type `R`) like addition, subtraction, multiplication, division (in some cases), and some others and common properties
|
||||
like degree of polynomial.
|
||||
|
||||
Then to add abstraction of similar behaviour with variables (in multivariate case) there are
|
||||
implemented `MultivariatePolynomialSpace` and `MultivariateRationalFunctionSpace`. They just include variables (of
|
||||
type `V`) in the interactions of the entities.
|
||||
|
||||
Also, to remove boilerplates there were provided helping subinterfaces and abstract subclasses:
|
||||
|
||||
- `PolynomialSpaceOverRing` allows to replace implementation of interactions of integers and constants with
|
||||
implementations from provided ring over constants (of type `A: Ring<C>`).
|
||||
- `RationalFunctionSpaceOverRing` — the same but for `RationalFunctionSpace`.
|
||||
- `RationalFunctionSpaceOverPolynomialSpace` — the same but "the inheritance" includes interactions with
|
||||
polynomials from provided `PolynomialSpace`.
|
||||
- `PolynomialSpaceOfFractions` is actually abstract subclass of `RationalFunctionSpace` that implements all fractions
|
||||
boilerplates with provided (`protected`) constructor of rational functions by polynomial numerator and denominator.
|
||||
- `MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpace` and `MultivariatePolynomialSpaceOfFractions`
|
||||
— the same stories of operators inheritance and fractions boilerplates respectively but in multivariate case.
|
||||
|
||||
## Utilities
|
||||
|
||||
For all kinds of polynomials there are provided (implementation details depend on kind of polynomials) such common
|
||||
utilities as:
|
||||
|
||||
1. differentiation and anti-differentiation,
|
||||
2. substitution, invocation and functional representation.
|
14
docs/readme.md
Normal file
@ -0,0 +1,14 @@
|
||||
# Documentation
|
||||
|
||||
* [Algebra](algebra.md): [context-based](contexts.md) operations on different primitives and structures.
|
||||
|
||||
* [NDStructures](nd-structure.md)
|
||||
|
||||
* [Linear algebra](linear.md): matrices, operations and linear equations solving. To be moved to separate module.
|
||||
Currently, supports basic API and multiple library back-ends.
|
||||
|
||||
* [Histograms](histograms.md): multidimensional histogram calculation and operations.
|
||||
|
||||
* [Expressions](expressions.md)
|
||||
|
||||
* Commons math integration
|
56
docs/templates/ARTIFACT-TEMPLATE.md
vendored
@ -1,40 +1,16 @@
|
||||
> #### Artifact:
|
||||
>
|
||||
> This module artifact: `${group}:${name}:${version}`.
|
||||
>
|
||||
> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/${name}/images/download.svg) ](https://bintray.com/mipt-npm/kscience/${name}/_latestVersion)
|
||||
>
|
||||
> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/${name}/images/download.svg) ](https://bintray.com/mipt-npm/dev/${name}/_latestVersion)
|
||||
>
|
||||
> **Gradle:**
|
||||
>
|
||||
> ```gradle
|
||||
> repositories {
|
||||
> maven { url 'https://repo.kotlin.link' }
|
||||
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||
> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
||||
>// Uncomment if repo.kotlin.link is unavailable
|
||||
>// maven { url 'https://dl.bintray.com/mipt-npm/kscience' }
|
||||
>// maven { url 'https://dl.bintray.com/mipt-npm/dev' }
|
||||
> }
|
||||
>
|
||||
> dependencies {
|
||||
> implementation '${group}:${name}:${version}'
|
||||
> }
|
||||
> ```
|
||||
> **Gradle Kotlin DSL:**
|
||||
>
|
||||
> ```kotlin
|
||||
> repositories {
|
||||
> maven("https://repo.kotlin.link")
|
||||
> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
||||
> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
||||
>// Uncomment if repo.kotlin.link is unavailable
|
||||
>// maven("https://dl.bintray.com/mipt-npm/kscience")
|
||||
>// maven("https://dl.bintray.com/mipt-npm/dev")
|
||||
> }
|
||||
>
|
||||
> dependencies {
|
||||
> implementation("${group}:${name}:${version}")
|
||||
> }
|
||||
> ```
|
||||
## Artifact:
|
||||
|
||||
The Maven coordinates of this project are `${group}:${name}:${version}`.
|
||||
|
||||
**Gradle:**
|
||||
|
||||
```kotlin
|
||||
repositories {
|
||||
maven("https://repo.kotlin.link")
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("${group}:${name}:${version}")
|
||||
}
|
||||
```
|
124
docs/templates/README-TEMPLATE.md
vendored
@ -1,104 +1,93 @@
|
||||
[![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
|
||||
[![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382)
|
||||
|
||||
![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg)
|
||||
|
||||
Bintray: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion)
|
||||
|
||||
Bintray-dev: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion)
|
||||
![Gradle build](https://github.com/SciProgCentre/kmath/workflows/Gradle%20build/badge.svg)
|
||||
[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22)
|
||||
[![Space](https://img.shields.io/badge/dynamic/xml?color=orange&label=Space&query=//metadata/versioning/latest&url=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/)
|
||||
|
||||
# KMath
|
||||
|
||||
Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based analog to
|
||||
Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior architecture
|
||||
designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could
|
||||
be achieved with [kmath-for-real](/kmath-for-real) extension module.
|
||||
Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based
|
||||
analog to Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior
|
||||
architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like
|
||||
experience could be achieved with [kmath-for-real](/kmath-for-real) extension module.
|
||||
|
||||
[Documentation site](https://SciProgCentre.github.io/kmath/)
|
||||
|
||||
## Publications and talks
|
||||
|
||||
* [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2)
|
||||
* [Another article about context-oriented design](https://proandroiddev.com/diving-deeper-into-context-oriented-programming-in-kotlin-3ecb4ec38814)
|
||||
* [ACAT 2019 conference paper](https://aip.scitation.org/doi/abs/10.1063/1.5130103)
|
||||
* [A talk at KotlinConf 2019 about using kotlin for science](https://youtu.be/LI_5TZ7tnOE?si=4LknX41gl_YeUbIe)
|
||||
* [A talk on architecture at Joker-2021 (in Russian)](https://youtu.be/1bZ2doHiRRM?si=9w953ro9yu98X_KJ)
|
||||
* [The same talk in English](https://youtu.be/yP5DIc2fVwQ?si=louZzQ1dcXV6gP10)
|
||||
* [A seminar on tensor API](https://youtu.be/0H99wUs0xTM?si=6c__04jrByFQtVpo)
|
||||
|
||||
# Goal
|
||||
|
||||
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native).
|
||||
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS, Native and
|
||||
Wasm).
|
||||
* Provide basic multiplatform implementations for those abstractions (without significant performance optimization).
|
||||
* Provide bindings and wrappers with those abstractions for popular optimized platform libraries.
|
||||
|
||||
## Non-goals
|
||||
|
||||
* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in terms of API.
|
||||
* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in API.
|
||||
* Provide the best performance out of the box. We have specialized libraries for that. Need only API wrappers for them.
|
||||
* Cover all cases as immediately and in one bundle. We will modularize everything and add new features gradually.
|
||||
* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like
|
||||
for `Double` in the core. For that we will have specialization modules like `kmath-for-real`, which will give better
|
||||
experience for those, who want to work with specific types.
|
||||
* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like
|
||||
for `Double` in the core. For that we will have specialization modules like `kmath-for-real`, which will give better
|
||||
experience for those, who want to work with specific types.
|
||||
|
||||
## Features and stability
|
||||
|
||||
KMath is a modular library. Different modules provide different features with different API stability guarantees. All core modules are released with the same version, but with different API change policy. The features are described in module definitions below. The module stability could have following levels:
|
||||
KMath is a modular library. Different modules provide different features with different API stability guarantees. All
|
||||
core modules are released with the same version, but with different API change policy. The features are described in
|
||||
module definitions below. The module stability could have the following levels:
|
||||
|
||||
* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could break any moment. You can still use it, but be sure to fix the specific version.
|
||||
* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked with `@UnstableKmathAPI` or other stability warning annotations.
|
||||
* **DEVELOPMENT**. API breaking genrally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
|
||||
* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could
|
||||
break any moment. You can still use it, but be sure to fix the specific version.
|
||||
* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked
|
||||
with `@UnstableKMathAPI` or other stability warning annotations.
|
||||
* **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor
|
||||
versions, but not in patch versions. API is protected
|
||||
with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
|
||||
* **STABLE**. The API stabilized. Breaking changes are allowed only in major releases.
|
||||
|
||||
<!--Current feature list is [here](/docs/features.md)-->
|
||||
|
||||
|
||||
<!--* **Array-like structures** Full support of many-dimensional array-like structures -->
|
||||
<!--including mixed arithmetic operations and function operations over arrays and numbers (with the added benefit of static type checking).-->
|
||||
|
||||
<!--* **Histograms** Fast multi-dimensional histograms.-->
|
||||
|
||||
<!--* **Streaming** Streaming operations on mathematical objects and objects buffers.-->
|
||||
|
||||
<!--* **Type-safe dimensions** Type-safe dimensions for matrix operations.-->
|
||||
|
||||
<!--* **Commons-math wrapper** It is planned to gradually wrap most parts of -->
|
||||
<!--[Apache commons-math](http://commons.apache.org/proper/commons-math/) library in Kotlin code and maybe rewrite some -->
|
||||
<!--parts to better suit the Kotlin programming paradigm, however there is no established roadmap for that. Feel free to -->
|
||||
<!--submit a feature request if you want something to be implemented first.-->
|
||||
<!-- -->
|
||||
<!--## Planned features-->
|
||||
|
||||
<!--* **Messaging** A mathematical notation to support multi-language and multi-node communication for mathematical tasks.-->
|
||||
|
||||
<!--* **Array statistics** -->
|
||||
|
||||
<!--* **Integration** Univariate and multivariate integration framework.-->
|
||||
|
||||
<!--* **Probability and distributions**-->
|
||||
|
||||
<!--* **Fitting** Non-linear curve fitting facilities-->
|
||||
|
||||
## Modules
|
||||
|
||||
$modules
|
||||
${modules}
|
||||
|
||||
## Multi-platform support
|
||||
|
||||
KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the
|
||||
[common source sets](/kmath-core/src/commonMain) and implemented there wherever it is possible. In some cases, features
|
||||
are delegated to platform-specific implementations even if they could be provided in the common module for performance
|
||||
reasons. Currently, the Kotlin/JVM is the primary platform, however Kotlin/Native and Kotlin/JS contributions and
|
||||
KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the
|
||||
[common source sets](/kmath-core/src/commonMain) and implemented there wherever it is possible. In some cases, features
|
||||
are delegated to platform-specific implementations even if they could be provided in the common module for performance
|
||||
reasons. Currently, Kotlin/JVM is the primary platform, however, Kotlin/Native and Kotlin/JS contributions and
|
||||
feedback are also welcome.
|
||||
|
||||
## Performance
|
||||
|
||||
Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve
|
||||
both performance and flexibility.
|
||||
Calculation of performance is one of the major goals of KMath in the future, but in some cases it is impossible to
|
||||
achieve both
|
||||
performance and flexibility.
|
||||
|
||||
We expect to focus on creating convenient universal API first and then work on increasing performance for specific
|
||||
cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized
|
||||
native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be
|
||||
We expect to focus on creating a convenient universal API first and then work on increasing performance for specific
|
||||
cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized
|
||||
native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be
|
||||
better than SciPy.
|
||||
|
||||
## Requirements
|
||||
|
||||
KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend using GraalVM-CE or
|
||||
Oracle GraalVM for execution to get better performance.
|
||||
|
||||
### Repositories
|
||||
|
||||
Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/) repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
|
||||
[Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) for more details). The repository could be reached through [repo.kotlin.link](https://repo.kotlin.link) proxy:
|
||||
Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/)
|
||||
repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
|
||||
[Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) for more details). The repository could
|
||||
be reached through [repo.kotlin.link](https://repo.kotlin.link) proxy:
|
||||
|
||||
```kotlin
|
||||
repositories {
|
||||
@ -106,16 +95,15 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api("kscience.kmath:kmath-core:$version")
|
||||
// api("kscience.kmath:kmath-core-jvm:$version") for jvm-specific version
|
||||
api("${group}:kmath-core:$version")
|
||||
// api("${group}:kmath-core-jvm:$version") for jvm-specific version
|
||||
}
|
||||
```
|
||||
|
||||
Gradle `6.0+` is required for multiplatform artifacts.
|
||||
|
||||
## Contributing
|
||||
|
||||
The project requires a lot of additional work. The most important thing we need is a feedback about what features are
|
||||
required the most. Feel free to create feature requests. We are also welcome to code contributions,
|
||||
especially in issues marked with
|
||||
[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label.
|
||||
The project requires a lot of additional work. The most important thing we need is feedback about what features are
|
||||
required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues
|
||||
marked
|
||||
with [good first issue](hhttps://github.com/SciProgCentre/kmath/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
|
||||
label.
|
4
examples/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Module examples
|
||||
|
||||
|
||||
|
@ -1,29 +1,17 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
kotlin("plugin.allopen")
|
||||
id("kotlinx.benchmark")
|
||||
}
|
||||
|
||||
allOpen.annotation("org.openjdk.jmh.annotations.State")
|
||||
sourceSets.register("benchmarks")
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
maven("https://repo.kotlin.link")
|
||||
maven("https://clojars.org/repo")
|
||||
maven("https://dl.bintray.com/egor-bogomolov/astminer/")
|
||||
maven("https://dl.bintray.com/hotkeytlt/maven")
|
||||
maven("https://dl.bintray.com/kotlin/kotlin-eap")
|
||||
maven("https://dl.bintray.com/kotlin/kotlinx")
|
||||
maven("https://dl.bintray.com/mipt-npm/dev")
|
||||
maven("https://dl.bintray.com/mipt-npm/kscience")
|
||||
maven("https://jitpack.io")
|
||||
maven("http://logicrunch.research.it.uu.se/maven/")
|
||||
mavenCentral()
|
||||
maven("https://repo.kotlin.link")
|
||||
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-js-wrappers")
|
||||
}
|
||||
|
||||
val multikVersion: String by rootProject.extra
|
||||
|
||||
dependencies {
|
||||
implementation(project(":kmath-ast"))
|
||||
implementation(project(":kmath-kotlingrad"))
|
||||
@ -31,15 +19,25 @@ dependencies {
|
||||
implementation(project(":kmath-coroutines"))
|
||||
implementation(project(":kmath-commons"))
|
||||
implementation(project(":kmath-complex"))
|
||||
implementation(project(":kmath-functions"))
|
||||
implementation(project(":kmath-optimization"))
|
||||
implementation(project(":kmath-stat"))
|
||||
implementation(project(":kmath-viktor"))
|
||||
implementation(project(":kmath-dimensions"))
|
||||
implementation(project(":kmath-ejml"))
|
||||
implementation(project(":kmath-nd4j"))
|
||||
|
||||
implementation(project(":kmath-tensors"))
|
||||
implementation(project(":kmath-symja"))
|
||||
implementation(project(":kmath-for-real"))
|
||||
//jafama
|
||||
implementation(project(":kmath-jafama"))
|
||||
//multik
|
||||
implementation(project(":kmath-multik"))
|
||||
implementation("org.jetbrains.kotlinx:multik-default:$multikVersion")
|
||||
|
||||
//datetime
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
|
||||
|
||||
implementation("org.deeplearning4j:deeplearning4j-core:1.0.0-beta7")
|
||||
implementation("org.nd4j:nd4j-native:1.0.0-beta7")
|
||||
|
||||
// uncomment if your system supports AVX2
|
||||
@ -52,59 +50,28 @@ dependencies {
|
||||
// } else
|
||||
implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7")
|
||||
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-io:0.2.0-npm-dev-11")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-20")
|
||||
implementation("org.slf4j:slf4j-simple:1.7.30")
|
||||
|
||||
implementation("org.slf4j:slf4j-simple:1.7.32")
|
||||
// plotting
|
||||
implementation("kscience.plotlykt:plotlykt-server:0.3.1-dev")
|
||||
|
||||
"benchmarksImplementation"("org.jetbrains.kotlinx:kotlinx.benchmark.runtime-jvm:0.2.0-dev-20")
|
||||
"benchmarksImplementation"(sourceSets.main.get().output + sourceSets.main.get().runtimeClasspath)
|
||||
implementation("space.kscience:plotlykt-server:0.7.0")
|
||||
}
|
||||
|
||||
// Configure benchmark
|
||||
benchmark {
|
||||
// Setup configurations
|
||||
targets.register("benchmarks")
|
||||
// This one matches sourceSet name above
|
||||
|
||||
configurations.register("buffer") {
|
||||
warmups = 1 // number of warmup iterations
|
||||
iterations = 3 // number of iterations
|
||||
iterationTime = 500 // time in seconds per iteration
|
||||
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
|
||||
include("BufferBenchmark")
|
||||
}
|
||||
|
||||
configurations.register("dot") {
|
||||
warmups = 1 // number of warmup iterations
|
||||
iterations = 3 // number of iterations
|
||||
iterationTime = 500 // time in seconds per iteration
|
||||
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
|
||||
include("DotBenchmark")
|
||||
}
|
||||
|
||||
configurations.register("expressions") {
|
||||
warmups = 1 // number of warmup iterations
|
||||
iterations = 3 // number of iterations
|
||||
iterationTime = 500 // time in seconds per iteration
|
||||
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
|
||||
include("ExpressionsInterpretersBenchmark")
|
||||
kotlin {
|
||||
jvmToolchain(11)
|
||||
sourceSets.all {
|
||||
languageSettings {
|
||||
optIn("kotlin.contracts.ExperimentalContracts")
|
||||
optIn("kotlin.ExperimentalUnsignedTypes")
|
||||
optIn("space.kscience.kmath.UnstableKMathAPI")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kotlin.sourceSets.all {
|
||||
with(languageSettings) {
|
||||
useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts")
|
||||
useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes")
|
||||
tasks.withType<KotlinJvmCompile> {
|
||||
compilerOptions {
|
||||
freeCompilerArgs.addAll("-Xjvm-default=all", "-Xopt-in=kotlin.RequiresOptIn", "-Xlambdas=indy")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
kotlinOptions.jvmTarget = "11"
|
||||
}
|
||||
|
||||
readme{
|
||||
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
||||
readme {
|
||||
maturity = space.kscience.gradle.Maturity.EXPERIMENTAL
|
||||
}
|
||||
|
418
examples/notebooks/Naive classifier.ipynb
Normal file
@ -0,0 +1,418 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"%use kmath(0.3.1-dev-5)\n",
|
||||
"%use plotly(0.5.0)\n",
|
||||
"@file:DependsOn(\"space.kscience:kmath-commons:0.3.1-dev-5\")"
|
||||
],
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"metadata": {
|
||||
"datalore": {
|
||||
"node_id": "lQbSB87rNAn9lV6poArVWW",
|
||||
"type": "CODE",
|
||||
"hide_input_from_viewers": false,
|
||||
"hide_output_from_viewers": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"//Uncomment to work in Jupyter classic or DataLore\n",
|
||||
"//Plotly.jupyter.notebook()"
|
||||
],
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"metadata": {
|
||||
"datalore": {
|
||||
"node_id": "0UP158hfccGgjQtHz0wAi6",
|
||||
"type": "CODE",
|
||||
"hide_input_from_viewers": false,
|
||||
"hide_output_from_viewers": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# The model\n",
|
||||
"\n",
|
||||
"Defining the input data format, the statistic abstraction and the statistic implementation based on a weighted sum of elements."
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"class XYValues(val xValues: DoubleArray, val yValues: DoubleArray) {\n",
|
||||
" init {\n",
|
||||
" require(xValues.size == yValues.size)\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"fun interface XYStatistic {\n",
|
||||
" operator fun invoke(values: XYValues): Double\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"class ConvolutionalXYStatistic(val weights: DoubleArray) : XYStatistic {\n",
|
||||
" override fun invoke(values: XYValues): Double {\n",
|
||||
" require(weights.size == values.yValues.size)\n",
|
||||
" val norm = values.yValues.sum()\n",
|
||||
" return values.yValues.zip(weights) { value, weight -> value * weight }.sum()/norm\n",
|
||||
" }\n",
|
||||
"}"
|
||||
],
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"metadata": {
|
||||
"datalore": {
|
||||
"node_id": "Zhgz1Ui91PWz0meJiQpHol",
|
||||
"type": "CODE",
|
||||
"hide_input_from_viewers": false,
|
||||
"hide_output_from_viewers": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# Generator\n",
|
||||
"Generate sample data for parabolas and hyperbolas"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fun generateParabolas(xValues: DoubleArray, a: Double, b: Double, c: Double): XYValues {\n",
|
||||
" val yValues = xValues.map { x -> a * x * x + b * x + c }.toDoubleArray()\n",
|
||||
" return XYValues(xValues, yValues)\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"fun generateHyperbols(xValues: DoubleArray, gamma: Double, x0: Double, y0: Double): XYValues {\n",
|
||||
" val yValues = xValues.map { x -> y0 + gamma / (x - x0) }.toDoubleArray()\n",
|
||||
" return XYValues(xValues, yValues)\n",
|
||||
"}"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"val xValues = (1.0..10.0).step(1.0).toDoubleArray()\n",
|
||||
"\n",
|
||||
"val xy = generateHyperbols(xValues, 1.0, 0.0, 0.0)\n",
|
||||
"\n",
|
||||
"Plotly.plot {\n",
|
||||
" scatter {\n",
|
||||
" this.x.doubles = xValues\n",
|
||||
" this.y.doubles = xy.yValues\n",
|
||||
" }\n",
|
||||
"}"
|
||||
],
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"metadata": {
|
||||
"datalore": {
|
||||
"node_id": "ZE2atNvFzQsCvpAF8KK4ch",
|
||||
"type": "CODE",
|
||||
"hide_input_from_viewers": false,
|
||||
"hide_output_from_viewers": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"Create a default statistic with uniform weights"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"val statistic = ConvolutionalXYStatistic(DoubleArray(xValues.size){1.0})\n",
|
||||
"statistic(xy)"
|
||||
],
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"metadata": {
|
||||
"datalore": {
|
||||
"node_id": "EA5HaydTddRKYrtAUwd29h",
|
||||
"type": "CODE",
|
||||
"hide_input_from_viewers": false,
|
||||
"hide_output_from_viewers": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"import kotlin.random.Random\n",
|
||||
"\n",
|
||||
"val random = Random(1288)\n",
|
||||
"\n",
|
||||
"val parabolas = buildList{\n",
|
||||
" repeat(500){\n",
|
||||
" add(\n",
|
||||
" generateParabolas(\n",
|
||||
" xValues, \n",
|
||||
" random.nextDouble(), \n",
|
||||
" random.nextDouble(), \n",
|
||||
" random.nextDouble()\n",
|
||||
" )\n",
|
||||
" )\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"val hyperbolas: List<XYValues> = buildList{\n",
|
||||
" repeat(500){\n",
|
||||
" add(\n",
|
||||
" generateHyperbols(\n",
|
||||
" xValues, \n",
|
||||
" random.nextDouble()*10, \n",
|
||||
" random.nextDouble(), \n",
|
||||
" random.nextDouble()\n",
|
||||
" )\n",
|
||||
" )\n",
|
||||
" }\n",
|
||||
"}"
|
||||
],
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"metadata": {
|
||||
"datalore": {
|
||||
"node_id": "t5t6IYmD7Q1ykeo9uijFfQ",
|
||||
"type": "CODE",
|
||||
"hide_input_from_viewers": false,
|
||||
"hide_output_from_viewers": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"Plotly.plot { \n",
|
||||
" scatter { \n",
|
||||
" x.doubles = xValues\n",
|
||||
" y.doubles = parabolas[257].yValues\n",
|
||||
" }\n",
|
||||
" scatter { \n",
|
||||
" x.doubles = xValues\n",
|
||||
" y.doubles = hyperbolas[252].yValues\n",
|
||||
" }\n",
|
||||
" }"
|
||||
],
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"metadata": {
|
||||
"datalore": {
|
||||
"node_id": "oXB8lmju7YVYjMRXITKnhO",
|
||||
"type": "CODE",
|
||||
"hide_input_from_viewers": false,
|
||||
"hide_output_from_viewers": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"Plotly.plot { \n",
|
||||
" histogram { \n",
|
||||
" name = \"parabolae\"\n",
|
||||
" x.numbers = parabolas.map { statistic(it) }\n",
|
||||
" }\n",
|
||||
" histogram { \n",
|
||||
" name = \"hyperbolae\"\n",
|
||||
" x.numbers = hyperbolas.map { statistic(it) }\n",
|
||||
" }\n",
|
||||
"}"
|
||||
],
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"metadata": {
|
||||
"datalore": {
|
||||
"node_id": "8EIIecUZrt2NNrOkhxG5P0",
|
||||
"type": "CODE",
|
||||
"hide_input_from_viewers": false,
|
||||
"hide_output_from_viewers": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"val lossFunction: (XYStatistic) -> Double = { statistic ->\n",
|
||||
" - abs(parabolas.sumOf { statistic(it) } - hyperbolas.sumOf { statistic(it) })\n",
|
||||
"}"
|
||||
],
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"metadata": {
|
||||
"datalore": {
|
||||
"node_id": "h7UmglJW5zXkAfKHK40oIL",
|
||||
"type": "CODE",
|
||||
"hide_input_from_viewers": false,
|
||||
"hide_output_from_viewers": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"Using commons-math optimizer to optimize weights"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"import org.apache.commons.math3.optim.*\n",
|
||||
"import org.apache.commons.math3.optim.nonlinear.scalar.*\n",
|
||||
"import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.*\n",
|
||||
"\n",
|
||||
"val optimizer = SimplexOptimizer(1e-1, Double.MAX_VALUE)\n",
|
||||
"\n",
|
||||
"val result = optimizer.optimize(\n",
|
||||
" ObjectiveFunction { point ->\n",
|
||||
" lossFunction(ConvolutionalXYStatistic(point))\n",
|
||||
" },\n",
|
||||
" NelderMeadSimplex(xValues.size),\n",
|
||||
" InitialGuess(DoubleArray(xValues.size){ 1.0 }),\n",
|
||||
" GoalType.MINIMIZE,\n",
|
||||
" MaxEval(100000)\n",
|
||||
")"
|
||||
],
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"metadata": {
|
||||
"datalore": {
|
||||
"node_id": "0EG3K4aCUciMlgGQKPvJ57",
|
||||
"type": "CODE",
|
||||
"hide_input_from_viewers": false,
|
||||
"hide_output_from_viewers": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"Print resulting weights of optimization"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"result.point"
|
||||
],
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"metadata": {
|
||||
"datalore": {
|
||||
"node_id": "LelUlY0ZSlJEO9yC6SLk5B",
|
||||
"type": "CODE",
|
||||
"hide_input_from_viewers": false,
|
||||
"hide_output_from_viewers": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"Plotly.plot { \n",
|
||||
" scatter { \n",
|
||||
" y.doubles = result.point\n",
|
||||
" }\n",
|
||||
"}"
|
||||
],
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"metadata": {
|
||||
"datalore": {
|
||||
"node_id": "AuFOq5t9KpOIkGrOLsVXNf",
|
||||
"type": "CODE",
|
||||
"hide_input_from_viewers": false,
|
||||
"hide_output_from_viewers": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# The resulting statistic distribution"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"val resultStatistic = ConvolutionalXYStatistic(result.point)\n",
|
||||
"Plotly.plot { \n",
|
||||
" histogram { \n",
|
||||
" name = \"parabolae\"\n",
|
||||
" x.numbers = parabolas.map { resultStatistic(it) }\n",
|
||||
" }\n",
|
||||
" histogram { \n",
|
||||
" name = \"hyperbolae\"\n",
|
||||
" x.numbers = hyperbolas.map { resultStatistic(it) }\n",
|
||||
" }\n",
|
||||
"}"
|
||||
],
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"metadata": {
|
||||
"datalore": {
|
||||
"node_id": "zvmq42DRdM5mZ3SpzviHwI",
|
||||
"type": "CODE",
|
||||
"hide_input_from_viewers": false,
|
||||
"hide_output_from_viewers": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"source": [],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Kotlin",
|
||||
"language": "kotlin",
|
||||
"name": "kotlin"
|
||||
},
|
||||
"datalore": {
|
||||
"version": 1,
|
||||
"computation_mode": "JUPYTER",
|
||||
"package_manager": "pip",
|
||||
"base_environment": "default",
|
||||
"packages": []
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import org.openjdk.jmh.annotations.Benchmark
|
||||
import org.openjdk.jmh.annotations.Scope
|
||||
import org.openjdk.jmh.annotations.State
|
||||
import java.nio.IntBuffer
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class ArrayBenchmark {
|
||||
@Benchmark
|
||||
fun benchmarkArrayRead() {
|
||||
var res = 0
|
||||
for (i in 1..space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) res += space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.array[space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size - i]
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun benchmarkBufferRead() {
|
||||
var res = 0
|
||||
for (i in 1..space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) res += space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.arrayBuffer[space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size - i]
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun nativeBufferRead() {
|
||||
var res = 0
|
||||
for (i in 1..space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) res += space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.nativeBuffer[space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size - i]
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val size: Int = 1000
|
||||
val array: IntArray = IntArray(space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) { it }
|
||||
val arrayBuffer: IntBuffer = IntBuffer.wrap(space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.array)
|
||||
val nativeBuffer: IntBuffer = IntBuffer.allocate(space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size).also { for (i in 0 until space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) it.put(i, i) }
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import org.openjdk.jmh.annotations.Benchmark
|
||||
import org.openjdk.jmh.annotations.Scope
|
||||
import org.openjdk.jmh.annotations.State
|
||||
import space.kscience.kmath.complex.Complex
|
||||
import space.kscience.kmath.complex.complex
|
||||
import space.kscience.kmath.structures.MutableBuffer
|
||||
import space.kscience.kmath.structures.RealBuffer
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class BufferBenchmark {
|
||||
@Benchmark
|
||||
fun genericRealBufferReadWrite() {
|
||||
val buffer = RealBuffer(size) { it.toDouble() }
|
||||
|
||||
(0 until size).forEach {
|
||||
buffer[it]
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun complexBufferReadWrite() {
|
||||
val buffer = MutableBuffer.complex(size / 2) { Complex(it.toDouble(), -it.toDouble()) }
|
||||
|
||||
(0 until size / 2).forEach {
|
||||
buffer[it]
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val size: Int = 100
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import kotlinx.benchmark.Benchmark
|
||||
import org.openjdk.jmh.annotations.Scope
|
||||
import org.openjdk.jmh.annotations.State
|
||||
import space.kscience.kmath.commons.linear.CMMatrixContext
|
||||
import space.kscience.kmath.ejml.EjmlMatrixContext
|
||||
import space.kscience.kmath.linear.BufferMatrixContext
|
||||
import space.kscience.kmath.linear.Matrix
|
||||
import space.kscience.kmath.linear.RealMatrixContext
|
||||
import space.kscience.kmath.operations.RealField
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import kotlin.random.Random
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class DotBenchmark {
|
||||
companion object {
|
||||
val random = Random(12224)
|
||||
val dim = 1000
|
||||
|
||||
//creating invertible matrix
|
||||
val matrix1 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
|
||||
val matrix2 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
|
||||
|
||||
val cmMatrix1 = CMMatrixContext { matrix1.toCM() }
|
||||
val cmMatrix2 = CMMatrixContext { matrix2.toCM() }
|
||||
|
||||
val ejmlMatrix1 = EjmlMatrixContext { matrix1.toEjml() }
|
||||
val ejmlMatrix2 = EjmlMatrixContext { matrix2.toEjml() }
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun cmDot() {
|
||||
CMMatrixContext {
|
||||
cmMatrix1 dot cmMatrix2
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun ejmlDot() {
|
||||
EjmlMatrixContext {
|
||||
ejmlMatrix1 dot ejmlMatrix2
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun ejmlDotWithConversion() {
|
||||
EjmlMatrixContext {
|
||||
matrix1 dot matrix2
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun bufferedDot() {
|
||||
BufferMatrixContext(RealField, Buffer.Companion::real).invoke {
|
||||
matrix1 dot matrix2
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun realDot() {
|
||||
RealMatrixContext {
|
||||
matrix1 dot matrix2
|
||||
}
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import org.openjdk.jmh.annotations.Benchmark
|
||||
import org.openjdk.jmh.annotations.Scope
|
||||
import org.openjdk.jmh.annotations.State
|
||||
import space.kscience.kmath.asm.compile
|
||||
import space.kscience.kmath.ast.mstInField
|
||||
import space.kscience.kmath.expressions.Expression
|
||||
import space.kscience.kmath.expressions.expressionInField
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.expressions.symbol
|
||||
import space.kscience.kmath.operations.Field
|
||||
import space.kscience.kmath.operations.RealField
|
||||
import space.kscience.kmath.operations.bindSymbol
|
||||
import kotlin.random.Random
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class ExpressionsInterpretersBenchmark {
|
||||
private val algebra: Field<Double> = RealField
|
||||
val x by symbol
|
||||
|
||||
@Benchmark
|
||||
fun functionalExpression() {
|
||||
val expr = algebra.expressionInField {
|
||||
val x = bindSymbol(x)
|
||||
x * const(2.0) + const(2.0) / x - const(16.0)
|
||||
}
|
||||
|
||||
invokeAndSum(expr)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun mstExpression() {
|
||||
val expr = algebra.mstInField {
|
||||
val x = bindSymbol(x)
|
||||
x * 2.0 + 2.0 / x - 16.0
|
||||
}
|
||||
|
||||
invokeAndSum(expr)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun asmExpression() {
|
||||
val expr = algebra.mstInField {
|
||||
val x = bindSymbol(x)
|
||||
x * 2.0 + 2.0 / x - 16.0
|
||||
}.compile()
|
||||
|
||||
invokeAndSum(expr)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun rawExpression() {
|
||||
val expr = Expression<Double> { args ->
|
||||
val x = args.getValue(x)
|
||||
x * 2.0 + 2.0 / x - 16.0
|
||||
}
|
||||
invokeAndSum(expr)
|
||||
}
|
||||
|
||||
private fun invokeAndSum(expr: Expression<Double>) {
|
||||
val random = Random(0)
|
||||
var sum = 0.0
|
||||
|
||||
repeat(1000000) {
|
||||
sum += expr(x to random.nextDouble())
|
||||
}
|
||||
|
||||
println(sum)
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import kotlinx.benchmark.Benchmark
|
||||
import org.openjdk.jmh.annotations.Scope
|
||||
import org.openjdk.jmh.annotations.State
|
||||
import space.kscience.kmath.commons.linear.CMMatrixContext
|
||||
import space.kscience.kmath.commons.linear.CMMatrixContext.dot
|
||||
import space.kscience.kmath.commons.linear.inverse
|
||||
import space.kscience.kmath.ejml.EjmlMatrixContext
|
||||
import space.kscience.kmath.ejml.inverse
|
||||
import space.kscience.kmath.linear.Matrix
|
||||
import space.kscience.kmath.linear.MatrixContext
|
||||
import space.kscience.kmath.linear.inverseWithLup
|
||||
import space.kscience.kmath.linear.real
|
||||
import kotlin.random.Random
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class LinearAlgebraBenchmark {
|
||||
companion object {
|
||||
val random = Random(1224)
|
||||
val dim = 100
|
||||
|
||||
//creating invertible matrix
|
||||
val u = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
|
||||
val l = Matrix.real(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 }
|
||||
val matrix = l dot u
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun kmathLupInversion() {
|
||||
MatrixContext.real.inverseWithLup(matrix)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun cmLUPInversion() {
|
||||
with(CMMatrixContext) {
|
||||
inverse(matrix)
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun ejmlInverse() {
|
||||
with(EjmlMatrixContext) {
|
||||
inverse(matrix)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import org.openjdk.jmh.annotations.Benchmark
|
||||
import org.openjdk.jmh.annotations.Scope
|
||||
import org.openjdk.jmh.annotations.State
|
||||
import space.kscience.kmath.nd.*
|
||||
import space.kscience.kmath.operations.RealField
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class NDFieldBenchmark {
|
||||
@Benchmark
|
||||
fun autoFieldAdd() {
|
||||
with(autoField) {
|
||||
var res: NDStructure<Double> = one
|
||||
repeat(n) { res += one }
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun specializedFieldAdd() {
|
||||
with(specializedField) {
|
||||
var res: NDStructure<Double> = one
|
||||
repeat(n) { res += 1.0 }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Benchmark
|
||||
fun boxingFieldAdd() {
|
||||
with(genericField) {
|
||||
var res: NDStructure<Double> = one
|
||||
repeat(n) { res += 1.0 }
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val dim: Int = 1000
|
||||
const val n: Int = 100
|
||||
val autoField = NDAlgebra.auto(RealField, dim, dim)
|
||||
val specializedField: RealNDField = NDAlgebra.real(dim, dim)
|
||||
val genericField = NDAlgebra.field(RealField, Buffer.Companion::boxing, dim, dim)
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import org.jetbrains.bio.viktor.F64Array
|
||||
import org.openjdk.jmh.annotations.Benchmark
|
||||
import org.openjdk.jmh.annotations.Scope
|
||||
import org.openjdk.jmh.annotations.State
|
||||
import space.kscience.kmath.nd.*
|
||||
import space.kscience.kmath.operations.RealField
|
||||
import space.kscience.kmath.viktor.ViktorNDField
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class ViktorBenchmark {
|
||||
final val dim: Int = 1000
|
||||
final val n: Int = 100
|
||||
|
||||
// automatically build context most suited for given type.
|
||||
final val autoField: NDField<Double, RealField> = NDAlgebra.auto(RealField, dim, dim)
|
||||
final val realField: RealNDField = NDAlgebra.real(dim, dim)
|
||||
final val viktorField: ViktorNDField = ViktorNDField(dim, dim)
|
||||
|
||||
@Benchmark
|
||||
fun automaticFieldAddition() {
|
||||
with(autoField) {
|
||||
var res: NDStructure<Double> = one
|
||||
repeat(n) { res += 1.0 }
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun realFieldAddition() {
|
||||
with(realField) {
|
||||
var res: NDStructure<Double> = one
|
||||
repeat(n) { res += 1.0 }
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun viktorFieldAddition() {
|
||||
with(viktorField) {
|
||||
var res = one
|
||||
repeat(n) { res += 1.0 }
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun rawViktor() {
|
||||
val one = F64Array.full(init = 1.0, shape = intArrayOf(dim, dim))
|
||||
var res = one
|
||||
repeat(n) { res = res + one }
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
package space.kscience.kmath.benchmarks
|
||||
|
||||
import org.jetbrains.bio.viktor.F64Array
|
||||
import org.openjdk.jmh.annotations.Benchmark
|
||||
import org.openjdk.jmh.annotations.Scope
|
||||
import org.openjdk.jmh.annotations.State
|
||||
import space.kscience.kmath.nd.*
|
||||
import space.kscience.kmath.operations.RealField
|
||||
import space.kscience.kmath.viktor.ViktorNDField
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
internal class ViktorLogBenchmark {
|
||||
final val dim: Int = 1000
|
||||
final val n: Int = 100
|
||||
|
||||
// automatically build context most suited for given type.
|
||||
final val autoField: NDField<Double, RealField> = NDAlgebra.auto(RealField, dim, dim)
|
||||
final val realField: RealNDField = NDAlgebra.real(dim, dim)
|
||||
final val viktorField: ViktorNDField = ViktorNDField(intArrayOf(dim, dim))
|
||||
|
||||
|
||||
@Benchmark
|
||||
fun realFieldLog() {
|
||||
with(realField) {
|
||||
val fortyTwo = produce { 42.0 }
|
||||
var res = one
|
||||
repeat(n) { res = ln(fortyTwo) }
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun viktorFieldLog() {
|
||||
with(viktorField) {
|
||||
val fortyTwo = produce { 42.0 }
|
||||
var res = one
|
||||
repeat(n) { res = ln(fortyTwo) }
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun rawViktorLog() {
|
||||
val fortyTwo = F64Array.full(dim, dim, init = 42.0)
|
||||
var res: F64Array
|
||||
repeat(n) {
|
||||
res = fortyTwo.log()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.ast
|
||||
|
||||
import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess
|
||||
import space.kscience.kmath.ast.rendering.LatexSyntaxRenderer
|
||||
import space.kscience.kmath.ast.rendering.MathMLSyntaxRenderer
|
||||
import space.kscience.kmath.ast.rendering.renderWithStringBuilder
|
||||
|
||||
fun main() {
|
||||
val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(-12)".parseMath()
|
||||
val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst)
|
||||
println("MathSyntax:")
|
||||
println(syntax)
|
||||
println()
|
||||
val latex = LatexSyntaxRenderer.renderWithStringBuilder(syntax)
|
||||
println("LaTeX:")
|
||||
println(latex)
|
||||
println()
|
||||
val mathML = MathMLSyntaxRenderer.renderWithStringBuilder(syntax)
|
||||
println("MathML:")
|
||||
println(mathML)
|
||||
}
|
@ -1,15 +1,26 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.ast
|
||||
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.operations.RealField
|
||||
import space.kscience.kmath.asm.compileToExpression
|
||||
import space.kscience.kmath.expressions.MstExtendedField
|
||||
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.operations.invoke
|
||||
|
||||
fun main() {
|
||||
val expr = RealField.mstInField {
|
||||
val x = bindSymbol("x")
|
||||
x * 2.0 + 2.0 / x - 16.0
|
||||
}
|
||||
val expr = MstExtendedField {
|
||||
x * 2.0 + number(2.0) / x - number(16.0) + asinh(x) / sin(x)
|
||||
}.compileToExpression(Float64Field)
|
||||
|
||||
repeat(10000000){
|
||||
expr.invoke("x" to 1.0)
|
||||
val m = DoubleArray(expr.indexer.symbols.size)
|
||||
val xIdx = expr.indexer.indexOf(x)
|
||||
|
||||
repeat(10000000) {
|
||||
m[xIdx] = 1.0
|
||||
expr(m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,27 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.ast
|
||||
|
||||
import space.kscience.kmath.asm.compile
|
||||
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||
import space.kscience.kmath.expressions.derivative
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.expressions.symbol
|
||||
import space.kscience.kmath.kotlingrad.differentiable
|
||||
import space.kscience.kmath.operations.RealField
|
||||
import space.kscience.kmath.expressions.toExpression
|
||||
import space.kscience.kmath.kotlingrad.toKotlingradExpression
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
|
||||
/**
|
||||
* In this example, x^2-4*x-44 function is differentiated with Kotlin∇, and the autodiff result is compared with
|
||||
* valid derivative.
|
||||
* In this example, *x<sup>2</sup> − 4 x − 44* function is differentiated with Kotlin∇, and the
|
||||
* derivation result is compared with valid derivative in a certain point.
|
||||
*/
|
||||
fun main() {
|
||||
val x by symbol
|
||||
|
||||
val actualDerivative = MstExpression(RealField, "x^2-4*x-44".parseMath())
|
||||
.differentiable()
|
||||
val actualDerivative = "x^2-4*x-44"
|
||||
.parseMath()
|
||||
.toKotlingradExpression(Float64Field)
|
||||
.derivative(x)
|
||||
.compile()
|
||||
|
||||
val expectedDerivative = MstExpression(RealField, "2*x-4".parseMath()).compile()
|
||||
assert(actualDerivative("x" to 123.0) == expectedDerivative("x" to 123.0))
|
||||
val expectedDerivative = "2*x-4".parseMath().toExpression(Float64Field)
|
||||
check(actualDerivative(x to 123.0) == expectedDerivative(x to 123.0))
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.ast
|
||||
|
||||
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||
import space.kscience.kmath.expressions.derivative
|
||||
import space.kscience.kmath.expressions.invoke
|
||||
import space.kscience.kmath.expressions.toExpression
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.symja.toSymjaExpression
|
||||
|
||||
/**
|
||||
* In this example, *x<sup>2</sup> − 4 x − 44* function is differentiated with Symja, and the
|
||||
* derivation result is compared with valid derivative in a certain point.
|
||||
*/
|
||||
fun main() {
|
||||
val actualDerivative = "x^2-4*x-44"
|
||||
.parseMath()
|
||||
.toSymjaExpression(Float64Field)
|
||||
.derivative(x)
|
||||
|
||||
val expectedDerivative = "2*x-4".parseMath().toExpression(Float64Field)
|
||||
check(actualDerivative(x to 123.0) == expectedDerivative(x to 123.0))
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.expressions
|
||||
|
||||
import space.kscience.kmath.UnstableKMathAPI
|
||||
|
||||
// Only kmath-core is needed.
|
||||
|
||||
// Let's declare some variables
|
||||
val x by symbol
|
||||
val y by symbol
|
||||
val z by symbol
|
||||
|
||||
@OptIn(UnstableKMathAPI::class)
|
||||
fun main() {
|
||||
// Let's define some random expression.
|
||||
val someExpression = Double.autodiff.differentiate {
|
||||
// We bind variables `x` and `y` to the builder scope,
|
||||
val x = bindSymbol(x)
|
||||
val y = bindSymbol(y)
|
||||
|
||||
// Then we use the bindings to define expression `xy + x + y - 1`
|
||||
x * y + x + y - 1
|
||||
}
|
||||
|
||||
// Then we can evaluate it at any point ((-1, -1) in the case):
|
||||
println(someExpression(x to -1.0, y to -1.0))
|
||||
// >>> -2.0
|
||||
|
||||
// We can also construct its partial derivatives:
|
||||
val dxExpression = someExpression.derivative(x) // ∂/∂x. Must be `y+1`
|
||||
val dyExpression = someExpression.derivative(y) // ∂/∂y. Must be `x+1`
|
||||
val dxdxExpression = someExpression.derivative(x, x) // ∂^2/∂x^2. Must be `0`
|
||||
|
||||
// We can evaluate them as well
|
||||
println(dxExpression(x to 57.0, y to 6.0))
|
||||
// >>> 7.0
|
||||
println(dyExpression(x to -1.0, y to 179.0))
|
||||
// >>> 0.0
|
||||
println(dxdxExpression(x to 239.0, y to 30.0))
|
||||
// >>> 0.0
|
||||
|
||||
// You can also provide extra arguments that obviously won't affect the result:
|
||||
println(dxExpression(x to 57.0, y to 6.0, z to 42.0))
|
||||
// >>> 7.0
|
||||
println(dyExpression(x to -1.0, y to 179.0, z to 0.0))
|
||||
// >>> 0.0
|
||||
println(dxdxExpression(x to 239.0, y to 30.0, z to 100_000.0))
|
||||
// >>> 0.0
|
||||
|
||||
// But in case you forgot to specify bound symbol's value, exception is thrown:
|
||||
println(runCatching { someExpression(z to 4.0) })
|
||||
// >>> Failure(java.lang.IllegalStateException: Symbol 'x' is not supported in ...)
|
||||
|
||||
// The reason is that the expression is evaluated lazily,
|
||||
// and each `bindSymbol` operation actually substitutes the provided symbol with the corresponding value.
|
||||
|
||||
// For example, let there be an expression
|
||||
val simpleExpression = Double.autodiff.differentiate {
|
||||
val x = bindSymbol(x)
|
||||
x pow 2
|
||||
}
|
||||
// When you evaluate it via
|
||||
simpleExpression(x to 1.0, y to 57.0, z to 179.0)
|
||||
// lambda above has the context of map `{x: 1.0, y: 57.0, z: 179.0}`.
|
||||
// When x is bound, you can think of it as substitution `x -> 1.0`.
|
||||
// Other values are unused which does not make any problem to us.
|
||||
// But in the case the corresponding value is not provided,
|
||||
// we cannot bind the variable. Thus, exception is thrown.
|
||||
|
||||
// There is also a function `bindSymbolOrNull` that fixes the problem:
|
||||
val fixedExpression = Double.autodiff.differentiate {
|
||||
val x = bindSymbolOrNull(x) ?: const(8.0)
|
||||
x pow -2
|
||||
}
|
||||
println(fixedExpression())
|
||||
// >>> 0.015625
|
||||
// It works!
|
||||
|
||||
// The expression provides a bunch of operations:
|
||||
// 1. Constant bindings (via `const` and `number`).
|
||||
// 2. Variable bindings (via `bindVariable`, `bindVariableOrNull`).
|
||||
// 3. Arithmetic operations (via `+`, `-`, `*`, and `-`).
|
||||
// 4. Exponentiation (via `pow` or `power`).
|
||||
// 5. `exp` and `ln`.
|
||||
// 6. Trigonometrical functions (`sin`, `cos`, `tan`, `cot`).
|
||||
// 7. Inverse trigonometrical functions (`asin`, `acos`, `atan`, `acot`).
|
||||
// 8. Hyperbolic functions and inverse hyperbolic functions.
|
||||
}
|
@ -1,24 +1,31 @@
|
||||
package space.kscience.kmath.commons.fit
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.fit
|
||||
|
||||
import kotlinx.html.br
|
||||
import kotlinx.html.h3
|
||||
import kscience.plotly.*
|
||||
import kscience.plotly.models.ScatterMode
|
||||
import kscience.plotly.models.TraceValues
|
||||
import space.kscience.kmath.commons.optimization.chiSquared
|
||||
import space.kscience.kmath.commons.optimization.minimize
|
||||
import space.kscience.kmath.commons.optimization.CMOptimizer
|
||||
import space.kscience.kmath.distributions.NormalDistribution
|
||||
import space.kscience.kmath.expressions.autodiff
|
||||
import space.kscience.kmath.expressions.symbol
|
||||
import space.kscience.kmath.real.RealVector
|
||||
import space.kscience.kmath.operations.asIterable
|
||||
import space.kscience.kmath.operations.toList
|
||||
import space.kscience.kmath.optimization.*
|
||||
import space.kscience.kmath.random.RandomGenerator
|
||||
import space.kscience.kmath.real.DoubleVector
|
||||
import space.kscience.kmath.real.map
|
||||
import space.kscience.kmath.real.step
|
||||
import space.kscience.kmath.stat.*
|
||||
import space.kscience.kmath.structures.asIterable
|
||||
import space.kscience.kmath.structures.toList
|
||||
import space.kscience.kmath.stat.chiSquaredExpression
|
||||
import space.kscience.plotly.*
|
||||
import space.kscience.plotly.models.ScatterMode
|
||||
import space.kscience.plotly.models.TraceValues
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sqrt
|
||||
|
||||
//Forward declaration of symbols that will be used in expressions.
|
||||
// This declaration is required for
|
||||
// Forward declaration of symbols that will be used in expressions.
|
||||
private val a by symbol
|
||||
private val b by symbol
|
||||
private val c by symbol
|
||||
@ -26,17 +33,16 @@ private val c by symbol
|
||||
/**
|
||||
* Shortcut to use buffers in plotly
|
||||
*/
|
||||
operator fun TraceValues.invoke(vector: RealVector) {
|
||||
operator fun TraceValues.invoke(vector: DoubleVector) {
|
||||
numbers = vector.asIterable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Least squares fie with auto-differentiation. Uses `kmath-commons` and `kmath-for-real` modules.
|
||||
*/
|
||||
fun main() {
|
||||
|
||||
suspend fun main() {
|
||||
//A generator for a normally distributed values
|
||||
val generator = Distribution.normal()
|
||||
val generator = NormalDistribution(0.0, 1.0)
|
||||
|
||||
//A chain/flow of random values with the given seed
|
||||
val chain = generator.sample(RandomGenerator.default(112667))
|
||||
@ -47,9 +53,9 @@ fun main() {
|
||||
|
||||
|
||||
//Perform an operation on each x value (much more effective, than numpy)
|
||||
val y = x.map {
|
||||
val y = x.map { it ->
|
||||
val value = it.pow(2) + it + 1
|
||||
value + chain.nextDouble() * sqrt(value)
|
||||
value + chain.next() * sqrt(value)
|
||||
}
|
||||
// this will also work, but less effective:
|
||||
// val y = x.pow(2)+ x + 1 + chain.nextDouble()
|
||||
@ -58,17 +64,22 @@ fun main() {
|
||||
val yErr = y.map { sqrt(it) }//RealVector.same(x.size, sigma)
|
||||
|
||||
// compute differentiable chi^2 sum for given model ax^2 + bx + c
|
||||
val chi2 = Fitting.chiSquared(x, y, yErr) { x1 ->
|
||||
val chi2 = Double.autodiff.chiSquaredExpression(x, y, yErr) { arg ->
|
||||
//bind variables to autodiff context
|
||||
val a = bind(a)
|
||||
val b = bind(b)
|
||||
val a = bindSymbol(a)
|
||||
val b = bindSymbol(b)
|
||||
//Include default value for c if it is not provided as a parameter
|
||||
val c = bindSymbolOrNull(c) ?: one
|
||||
a * x1.pow(2) + b * x1 + c
|
||||
a * arg.pow(2) + b * arg + c
|
||||
}
|
||||
|
||||
//minimize the chi^2 in given starting point. Derivatives are not required, they are already included.
|
||||
val result: OptimizationResult<Double> = chi2.minimize(a to 1.5, b to 0.9, c to 1.0)
|
||||
val result = chi2.optimizeWith(
|
||||
CMOptimizer,
|
||||
mapOf(a to 1.5, b to 0.9, c to 1.0),
|
||||
) {
|
||||
FunctionOptimizationTarget(OptimizationDirection.MINIMIZE)
|
||||
}
|
||||
|
||||
//display a page with plot and numerical results
|
||||
val page = Plotly.page {
|
||||
@ -85,18 +96,18 @@ fun main() {
|
||||
scatter {
|
||||
mode = ScatterMode.lines
|
||||
x(x)
|
||||
y(x.map { result.point[a]!! * it.pow(2) + result.point[b]!! * it + 1 })
|
||||
y(x.map { result.result[a]!! * it.pow(2) + result.result[b]!! * it + 1 })
|
||||
name = "fit"
|
||||
}
|
||||
}
|
||||
br()
|
||||
h3{
|
||||
h3 {
|
||||
+"Fit result: $result"
|
||||
}
|
||||
h3{
|
||||
+"Chi2/dof = ${result.value / (x.size - 3)}"
|
||||
h3 {
|
||||
+"Chi2/dof = ${result.resultValue / (x.size - 3)}"
|
||||
}
|
||||
}
|
||||
|
||||
page.makeFile()
|
||||
}
|
||||
}
|
112
examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.fit
|
||||
|
||||
import kotlinx.html.br
|
||||
import kotlinx.html.h3
|
||||
import space.kscience.attributes.Attributes
|
||||
import space.kscience.kmath.data.XYErrorColumnarData
|
||||
import space.kscience.kmath.distributions.NormalDistribution
|
||||
import space.kscience.kmath.expressions.Symbol
|
||||
import space.kscience.kmath.expressions.autodiff
|
||||
import space.kscience.kmath.expressions.binding
|
||||
import space.kscience.kmath.expressions.symbol
|
||||
import space.kscience.kmath.operations.asIterable
|
||||
import space.kscience.kmath.operations.toList
|
||||
import space.kscience.kmath.optimization.*
|
||||
import space.kscience.kmath.random.RandomGenerator
|
||||
import space.kscience.kmath.real.map
|
||||
import space.kscience.kmath.real.step
|
||||
import space.kscience.plotly.*
|
||||
import space.kscience.plotly.models.ScatterMode
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sqrt
|
||||
|
||||
// Forward declaration of symbols that will be used in expressions.
|
||||
private val a by symbol
|
||||
private val b by symbol
|
||||
private val c by symbol
|
||||
private val d by symbol
|
||||
private val e by symbol
|
||||
|
||||
|
||||
/**
|
||||
* Least squares fie with auto-differentiation. Uses `kmath-commons` and `kmath-for-real` modules.
|
||||
*/
|
||||
suspend fun main() {
|
||||
//A generator for a normally distributed values
|
||||
val generator = NormalDistribution(0.0, 1.0)
|
||||
|
||||
//A chain/flow of random values with the given seed
|
||||
val chain = generator.sample(RandomGenerator.default(112667))
|
||||
|
||||
|
||||
//Create a uniformly distributed x values like numpy.arrange
|
||||
val x = 1.0..100.0 step 1.0
|
||||
|
||||
|
||||
//Perform an operation on each x value (much more effective, than numpy)
|
||||
val y = x.map { it ->
|
||||
val value = it.pow(2) + it + 1
|
||||
value + chain.next() * sqrt(value)
|
||||
}
|
||||
// this will also work, but less effective:
|
||||
// val y = x.pow(2)+ x + 1 + chain.nextDouble()
|
||||
|
||||
// create same errors for all xs
|
||||
val yErr = y.map { sqrt(abs(it)) }
|
||||
require(yErr.asIterable().all { it > 0 }) { "All errors must be strictly positive" }
|
||||
|
||||
val result = XYErrorColumnarData.of(x, y, yErr).fitWith(
|
||||
QowOptimizer,
|
||||
Double.autodiff,
|
||||
mapOf(a to 0.9, b to 1.2, c to 2.0, e to 1.0, d to 1.0, e to 0.0),
|
||||
attributes = Attributes(OptimizationParameters, listOf(a, b, c, d))
|
||||
) { arg ->
|
||||
//bind variables to autodiff context
|
||||
val a by binding
|
||||
val b by binding
|
||||
//Include default value for c if it is not provided as a parameter
|
||||
val c = bindSymbolOrNull(c) ?: one
|
||||
val d by binding
|
||||
val e by binding
|
||||
|
||||
a * arg.pow(2) + b * arg + c + d * arg.pow(3) + e / arg
|
||||
}
|
||||
|
||||
println("Resulting chi2/dof: ${result.chiSquaredOrNull}/${result.dof}")
|
||||
|
||||
//display a page with plot and numerical results
|
||||
val page = Plotly.page {
|
||||
plot {
|
||||
scatter {
|
||||
mode = ScatterMode.markers
|
||||
x(x)
|
||||
y(y)
|
||||
error_y {
|
||||
array = yErr.toList()
|
||||
}
|
||||
name = "data"
|
||||
}
|
||||
scatter {
|
||||
mode = ScatterMode.lines
|
||||
x(x)
|
||||
y(x.map { result.model(result.startPoint + result.result + (Symbol.x to it)) })
|
||||
name = "fit"
|
||||
}
|
||||
}
|
||||
br()
|
||||
h3 {
|
||||
+"Fit result: ${result.result}"
|
||||
}
|
||||
h3 {
|
||||
+"Chi2/dof = ${result.chiSquaredOrNull!! / result.dof}"
|
||||
}
|
||||
}
|
||||
|
||||
page.makeFile()
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.functions
|
||||
|
||||
import space.kscience.kmath.complex.Complex
|
||||
import space.kscience.kmath.complex.ComplexField
|
||||
import space.kscience.kmath.complex.ComplexField.div
|
||||
import space.kscience.kmath.complex.ComplexField.minus
|
||||
import space.kscience.kmath.complex.algebra
|
||||
import space.kscience.kmath.integration.gaussIntegrator
|
||||
import space.kscience.kmath.integration.integrate
|
||||
import space.kscience.kmath.integration.value
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import kotlin.math.pow
|
||||
|
||||
fun main() {
|
||||
//Define a function
|
||||
val function: Function1D<Double> = { x -> 3 * x.pow(2) + 2 * x + 1 }
|
||||
|
||||
//get the result of the integration
|
||||
val result = Float64Field.gaussIntegrator.integrate(0.0..10.0, function = function)
|
||||
|
||||
//the value is nullable because in some cases the integration could not succeed
|
||||
println(result.value)
|
||||
|
||||
|
||||
repeat(100000) {
|
||||
Complex.algebra.gaussIntegrator.integrate(0.0..1.0, intervals = 1000) { x: Double ->
|
||||
// sin(1 / x) + i * cos(1 / x)
|
||||
1 / x - ComplexField.i / x
|
||||
}.value
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.functions
|
||||
|
||||
import space.kscience.kmath.interpolation.SplineInterpolator
|
||||
import space.kscience.kmath.interpolation.interpolatePolynomials
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.UnstablePlotlyAPI
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.functionXY
|
||||
import space.kscience.plotly.scatter
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.sin
|
||||
|
||||
@OptIn(UnstablePlotlyAPI::class)
|
||||
fun main() {
|
||||
val data = (0..10).map {
|
||||
val x = it.toDouble() / 5 * PI
|
||||
x to sin(x)
|
||||
}
|
||||
|
||||
val polynomial: PiecewisePolynomial<Double> = SplineInterpolator(Float64Field).interpolatePolynomials(data)
|
||||
|
||||
val function = polynomial.asFunction(Float64Field, 0.0)
|
||||
|
||||
val cmInterpolate = org.apache.commons.math3.analysis.interpolation.SplineInterpolator().interpolate(
|
||||
data.map { it.first }.toDoubleArray(),
|
||||
data.map { it.second }.toDoubleArray()
|
||||
)
|
||||
|
||||
Plotly.plot {
|
||||
scatter {
|
||||
name = "interpolated"
|
||||
x.numbers = data.map { it.first }
|
||||
y.numbers = x.doubles.map { function(it) }
|
||||
}
|
||||
scatter {
|
||||
name = "original"
|
||||
functionXY(0.0..(2 * PI), 0.1) { sin(it) }
|
||||
}
|
||||
scatter {
|
||||
name = "cm"
|
||||
x.numbers = data.map { it.first }
|
||||
y.numbers = x.doubles.map { cmInterpolate.value(it) }
|
||||
}
|
||||
}.makeFile()
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.functions
|
||||
|
||||
import space.kscience.kmath.interpolation.interpolatePolynomials
|
||||
import space.kscience.kmath.interpolation.splineInterpolator
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.real.map
|
||||
import space.kscience.kmath.real.step
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.UnstablePlotlyAPI
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.functionXY
|
||||
import space.kscience.plotly.scatter
|
||||
|
||||
@OptIn(UnstablePlotlyAPI::class)
|
||||
fun main() {
|
||||
val function: Function1D<Double> = { x ->
|
||||
if (x in 30.0..50.0) {
|
||||
1.0
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
val xs = 0.0..100.0 step 0.5
|
||||
val ys = xs.map(function)
|
||||
|
||||
val polynomial: PiecewisePolynomial<Double> = Float64Field.splineInterpolator.interpolatePolynomials(xs, ys)
|
||||
|
||||
val polyFunction = polynomial.asFunction(Float64Field, 0.0)
|
||||
|
||||
Plotly.plot {
|
||||
scatter {
|
||||
name = "interpolated"
|
||||
functionXY(25.0..55.0, 0.1) { polyFunction(it) }
|
||||
}
|
||||
scatter {
|
||||
name = "original"
|
||||
functionXY(25.0..55.0, 0.1) { function(it) }
|
||||
}
|
||||
}.makeFile()
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.functions
|
||||
|
||||
import space.kscience.kmath.integration.gaussIntegrator
|
||||
import space.kscience.kmath.integration.integrate
|
||||
import space.kscience.kmath.integration.value
|
||||
import space.kscience.kmath.nd.StructureND
|
||||
import space.kscience.kmath.nd.structureND
|
||||
import space.kscience.kmath.nd.withNdAlgebra
|
||||
import space.kscience.kmath.operations.algebra
|
||||
import kotlin.math.pow
|
||||
|
||||
fun main(): Unit = Double.algebra.withNdAlgebra(2, 2) {
|
||||
|
||||
//Produce a diagonal StructureND
|
||||
fun diagonal(v: Double) = structureND { (i, j) ->
|
||||
if (i == j) v else 0.0
|
||||
}
|
||||
|
||||
//Define a function in a nd space
|
||||
val function: (Double) -> StructureND<Double> = { x: Double -> 3 * x.pow(2) + 2 * diagonal(x) + 1 }
|
||||
|
||||
//get the result of the integration
|
||||
val result = gaussIntegrator.integrate(0.0..10.0, function = function)
|
||||
|
||||
//the value is nullable because in some cases the integration could not succeed
|
||||
println(result.value)
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.jafama
|
||||
|
||||
import space.kscience.kmath.operations.invoke
|
||||
|
||||
fun main() {
|
||||
val a = 2.0
|
||||
val b = StrictJafamaDoubleField { exp(a) }
|
||||
println(JafamaDoubleField { b + a })
|
||||
println(StrictJafamaDoubleField { ln(b) })
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.linear
|
||||
|
||||
import kotlin.random.Random
|
||||
import kotlin.time.measureTime
|
||||
|
||||
fun main() = with(Float64ParallelLinearSpace) {
|
||||
val random = Random(12224)
|
||||
val dim = 1000
|
||||
|
||||
//creating invertible matrix
|
||||
val matrix1 = buildMatrix(dim, dim) { i, j ->
|
||||
if (i <= j) random.nextDouble() else 0.0
|
||||
}
|
||||
val matrix2 = buildMatrix(dim, dim) { i, j ->
|
||||
if (i <= j) random.nextDouble() else 0.0
|
||||
}
|
||||
|
||||
val time = measureTime {
|
||||
repeat(30) {
|
||||
matrix1 dot matrix2
|
||||
}
|
||||
}
|
||||
|
||||
println(time)
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.linear
|
||||
|
||||
import space.kscience.kmath.real.*
|
||||
import space.kscience.kmath.structures.Float64Buffer
|
||||
|
||||
fun main() {
|
||||
val x0 = DoubleVector(0.0, 0.0, 0.0)
|
||||
val sigma = DoubleVector(1.0, 1.0, 1.0)
|
||||
|
||||
val gaussian: (Point<Double>) -> Double = { x ->
|
||||
require(x.size == x0.size)
|
||||
kotlin.math.exp(-((x - x0) / sigma).square().sum())
|
||||
}
|
||||
|
||||
fun ((Point<Double>) -> Double).grad(x: Point<Double>): Point<Double> {
|
||||
require(x.size == x0.size)
|
||||
return Float64Buffer(x.size) { i ->
|
||||
val h = sigma[i] / 5
|
||||
val dVector = Float64Buffer(x.size) { if (it == i) h else 0.0 }
|
||||
val f1 = this(x + dVector / 2)
|
||||
val f0 = this(x - dVector / 2)
|
||||
(f1 - f0) / h
|
||||
}
|
||||
}
|
||||
|
||||
println(gaussian.grad(x0))
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.linear
|
||||
|
||||
import kotlin.random.Random
|
||||
import kotlin.time.measureTime
|
||||
|
||||
fun main(): Unit = with(Float64LinearSpace) {
|
||||
val random = Random(1224)
|
||||
val dim = 500
|
||||
|
||||
//creating invertible matrix
|
||||
val u = buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
|
||||
val l = buildMatrix(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 }
|
||||
val matrix = l dot u
|
||||
|
||||
val time = measureTime {
|
||||
repeat(20) {
|
||||
lupSolver().inverse(matrix)
|
||||
}
|
||||
}
|
||||
|
||||
println(time)
|
||||
}
|
@ -1,3 +1,8 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.operations
|
||||
|
||||
fun main() {
|
||||
|
@ -1,24 +0,0 @@
|
||||
package space.kscience.kmath.operations
|
||||
|
||||
import space.kscience.kmath.complex.Complex
|
||||
import space.kscience.kmath.complex.complex
|
||||
import space.kscience.kmath.nd.NDAlgebra
|
||||
|
||||
fun main() {
|
||||
// 2d element
|
||||
val element = NDAlgebra.complex(2, 2).produce { (i, j) ->
|
||||
Complex(i.toDouble() - j.toDouble(), i.toDouble() + j.toDouble())
|
||||
}
|
||||
println(element)
|
||||
|
||||
// 1d element operation
|
||||
val result = with(NDAlgebra.complex(8)) {
|
||||
val a = produce { (it) -> i * it - it.toDouble() }
|
||||
val b = 3
|
||||
val c = Complex(1.0, 1.0)
|
||||
|
||||
(a pow b) + c
|
||||
}
|
||||
|
||||
println(result)
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.operations
|
||||
|
||||
import space.kscience.kmath.complex.Complex
|
||||
import space.kscience.kmath.complex.algebra
|
||||
import space.kscience.kmath.complex.ndAlgebra
|
||||
import space.kscience.kmath.nd.BufferND
|
||||
import space.kscience.kmath.nd.StructureND
|
||||
import space.kscience.kmath.nd.structureND
|
||||
|
||||
fun main() = Complex.algebra {
|
||||
val complex = 2 + 2 * i
|
||||
println(complex * 8 - 5 * i)
|
||||
|
||||
//flat buffer
|
||||
val buffer = with(bufferAlgebra) {
|
||||
buffer(8) { Complex(it, -it) }.map { Complex(it.im, it.re) }
|
||||
}
|
||||
println(buffer)
|
||||
|
||||
// 2d element
|
||||
val element: BufferND<Complex> = ndAlgebra.structureND(2, 2) { (i, j) ->
|
||||
Complex(i - j, i + j)
|
||||
}
|
||||
println(element)
|
||||
|
||||
// 1d element operation
|
||||
val result: StructureND<Complex> = ndAlgebra {
|
||||
val a = structureND(8) { (it) -> i * it - it.toDouble() }
|
||||
val b = 3
|
||||
val c = Complex(1.0, 1.0)
|
||||
|
||||
(a pow b) + c
|
||||
}
|
||||
println(result)
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.operations
|
||||
|
||||
import space.kscience.kmath.commons.linear.CMLinearSpace
|
||||
import space.kscience.kmath.linear.matrix
|
||||
import space.kscience.kmath.nd.Float64BufferND
|
||||
import space.kscience.kmath.nd.Structure2D
|
||||
import space.kscience.kmath.nd.mutableStructureND
|
||||
import space.kscience.kmath.nd.ndAlgebra
|
||||
import space.kscience.kmath.viktor.viktorAlgebra
|
||||
import kotlin.collections.component1
|
||||
import kotlin.collections.component2
|
||||
|
||||
fun main() {
|
||||
val viktorStructure = Float64Field.viktorAlgebra.mutableStructureND(2, 2) { (i, j) ->
|
||||
if (i == j) 2.0 else 0.0
|
||||
}
|
||||
|
||||
val cmMatrix: Structure2D<Double> = CMLinearSpace.matrix(2, 2)(0.0, 1.0, 0.0, 3.0)
|
||||
|
||||
val res: Float64BufferND = Float64Field.ndAlgebra {
|
||||
exp(viktorStructure) + 2.0 * cmMatrix
|
||||
}
|
||||
|
||||
println(res)
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.series
|
||||
|
||||
import kotlinx.datetime.Instant
|
||||
import space.kscience.kmath.operations.algebra
|
||||
import space.kscience.kmath.operations.bufferAlgebra
|
||||
import kotlin.time.Duration
|
||||
|
||||
fun SeriesAlgebra.Companion.time(zero: Instant, step: Duration) = MonotonicSeriesAlgebra(
|
||||
bufferAlgebra = Double.algebra.bufferAlgebra,
|
||||
offsetToLabel = { zero + step * it },
|
||||
labelToOffset = { (it - zero) / step }
|
||||
)
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.series
|
||||
|
||||
|
||||
import kotlinx.html.h1
|
||||
import kotlinx.html.p
|
||||
import space.kscience.kmath.operations.algebra
|
||||
import space.kscience.kmath.operations.bufferAlgebra
|
||||
import space.kscience.kmath.operations.toList
|
||||
import space.kscience.kmath.stat.KMComparisonResult
|
||||
import space.kscience.kmath.stat.ksComparisonStatistic
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.slice
|
||||
import space.kscience.plotly.*
|
||||
import kotlin.math.PI
|
||||
|
||||
fun Double.Companion.seriesAlgebra() = Double.algebra.bufferAlgebra.seriesAlgebra()
|
||||
|
||||
|
||||
fun main() = with(Double.seriesAlgebra()) {
|
||||
|
||||
|
||||
fun Plot.plotSeries(name: String, buffer: Buffer<Double>) {
|
||||
scatter {
|
||||
this.name = name
|
||||
x.numbers = buffer.labels
|
||||
y.numbers = buffer.toList()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val s1 = series(100) { sin(2 * PI * it / 100) + 1.0 }
|
||||
|
||||
val s2 = s1.slice(20..50).moveTo(40)
|
||||
|
||||
val s3: Buffer<Double> = s1.zip(s2) { l, r -> l + r } //s1 + s2
|
||||
val s4 = s3.map { ln(it) }
|
||||
|
||||
val kmTest: KMComparisonResult<Double> = ksComparisonStatistic(s1, s2)
|
||||
|
||||
Plotly.page {
|
||||
h1 { +"This is my plot" }
|
||||
p {
|
||||
+"Kolmogorov-smirnov test for s1 and s2: ${kmTest.value}"
|
||||
}
|
||||
plot {
|
||||
plotSeries("s1", s1)
|
||||
plotSeries("s2", s2)
|
||||
plotSeries("s3", s3)
|
||||
plotSeries("s4", s4)
|
||||
layout {
|
||||
xaxis {
|
||||
range(0.0..100.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}.makeFile()
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2018-2023 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.series
|
||||
|
||||
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.Float64Buffer
|
||||
import space.kscience.kmath.structures.asBuffer
|
||||
import space.kscience.kmath.structures.toDoubleArray
|
||||
import space.kscience.plotly.*
|
||||
import space.kscience.plotly.models.Scatter
|
||||
import space.kscience.plotly.models.ScatterMode
|
||||
import kotlin.random.Random
|
||||
|
||||
fun main(): Unit = with(Double.seriesAlgebra()) {
|
||||
|
||||
val random = Random(1234)
|
||||
|
||||
val arrayOfRandoms = DoubleArray(20) { random.nextDouble() }
|
||||
|
||||
val series1: Float64Buffer = arrayOfRandoms.asBuffer()
|
||||
val series2: Series<Double> = series1.moveBy(3)
|
||||
|
||||
val res = series2 - series1
|
||||
|
||||
println(res.size)
|
||||
|
||||
println(res)
|
||||
|
||||
fun Plot.series(name: String, buffer: Buffer<Double>, block: Scatter.() -> Unit = {}) {
|
||||
scatter {
|
||||
this.name = name
|
||||
x.numbers = buffer.offsetIndices
|
||||
y.doubles = buffer.toDoubleArray()
|
||||
block()
|
||||
}
|
||||
}
|
||||
|
||||
Plotly.plot {
|
||||
series("series1", series1)
|
||||
series("series2", series2)
|
||||
series("dif", res) {
|
||||
mode = ScatterMode.lines
|
||||
line.color("magenta")
|
||||
}
|
||||
}.makeFile(resourceLocation = ResourceLocation.REMOTE)
|
||||
}
|
@ -1,23 +1,30 @@
|
||||
package kscience.kmath.commons.prob
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.stat
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler
|
||||
import org.apache.commons.rng.sampling.distribution.BoxMullerNormalizedGaussianSampler
|
||||
import org.apache.commons.rng.simple.RandomSource
|
||||
import space.kscience.kmath.stat.*
|
||||
import space.kscience.kmath.random.RandomGenerator
|
||||
import space.kscience.kmath.samplers.GaussianSampler
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
import org.apache.commons.rng.sampling.distribution.GaussianSampler as CMGaussianSampler
|
||||
|
||||
private fun runChain(): Duration {
|
||||
private suspend fun runKMathChained(): Duration {
|
||||
val generator = RandomGenerator.fromSource(RandomSource.MT, 123L)
|
||||
val normal = Distribution.normal(NormalSamplerMethod.Ziggurat)
|
||||
val normal = GaussianSampler(7.0, 2.0)
|
||||
val chain = normal.sample(generator)
|
||||
val startTime = Instant.now()
|
||||
var sum = 0.0
|
||||
|
||||
repeat(10000001) { counter ->
|
||||
sum += chain.nextDouble()
|
||||
sum += chain.next()
|
||||
|
||||
if (counter % 100000 == 0) {
|
||||
val duration = Duration.between(startTime, Instant.now())
|
||||
@ -29,9 +36,15 @@ private fun runChain(): Duration {
|
||||
return Duration.between(startTime, Instant.now())
|
||||
}
|
||||
|
||||
private fun runDirect(): Duration {
|
||||
val provider = RandomSource.create(RandomSource.MT, 123L)
|
||||
val sampler = ZigguratNormalizedGaussianSampler(provider)
|
||||
private fun runCMDirect(): Duration {
|
||||
val rng = RandomSource.create(RandomSource.MT, 123L)
|
||||
|
||||
val sampler = CMGaussianSampler.of(
|
||||
BoxMullerNormalizedGaussianSampler.of(rng),
|
||||
7.0,
|
||||
2.0
|
||||
)
|
||||
|
||||
val startTime = Instant.now()
|
||||
var sum = 0.0
|
||||
|
||||
@ -51,11 +64,9 @@ private fun runDirect(): Duration {
|
||||
/**
|
||||
* Comparing chain sampling performance with direct sampling performance
|
||||
*/
|
||||
fun main() {
|
||||
runBlocking(Dispatchers.Default) {
|
||||
val chainJob = async { runChain() }
|
||||
val directJob = async { runDirect() }
|
||||
println("Chain: ${chainJob.await()}")
|
||||
println("Direct: ${directJob.await()}")
|
||||
}
|
||||
fun main(): Unit = runBlocking(Dispatchers.Default) {
|
||||
val directJob = async { runCMDirect() }
|
||||
val chainJob = async { runKMathChained() }
|
||||
println("KMath Chained: ${chainJob.await()}")
|
||||
println("Apache Direct: ${directJob.await()}")
|
||||
}
|
||||
|
@ -1,27 +1,31 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.stat
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import space.kscience.kmath.chains.Chain
|
||||
import space.kscience.kmath.chains.collectWithState
|
||||
import space.kscience.kmath.chains.combineWithState
|
||||
import space.kscience.kmath.distributions.NormalDistribution
|
||||
import space.kscience.kmath.random.RandomGenerator
|
||||
|
||||
/**
|
||||
* The state of distribution averager
|
||||
*/
|
||||
private data class AveragingChainState(var num: Int = 0, var value: Double = 0.0)
|
||||
|
||||
/**
|
||||
* Averaging
|
||||
* Averaging.
|
||||
*/
|
||||
private fun Chain<Double>.mean(): Chain<Double> = collectWithState(AveragingChainState(), { it.copy() }) { chain ->
|
||||
private fun Chain<Double>.mean(): Chain<Double> = combineWithState(AveragingChainState(), { it.copy() }) { chain ->
|
||||
val next = chain.next()
|
||||
num++
|
||||
value += next
|
||||
return@collectWithState value / num
|
||||
return@combineWithState value / num
|
||||
}
|
||||
|
||||
|
||||
fun main() {
|
||||
val normal = Distribution.normal()
|
||||
val normal = NormalDistribution(0.0, 2.0)
|
||||
val chain = normal.sample(RandomGenerator.default).mean()
|
||||
|
||||
runBlocking {
|
||||
@ -32,4 +36,4 @@ fun main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,19 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("unused")
|
||||
|
||||
package space.kscience.kmath.structures
|
||||
|
||||
import space.kscience.kmath.complex.*
|
||||
import space.kscience.kmath.linear.transpose
|
||||
import space.kscience.kmath.nd.NDAlgebra
|
||||
import space.kscience.kmath.nd.NDStructure
|
||||
import space.kscience.kmath.linear.transposed
|
||||
import space.kscience.kmath.nd.StructureND
|
||||
import space.kscience.kmath.nd.as2D
|
||||
import space.kscience.kmath.nd.real
|
||||
import space.kscience.kmath.nd.ndAlgebra
|
||||
import space.kscience.kmath.nd.structureND
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import kotlin.system.measureTimeMillis
|
||||
|
||||
@ -15,12 +21,12 @@ fun main() {
|
||||
val dim = 1000
|
||||
val n = 1000
|
||||
|
||||
val realField = NDAlgebra.real(dim, dim)
|
||||
val complexField: ComplexNDField = NDAlgebra.complex(dim, dim)
|
||||
val realField = Float64Field.ndAlgebra(dim, dim)
|
||||
val complexField: ComplexFieldND = ComplexField.ndAlgebra(dim, dim)
|
||||
|
||||
val realTime = measureTimeMillis {
|
||||
realField {
|
||||
var res: NDStructure<Double> = one
|
||||
var res: StructureND<Double> = one
|
||||
repeat(n) {
|
||||
res += 1.0
|
||||
}
|
||||
@ -31,7 +37,7 @@ fun main() {
|
||||
|
||||
val complexTime = measureTimeMillis {
|
||||
complexField {
|
||||
var res: NDStructure<Complex> = one
|
||||
var res: StructureND<Complex> = one
|
||||
repeat(n) {
|
||||
res += 1.0
|
||||
}
|
||||
@ -44,17 +50,17 @@ fun main() {
|
||||
fun complexExample() {
|
||||
//Create a context for 2-d structure with complex values
|
||||
ComplexField {
|
||||
nd(4, 8) {
|
||||
withNdAlgebra(4, 8) {
|
||||
//a constant real-valued structure
|
||||
val x = one * 2.5
|
||||
operator fun Number.plus(other: Complex) = Complex(this.toDouble() + other.re, other.im)
|
||||
//a structure generator specific to this context
|
||||
val matrix = produce { (k, l) -> k + l * i }
|
||||
val matrix = structureND { (k, l) -> k + l * i }
|
||||
//Perform sum
|
||||
val sum = matrix + x + 1.0
|
||||
|
||||
//Represent the sum as 2d-structure and transpose
|
||||
sum.as2D().transpose()
|
||||
sum.as2D().transposed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,18 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.structures
|
||||
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import org.nd4j.linalg.factory.Nd4j
|
||||
import space.kscience.kmath.nd.*
|
||||
import space.kscience.kmath.nd4j.Nd4jArrayField
|
||||
import space.kscience.kmath.operations.RealField
|
||||
import space.kscience.kmath.nd4j.nd4j
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.operations.invoke
|
||||
import space.kscience.kmath.viktor.ViktorNDField
|
||||
import space.kscience.kmath.viktor.ViktorFieldND
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.system.measureTimeMillis
|
||||
@ -17,69 +23,63 @@ internal inline fun measureAndPrint(title: String, block: () -> Unit) {
|
||||
println("$title completed in $time millis")
|
||||
}
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
fun main() {
|
||||
// initializing Nd4j
|
||||
Nd4j.zeros(0)
|
||||
val dim = 1000
|
||||
val n = 1000
|
||||
val shape = ShapeND(dim, dim)
|
||||
|
||||
// automatically build context most suited for given type.
|
||||
val autoField = NDAlgebra.auto(RealField, dim, dim)
|
||||
// specialized nd-field for Double. It works as generic Double field as well
|
||||
val realField = NDAlgebra.real(dim, dim)
|
||||
//A generic boxing field. It should be used for objects, not primitives.
|
||||
val boxingField = NDAlgebra.field(RealField, Buffer.Companion::boxing, dim, dim)
|
||||
|
||||
// specialized nd-field for Double. It works as generic Double field as well.
|
||||
val doubleField = Float64Field.ndAlgebra
|
||||
//A generic field. It should be used for objects, not primitives.
|
||||
val genericField = BufferedFieldOpsND(Float64Field)
|
||||
// Nd4j specialized field.
|
||||
val nd4jField = Nd4jArrayField.real(dim, dim)
|
||||
val nd4jField = Float64Field.nd4j
|
||||
//viktor field
|
||||
val viktorField = ViktorNDField(dim,dim)
|
||||
val viktorField = ViktorFieldND(dim, dim)
|
||||
//parallel processing based on Java Streams
|
||||
val parallelField = NDAlgebra.realWithStream(dim,dim)
|
||||
val parallelField = Float64Field.ndStreaming(dim, dim)
|
||||
|
||||
measureAndPrint("Boxing addition") {
|
||||
boxingField {
|
||||
var res: NDStructure<Double> = one
|
||||
genericField {
|
||||
var res: StructureND<Double> = one(shape)
|
||||
repeat(n) { res += 1.0 }
|
||||
}
|
||||
}
|
||||
|
||||
measureAndPrint("Specialized addition") {
|
||||
realField {
|
||||
var res: NDStructure<Double> = one
|
||||
doubleField {
|
||||
var res: StructureND<Double> = one(shape)
|
||||
repeat(n) { res += 1.0 }
|
||||
}
|
||||
}
|
||||
|
||||
measureAndPrint("Nd4j specialized addition") {
|
||||
nd4jField {
|
||||
var res: NDStructure<Double> = one
|
||||
var res: StructureND<Double> = one(shape)
|
||||
repeat(n) { res += 1.0 }
|
||||
}
|
||||
}
|
||||
|
||||
measureAndPrint("Viktor addition") {
|
||||
viktorField {
|
||||
var res: NDStructure<Double> = one
|
||||
var res: StructureND<Double> = one
|
||||
repeat(n) { res += 1.0 }
|
||||
}
|
||||
}
|
||||
|
||||
measureAndPrint("Parallel stream addition") {
|
||||
parallelField {
|
||||
var res: NDStructure<Double> = one
|
||||
repeat(n) { res += 1.0 }
|
||||
}
|
||||
}
|
||||
|
||||
measureAndPrint("Automatic field addition") {
|
||||
autoField {
|
||||
var res: NDStructure<Double> = one
|
||||
var res: StructureND<Double> = one
|
||||
repeat(n) { res += 1.0 }
|
||||
}
|
||||
}
|
||||
|
||||
measureAndPrint("Lazy addition") {
|
||||
val res = realField.one.mapAsync(GlobalScope) {
|
||||
val res = doubleField.one(shape).mapAsync(GlobalScope) {
|
||||
var c = 0.0
|
||||
repeat(n) {
|
||||
c += 1.0
|
||||
|
@ -1,103 +0,0 @@
|
||||
package space.kscience.kmath.structures
|
||||
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.nd.*
|
||||
import space.kscience.kmath.operations.ExtendedField
|
||||
import space.kscience.kmath.operations.RealField
|
||||
import space.kscience.kmath.operations.RingWithNumbers
|
||||
import java.util.*
|
||||
import java.util.stream.IntStream
|
||||
|
||||
/**
|
||||
* A demonstration implementation of NDField over Real using Java [DoubleStream] for parallel execution
|
||||
*/
|
||||
@OptIn(UnstableKMathAPI::class)
|
||||
class StreamRealNDField(
|
||||
override val shape: IntArray,
|
||||
) : NDField<Double, RealField>,
|
||||
RingWithNumbers<NDStructure<Double>>,
|
||||
ExtendedField<NDStructure<Double>> {
|
||||
|
||||
private val strides = DefaultStrides(shape)
|
||||
override val elementContext: RealField get() = RealField
|
||||
override val zero: NDBuffer<Double> by lazy { produce { zero } }
|
||||
override val one: NDBuffer<Double> by lazy { produce { one } }
|
||||
|
||||
override fun number(value: Number): NDBuffer<Double> {
|
||||
val d = value.toDouble() // minimize conversions
|
||||
return produce { d }
|
||||
}
|
||||
|
||||
private val NDStructure<Double>.buffer: RealBuffer
|
||||
get() = when {
|
||||
!shape.contentEquals(this@StreamRealNDField.shape) -> throw ShapeMismatchException(
|
||||
this@StreamRealNDField.shape,
|
||||
shape
|
||||
)
|
||||
this is NDBuffer && this.strides == this@StreamRealNDField.strides -> this.buffer as RealBuffer
|
||||
else -> RealBuffer(strides.linearSize) { offset -> get(strides.index(offset)) }
|
||||
}
|
||||
|
||||
|
||||
override fun produce(initializer: RealField.(IntArray) -> Double): NDBuffer<Double> {
|
||||
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
||||
val index = strides.index(offset)
|
||||
RealField.initializer(index)
|
||||
}.toArray()
|
||||
|
||||
return NDBuffer(strides, array.asBuffer())
|
||||
}
|
||||
|
||||
override fun NDStructure<Double>.map(
|
||||
transform: RealField.(Double) -> Double,
|
||||
): NDBuffer<Double> {
|
||||
val array = Arrays.stream(buffer.array).parallel().map { RealField.transform(it) }.toArray()
|
||||
return NDBuffer(strides, array.asBuffer())
|
||||
}
|
||||
|
||||
override fun NDStructure<Double>.mapIndexed(
|
||||
transform: RealField.(index: IntArray, Double) -> Double,
|
||||
): NDBuffer<Double> {
|
||||
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
||||
RealField.transform(
|
||||
strides.index(offset),
|
||||
buffer.array[offset]
|
||||
)
|
||||
}.toArray()
|
||||
|
||||
return NDBuffer(strides, array.asBuffer())
|
||||
}
|
||||
|
||||
override fun combine(
|
||||
a: NDStructure<Double>,
|
||||
b: NDStructure<Double>,
|
||||
transform: RealField.(Double, Double) -> Double,
|
||||
): NDBuffer<Double> {
|
||||
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
||||
RealField.transform(a.buffer.array[offset], b.buffer.array[offset])
|
||||
}.toArray()
|
||||
return NDBuffer(strides, array.asBuffer())
|
||||
}
|
||||
|
||||
override fun power(arg: NDStructure<Double>, pow: Number): NDBuffer<Double> = arg.map() { power(it, pow) }
|
||||
|
||||
override fun exp(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { exp(it) }
|
||||
|
||||
override fun ln(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { ln(it) }
|
||||
|
||||
override fun sin(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { sin(it) }
|
||||
override fun cos(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { cos(it) }
|
||||
override fun tan(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { tan(it) }
|
||||
override fun asin(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { asin(it) }
|
||||
override fun acos(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { acos(it) }
|
||||
override fun atan(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { atan(it) }
|
||||
|
||||
override fun sinh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { sinh(it) }
|
||||
override fun cosh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { cosh(it) }
|
||||
override fun tanh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { tanh(it) }
|
||||
override fun asinh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { asinh(it) }
|
||||
override fun acosh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { acosh(it) }
|
||||
override fun atanh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { atanh(it) }
|
||||
}
|
||||
|
||||
fun NDAlgebra.Companion.realWithStream(vararg shape: Int): StreamRealNDField = StreamRealNDField(shape)
|
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2018-2024 KMath contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package space.kscience.kmath.structures
|
||||
|
||||
import space.kscience.kmath.PerformancePitfall
|
||||
import space.kscience.kmath.nd.*
|
||||
import space.kscience.kmath.operations.DoubleField
|
||||
import space.kscience.kmath.operations.ExtendedField
|
||||
import space.kscience.kmath.operations.Float64Field
|
||||
import space.kscience.kmath.operations.NumbersAddOps
|
||||
import java.util.*
|
||||
import java.util.stream.IntStream
|
||||
|
||||
/**
|
||||
* A demonstration implementation of NDField over Real using Java [java.util.stream.DoubleStream] for parallel
|
||||
* execution.
|
||||
*/
|
||||
class StreamDoubleFieldND(override val shape: ShapeND) : FieldND<Double, Float64Field>,
|
||||
NumbersAddOps<StructureND<Double>>,
|
||||
ExtendedField<StructureND<Double>> {
|
||||
|
||||
private val strides = ColumnStrides(shape)
|
||||
override val elementAlgebra: Float64Field get() = Float64Field
|
||||
override val zero: BufferND<Double> by lazy { structureND(shape) { zero } }
|
||||
override val one: BufferND<Double> by lazy { structureND(shape) { one } }
|
||||
|
||||
override fun number(value: Number): BufferND<Double> {
|
||||
val d = value.toDouble() // minimize conversions
|
||||
return structureND(shape) { d }
|
||||
}
|
||||
|
||||
@OptIn(PerformancePitfall::class)
|
||||
private val StructureND<Double>.buffer: Float64Buffer
|
||||
get() = when {
|
||||
shape != this@StreamDoubleFieldND.shape -> throw ShapeMismatchException(
|
||||
this@StreamDoubleFieldND.shape,
|
||||
shape
|
||||
)
|
||||
|
||||
this is BufferND && indices == this@StreamDoubleFieldND.strides -> this.buffer as Float64Buffer
|
||||
else -> Float64Buffer(strides.linearSize) { offset -> get(strides.index(offset)) }
|
||||
}
|
||||
|
||||
override fun structureND(shape: ShapeND, initializer: Float64Field.(IntArray) -> Double): BufferND<Double> {
|
||||
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
||||
val index = strides.index(offset)
|
||||
Float64Field.initializer(index)
|
||||
}.toArray()
|
||||
|
||||
return BufferND(strides, array.asBuffer())
|
||||
}
|
||||
|
||||
override fun mutableStructureND(
|
||||
shape: ShapeND,
|
||||
initializer: DoubleField.(IntArray) -> Double,
|
||||
): MutableBufferND<Double> {
|
||||
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
||||
val index = strides.index(offset)
|
||||
DoubleField.initializer(index)
|
||||
}.toArray()
|
||||
|
||||
return MutableBufferND(strides, array.asBuffer())
|
||||
}
|
||||
|
||||
@OptIn(PerformancePitfall::class)
|
||||
override fun StructureND<Double>.map(
|
||||
transform: Float64Field.(Double) -> Double,
|
||||
): BufferND<Double> {
|
||||
val array = Arrays.stream(buffer.array).parallel().map { Float64Field.transform(it) }.toArray()
|
||||
return BufferND(strides, array.asBuffer())
|
||||
}
|
||||
|
||||
@OptIn(PerformancePitfall::class)
|
||||
override fun StructureND<Double>.mapIndexed(
|
||||
transform: Float64Field.(index: IntArray, Double) -> Double,
|
||||
): BufferND<Double> {
|
||||
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
||||
Float64Field.transform(
|
||||
strides.index(offset),
|
||||
buffer.array[offset]
|
||||
)
|
||||
}.toArray()
|
||||
|
||||
return BufferND(strides, array.asBuffer())
|
||||
}
|
||||
|
||||
@OptIn(PerformancePitfall::class)
|
||||
override fun zip(
|
||||
left: StructureND<Double>,
|
||||
right: StructureND<Double>,
|
||||
transform: Float64Field.(Double, Double) -> Double,
|
||||
): BufferND<Double> {
|
||||
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
||||
Float64Field.transform(left.buffer.array[offset], right.buffer.array[offset])
|
||||
}.toArray()
|
||||
return BufferND(strides, array.asBuffer())
|
||||
}
|
||||
|
||||
override fun StructureND<Double>.unaryMinus(): StructureND<Double> = map { -it }
|
||||
|
||||
override fun scale(a: StructureND<Double>, value: Double): StructureND<Double> = a.map { it * value }
|
||||
|
||||
override fun power(arg: StructureND<Double>, pow: Number): BufferND<Double> = arg.map { power(it, pow) }
|
||||
|
||||
override fun exp(arg: StructureND<Double>): BufferND<Double> = arg.map { exp(it) }
|
||||
|
||||
override fun ln(arg: StructureND<Double>): BufferND<Double> = arg.map { ln(it) }
|
||||
|
||||
override fun sin(arg: StructureND<Double>): BufferND<Double> = arg.map { sin(it) }
|
||||
override fun cos(arg: StructureND<Double>): BufferND<Double> = arg.map { cos(it) }
|
||||
override fun tan(arg: StructureND<Double>): BufferND<Double> = arg.map { tan(it) }
|
||||
override fun asin(arg: StructureND<Double>): BufferND<Double> = arg.map { asin(it) }
|
||||
override fun acos(arg: StructureND<Double>): BufferND<Double> = arg.map { acos(it) }
|
||||
override fun atan(arg: StructureND<Double>): BufferND<Double> = arg.map { atan(it) }
|
||||
|
||||
override fun sinh(arg: StructureND<Double>): BufferND<Double> = arg.map { sinh(it) }
|
||||
override fun cosh(arg: StructureND<Double>): BufferND<Double> = arg.map { cosh(it) }
|
||||
override fun tanh(arg: StructureND<Double>): BufferND<Double> = arg.map { tanh(it) }
|
||||
override fun asinh(arg: StructureND<Double>): BufferND<Double> = arg.map { asinh(it) }
|
||||
override fun acosh(arg: StructureND<Double>): BufferND<Double> = arg.map { acosh(it) }
|
||||
override fun atanh(arg: StructureND<Double>): BufferND<Double> = arg.map { atanh(it) }
|
||||
}
|
||||
|
||||
fun Float64Field.ndStreaming(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(ShapeND(shape))
|