diff --git a/README.md b/README.md index 95bff76..7eff6b3 100644 --- a/README.md +++ b/README.md @@ -113,9 +113,9 @@ Several other methods are in testing and will likely be added in the future rele scientific computing community. ## Usage in Nim -Usage within Nim is fairly straightforward. You can install it using Nimble as explained earlier, or install it directly from GitHub: +Usage within Nim is fairly straightforward. You can install it using Nimble as explained earlier, or install it directly from GitHub, making sure to use the slightly modified `@#nimble` branch: ```cmd -nimble install -y https://github.com/amkrajewski/nimplex +nimble install -y https://github.com/amkrajewski/nimplex@#nimble ``` or, if you wish to modify the source code, you can simply download the core file `nimplex.nim` and place it in your own code, as long as you have the dependencies installed, since it is standalone. **Then simply follow the API documentation below.** diff --git a/docs/docs.nim b/docs/docs.nim index 36dc841..3f20071 100644 --- a/docs/docs.nim +++ b/docs/docs.nim @@ -25,7 +25,7 @@ ## ```cmd ## ./nimplex -c IFP 3 10 ## ``` -## 2. An **compiled Python library**, which you can import and use in your Python code like so: +## 2. A **compiled Python library**, which you can import and use in your Python code like so: ## ```python ## import nimplex ## ``` @@ -111,9 +111,9 @@ ## Critically, unlike the O(N^2) distance-based graph generation methods, this approach **scales linearly** with the resulting number of nodes. Because of that, it is extremely efficient even in high-dimensional spaces, where the number of ## edges goes into trillions and beyond. Nimplex can **both generate and find neighbors** for around **2M points per second in 9-dimensional space** on a modern CPU. ## -## As explored in the manuscript, such representations, even of different dimensions, can can then be used to efficeintly encode complex problem spaces where some prior assumptions and knowledge are available. In the Example #2 from -## manuscript, inspired by problem of joining titanium with stainless steel in [10.1016/j.addma.2022.102649](https://doi.org/10.1016/j.addma.2022.102649) using 3-component -## spaces, one encode 3 separate paths where some components are shared in predetermined fashion. This to efficiently encode the problem space in form of a structure graph (left panel below) and then use it to construct a +## As explored in the manuscript, such representations, even of different dimensions, can then be used to efficeintly encode complex problem spaces where some prior assumptions and knowledge are available. Consider the problem of joining +## titanium with stainless steel using 3-component spaces as presented in Bobbio et. al, [10.1016/j.addma.2022.102649](https://doi.org/10.1016/j.addma.2022.102649). Example #2 from the manuscript handles this problem by encoding 3 +## separate paths where some components are shared in a predetermined fashion. This is done to efficiently encode the problem space in the form of a structure graph (left panel below) and then use it to construct a ## single **simplex graph complex** (right panel below) as a single consistent structure. ## ## .. figure:: ../assets/Fig4.png @@ -123,9 +123,9 @@ ## scientific computing community. ## ## ## Usage in Nim -## Usage within Nim is fairly straightforward. You can install it using Nimble as explained earlier, or install it directly from GitHub: +## Usage within Nim is fairly straightforward. You can install it using Nimble as explained earlier, or install it directly from GitHub, making sure to use the slightly modified `@#nimble` branch: ## ```cmd -## nimble install -y https://github.com/amkrajewski/nimplex +## nimble install -y https://github.com/amkrajewski/nimplex@#nimble ## ``` ## or, if you wish to modify the source code, you can simply download the core file `nimplex.nim` and place it in your own code, as long as you have the dependencies installed, since it is standalone. ## **Then simply follow the API documentation below.** @@ -232,4 +232,4 @@ ## ## API ## ## **The following sections cover the core API of the library.** Further documentation for auxiliary functions, defined in **utils** submodule, can be found by following links under [Imports](#6) below -## or by searching the API [Index](theindex.html) in the top left corner of this page. \ No newline at end of file +## or by searching the API [Index](theindex.html) in the top left corner of this page. diff --git a/examples/quickstart.ipynb b/examples/quickstart.ipynb index 8130e87..d6e9c4b 100644 --- a/examples/quickstart.ipynb +++ b/examples/quickstart.ipynb @@ -38,15 +38,28 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "You should be able to just type `nimplex.` in the code cell below and a list of all the functions available in the module should pop up. If it doesn't, something went wrong with the installation." + "You should be able to just type `nimplex.` in the code cell below (without running it) and a dropdown menu of all the functions available in the module should pop up. If it doesn't, something went wrong with the installation." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nimplex" + ] }, { "cell_type": "markdown", @@ -237,6 +250,92 @@ "execution_count": 9, "metadata": {}, "outputs": [ + { + "data": { + "text/html": [ + " \n", + " " + ] + }, + "metadata": {}, + "output_type": "display_data" + }, { "data": { "application/vnd.plotly.v1+json": { @@ -4358,7 +4457,34 @@ } } } - } + }, + "text/html": [ + "
" + ] }, "metadata": {}, "output_type": "display_data" @@ -4421,16 +4547,7 @@ }, { "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "randomSample1df = pd.DataFrame(randomSample1, columns=['x','y','z'])" - ] - }, - { - "cell_type": "code", - "execution_count": 12, + "execution_count": 39, "metadata": {}, "outputs": [ { @@ -4475,7 +4592,7 @@ 0.0025228495156323725, 0.1525881511756969, 0.2780249811288979, - 0.47580235154913003, + 0.47580235154913014, 0.6913902042530681, 0.550754578664194, 0.3439652252019544, @@ -5240,7 +5357,7 @@ 0.16462903792064784, 0.0962493726019104, 0.2962045018228386, - 0.7112906436774822, + 0.7112906436774823, 0.17163972784871315, 0.3941342679956087, 0.3108521761226345, @@ -5400,7 +5517,7 @@ 0.033528558667383156, 0.18800252834848846, 0.8573142706559939, - 0.09045545862933288, + 0.0904554586293329, 0.5951097269559016, 0.4515456099926712, 0.671146682709438, @@ -5909,7 +6026,7 @@ 0.4180747514452351, 0.11100037967205643, 0.027995643342296407, - 0.04550202098289665, + 0.04550202098289666, 0.38604024495119277, 0.03390799715544521, 0.582213969575949, @@ -7373,7 +7490,7 @@ 0.6505227908235313, 0.5774778834767772, 0.01675047098414673, - 0.3270752918127398, + 0.32707529181273975, 0.26325838432209925, 0.3605243795972198, 0.2487043489735734, @@ -7402,7 +7519,7 @@ 0.3419717981716487, 0.5154804147489663, 0.1088820971153055, - 0.7853097914120977, + 0.7853097914120976, 0.02325822211815125, 0.020236809277724782, 0.06450864646329107, @@ -9244,13 +9361,13 @@ 0.6045396030496006, 0.1914869485383324, 0.5128170922225661, - 0.034154048985449034, + 0.03415404898544904, 0.4859969049172953, 0.421503586421947, 0.02191442948324876, 0.5840429907092325, 0.3415776085125369, - 0.06137043597223778, + 0.061370435972237784, 0.37543907715452823, 0.6201036562604129, 0.15279273858255846, @@ -9375,7 +9492,7 @@ 0.17934552998706685, 0.0860242703148829, 0.6290105972364031, - 0.4167384646900267, + 0.4167384646900266, 0.17934315772029746, 0.1792314349228854, 0.09800497463122043, @@ -9404,7 +9521,7 @@ 0.6244996431609681, 0.2965170569025453, 0.033803632228700725, - 0.12423474995856952, + 0.12423474995856953, 0.38163205092594715, 0.528217580729604, 0.264344670827271, @@ -9488,7 +9605,7 @@ 0.24035987345706283, 0.5494532812027616, 0.20486754681888228, - 0.17299466566415694, + 0.17299466566415697, 0.7290471804484556, 0.5965043388133101, 0.3979974439595838, @@ -9583,7 +9700,7 @@ 0.2556441821119743, 0.5873961720886606, 0.4717669564905644, - 0.02995549109282992, + 0.029955491092829918, 0.6953909919608415, 0.1015691550079152, 0.12469828918407005, @@ -9930,7 +10047,7 @@ 0.14959316859146174, 0.2869898153619005, 0.5208268055449263, - 0.05134641826005289, + 0.05134641826005288, 0.745464717197281, 0.4881912381445811, 0.33783850390775816, @@ -9947,7 +10064,7 @@ 0.0357724223452817, 0.3642059868709841, 0.06808181175797239, - 0.42154079327317, + 0.42154079327316996, 0.2985486515875435, 0.47189144340578537, 0.9376451269172201, @@ -11312,13 +11429,41 @@ } } } - } + }, + "text/html": [ + "
" + ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ + "randomSample1df = pd.DataFrame(randomSample1, columns=['x','y','z'])\n", "px.scatter_ternary(randomSample1df, a='x', b='y', c='z', opacity=0.33)" ] }, @@ -14414,7 +14559,34 @@ } } } - } + }, + "text/html": [ + "
" + ] }, "metadata": {}, "output_type": "display_data" @@ -14429,7 +14601,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "and then do the same for 4-component space:" + "and then do the same for 4-component simplex space in 3D cartesian space:" ] }, { @@ -14819,7 +14991,7 @@ -8.4887374907083305e-19, -0.06804138333333333, 0.06804138333333333, - 0 + -8.4887374907083305e-19 ], "z": [ 0.66666665, @@ -15843,7 +16015,34 @@ }, "width": 800 } - } + }, + "text/html": [ + "
" + ] }, "metadata": {}, "output_type": "display_data" @@ -16588,7 +16787,7 @@ 0.2990329619768337, -0.014386767871830717, -0.21001265990065318, - 0.134662509795341, + 0.13466250979534097, 0.2546249773059034, -0.33857055066179226, -0.09815157159185088, @@ -16810,7 +17009,7 @@ 0.14842049165661653, -0.2379960590655549, 0.05559425206748163, - -0.006937877114394221, + -0.006937877114394208, -0.18153800365547296, -0.03760503813734328, -0.02009172065882321, @@ -17590,7 +17789,7 @@ 0.15255300462185906, -0.09255688245144988, -0.07412112047490557, - 0.11966533075945507, + 0.11966533075945508, 0.27405414793197375, -0.576265675756067, -0.27900730511860056, @@ -17812,7 +18011,7 @@ 0.1346334252482446, -0.3479639580506892, -0.291281563111836, - 0.0934192567723158, + 0.09341925677231577, 0.10067391990408621, -0.27123189923857033, -0.13632066809088414, @@ -18583,7 +18782,7 @@ -0.1987751629401983, -0.11093553675591808, -0.22984522561478238, - -0.08531445702638749, + -0.08531445702638751, 0.0340773956932775, -0.09431922028035197, 0.18137594193022127, @@ -18592,7 +18791,7 @@ 0.16693113067505375, 0.7463323275602216, 0.23970523425389084, - 0.2372090579746144, + 0.23720905797461436, -0.15812757045231354, -0.24319055290889297, 0.2142493791219501, @@ -19778,7 +19977,34 @@ }, "width": 800 } - } + }, + "text/html": [ + "
" + ] }, "metadata": {}, "output_type": "display_data" @@ -20342,7 +20568,7 @@ -8.4887374907083305e-19, -0.06804138333333333, 0.06804138333333333, - 0 + -8.4887374907083305e-19 ], "z": [ 0.66666665, @@ -21415,7 +21641,34 @@ }, "width": 800 } - } + }, + "text/html": [ + "
" + ] }, "metadata": {}, "output_type": "display_data" @@ -21961,7 +22214,7 @@ 0.28452173334333203, 0.2931431727296572, 0.30114126828162896, - 0.321810013001975, + 0.3218100130019749, 0.33036775713315825, 0.3567015498345046, 0.1741527817045851, @@ -24304,7 +24557,34 @@ }, "width": 800 } - } + }, + "text/html": [ + "
" + ] }, "metadata": {}, "output_type": "display_data" @@ -24767,7 +25047,7 @@ 0.28452173334333203, 0.2931431727296572, 0.30114126828162896, - 0.321810013001975, + 0.3218100130019749, 0.33036775713315825, 0.3567015498345046, 0.1741527817045851, @@ -27567,7 +27847,34 @@ }, "width": 800 } - } + }, + "text/html": [ + "
" + ] }, "metadata": {}, "output_type": "display_data" @@ -27681,7 +27988,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In some cases, you may not have ability to read the NumPy format, beacuse for instance, you are writing code for your favorite satelite or train using a niche language like [Ada](https://ada-lang.io). For situations like that, the backup option of formatter text output is available. It is not nearly as efficient as the binary NumPy format, so the grid from the last example would take minutes to generate, but it should work with *everything*. \n", + "In some cases, you may not have the ability to read the NumPy format, because for instance, you are writing code for your favorite satellite or train using a niche language like [Ada](https://ada-lang.io). For situations like that, the backup option of formatter text output is available. It is not nearly as efficient as the binary NumPy format, so the grid from the last example would take minutes to generate, but it should work with *everything*. \n", "\n", "Let's start by looking at a toy example. To get a small grid of `3`-component `F`ull simplex grid with `F`ractional with `5` divisions per dimension, we can do:" ] @@ -27752,7 +28059,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - ",which you can quickly read in Ada using rather elaborate code to parse the file in strongly typed manner with some extra error checking. For the sake of conciseness, it is not shown here, but the below example shows how to do it in pure Python (just the built-in functions):" + ",which you can quickly read in Ada using rather elaborate code to parse the file in strongly typed manner with some extra error checking. For the sake of conciseness, it is not shown here, but the example below shows how to do it in pure Python (using just built-in functions):" ] }, { @@ -27815,7 +28122,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.11.7" } }, "nbformat": 4, diff --git a/nimplex.nim b/nimplex.nim index 49ed2c4..0736f85 100644 --- a/nimplex.nim +++ b/nimplex.nim @@ -11,6 +11,7 @@ import std/sugar import std/times import std/strutils from std/algorithm import reverse +from std/sequtils import foldl, mapIt # Arraymancer library for tensor operations import arraymancer/Tensor @@ -402,12 +403,12 @@ proc outFunction(config: string, npyName: string, outputData: Tensor) = ## and the destiantion filename `npyName`, which should include the extension. case config[2]: of 'P': - echo "Full Output:", outputData + echo "Full Output: ", outputData of 'N': outputData.write_npy(npyName) - echo "Shape:", outputData.shape + echo "Shape: ", outputData.shape of 'S': - echo "Shape:", outputData.shape + echo "Shape: ", outputData.shape else: echo "Invalid Config" @@ -434,11 +435,11 @@ proc outFunction_graph(config: string, dim: int, ndiv: int, npyName: string, out else: neighborsTensor[i, j] = -1 neighborsTensor.write_npy(npyName.replace(".npy", "_neighbors.npy")) - echo "Nodes Shape:", outputData[0].shape - echo "Neighbors Lenght:", outputData[1].len + echo "Nodes Shape: ", outputData[0].shape + echo "Edges Count: ", outputData[1].mapIt(it.len).foldl(a + b, 0) of 'S': - echo "Nodes Shape:", outputData[0].shape - echo "Neighbors Lenght:", outputData[1].len + echo "Nodes Shape: ", outputData[0].shape + echo "Edges Count: ", outputData[1].mapIt(it.len).foldl(a + b, 0) else: echo "Invalid Congig" @@ -495,14 +496,14 @@ when appType != "lib": let tempIn = readLine(stdin) if tempIn.len > 0: npyName = tempIn - echo "Persisting to NumPy array file:", npyName + echo "Persisting to NumPy array file: ", npyName taskRouter(config, dim, ndiv, npyName) # Configured elif args[0] == "-c" or args[0] == "--config": let config = args[1] - echo "Running with configuration:", args[1..