pycauset 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. pycauset-0.1.0/.gitignore +78 -0
  2. pycauset-0.1.0/.vscode/settings.json +9 -0
  3. pycauset-0.1.0/CMakeLists.txt +77 -0
  4. pycauset-0.1.0/PKG-INFO +124 -0
  5. pycauset-0.1.0/README.md +105 -0
  6. pycauset-0.1.0/SETUP_INSTRUCTIONS.md +32 -0
  7. pycauset-0.1.0/build.ps1 +157 -0
  8. pycauset-0.1.0/build_python.ps1 +31 -0
  9. pycauset-0.1.0/docs/PYTHON.md +205 -0
  10. pycauset-0.1.0/documentation/.obsidian/app.json +4 -0
  11. pycauset-0.1.0/documentation/.obsidian/appearance.json +1 -0
  12. pycauset-0.1.0/documentation/.obsidian/core-plugins.json +33 -0
  13. pycauset-0.1.0/documentation/.obsidian/graph.json +22 -0
  14. pycauset-0.1.0/documentation/.obsidian/workspace.json +271 -0
  15. pycauset-0.1.0/documentation/PYTHON.md +183 -0
  16. pycauset-0.1.0/documentation/Welcome.md +12 -0
  17. pycauset-0.1.0/documentation/api/parameters/pycauset.keep_temp_files.md +0 -0
  18. pycauset-0.1.0/documentation/api/parameters/pycauset.seed.md +12 -0
  19. pycauset-0.1.0/documentation/api/pycauset.CausalMatrix.md +16 -0
  20. pycauset-0.1.0/documentation/api/pycauset.FloatMatrix.md +33 -0
  21. pycauset-0.1.0/documentation/api/pycauset.IntegerMatrix.md +29 -0
  22. pycauset-0.1.0/documentation/api/pycauset.Matrix.md +18 -0
  23. pycauset-0.1.0/documentation/api/pycauset.MatrixBase.md +25 -0
  24. pycauset-0.1.0/documentation/api/pycauset.TriangularBitMatrix.md +41 -0
  25. pycauset-0.1.0/documentation/api/pycauset.TriangularFloatMatrix.md +40 -0
  26. pycauset-0.1.0/documentation/api/pycauset.TriangularMatrix.md +23 -0
  27. pycauset-0.1.0/documentation/api/pycauset.bitwise_not.md +19 -0
  28. pycauset-0.1.0/documentation/api/pycauset.compute_k.md +18 -0
  29. pycauset-0.1.0/documentation/api/pycauset.invert.md +60 -0
  30. pycauset-0.1.0/documentation/api/pycauset.load.md +41 -0
  31. pycauset-0.1.0/documentation/api/pycauset.matmul.md +19 -0
  32. pycauset-0.1.0/documentation/api/pycauset.save.md +21 -0
  33. pycauset-0.1.0/documentation/guides/BitwiseInversion.md +43 -0
  34. pycauset-0.1.0/documentation/guides/Installation.md +31 -0
  35. pycauset-0.1.0/documentation/guides/Inversion.md +69 -0
  36. pycauset-0.1.0/documentation/guides/Matrix Guide.md +112 -0
  37. pycauset-0.1.0/documentation/guides/Matrix Multiplication.md +75 -0
  38. pycauset-0.1.0/documentation/guides/User Guide.md +238 -0
  39. pycauset-0.1.0/documentation/internals/File Format.md +79 -0
  40. pycauset-0.1.0/documentation/internals/Implementation Plan.md +84 -0
  41. pycauset-0.1.0/documentation/internals/Math Derivation.md +64 -0
  42. pycauset-0.1.0/documentation/internals/Matrix Hierarchy.md +55 -0
  43. pycauset-0.1.0/documentation/project/TODO.md +28 -0
  44. pycauset-0.1.0/include/DenseMatrix.hpp +191 -0
  45. pycauset-0.1.0/include/FileFormat.hpp +36 -0
  46. pycauset-0.1.0/include/MatrixBase.hpp +52 -0
  47. pycauset-0.1.0/include/MatrixOperations.hpp +21 -0
  48. pycauset-0.1.0/include/MatrixTraits.hpp +26 -0
  49. pycauset-0.1.0/include/MemoryMapper.hpp +39 -0
  50. pycauset-0.1.0/include/StoragePaths.hpp +25 -0
  51. pycauset-0.1.0/include/TriangularBitMatrix.hpp +66 -0
  52. pycauset-0.1.0/include/TriangularMatrix.hpp +183 -0
  53. pycauset-0.1.0/pycauset/__init__.py +22 -0
  54. pycauset-0.1.0/pycauset/__init__.pyi +87 -0
  55. pycauset-0.1.0/pyproject.toml +32 -0
  56. pycauset-0.1.0/python/pycauset/__init__.py +742 -0
  57. pycauset-0.1.0/python/pycauset/_storage.py +83 -0
  58. pycauset-0.1.0/run_tests.ps1 +2 -0
  59. pycauset-0.1.0/sitecustomize.py +10 -0
  60. pycauset-0.1.0/src/MatrixBase.cpp +132 -0
  61. pycauset-0.1.0/src/MatrixOperations.cpp +191 -0
  62. pycauset-0.1.0/src/MemoryMapper.cpp +172 -0
  63. pycauset-0.1.0/src/TriangularBitMatrix.cpp +288 -0
  64. pycauset-0.1.0/src/TriangularMatrix.cpp +33 -0
  65. pycauset-0.1.0/src/bindings.cpp +397 -0
  66. pycauset-0.1.0/src/main.cpp +6 -0
  67. pycauset-0.1.0/test.py +11 -0
  68. pycauset-0.1.0/test_interface.py +65 -0
  69. pycauset-0.1.0/tests/python/__init__.py +0 -0
  70. pycauset-0.1.0/tests/python/benchmark_k.py +41 -0
  71. pycauset-0.1.0/tests/python/test_behaviour.py +191 -0
  72. pycauset-0.1.0/tests/python/test_interface.py +65 -0
  73. pycauset-0.1.0/tests/python/test_k_matrix.py +77 -0
  74. pycauset-0.1.0/tests/python/test_matrix_hierarchy.py +46 -0
  75. pycauset-0.1.0/tests/python/test_operations.py +149 -0
  76. pycauset-0.1.0/tests/test_main.cpp +267 -0
@@ -0,0 +1,78 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ share/python-wheels/
20
+ *.egg-info/
21
+ .installed.cfg
22
+ *.egg
23
+ MANIFEST
24
+
25
+ # Virtual Environments
26
+ .env
27
+ .venv
28
+ env/
29
+ venv/
30
+ ENV/
31
+ env.bak/
32
+ venv.bak/
33
+
34
+ # C++ / CMake
35
+ CMakeCache.txt
36
+ CMakeFiles/
37
+ cmake_install.cmake
38
+ Makefile
39
+ *.vcxproj
40
+ *.vcxproj.filters
41
+ *.sln
42
+ *.slnx
43
+ *.dir/
44
+ *.lib
45
+ *.exp
46
+ *.dll
47
+ *.exe
48
+ *.pdb
49
+ *.ilk
50
+ *.obj
51
+ compile_commands.json
52
+ CTestTestfile.cmake
53
+ _deps/
54
+ x64/
55
+ Debug/
56
+ Release/
57
+ RelWithDebInfo/
58
+ MinSizeRel/
59
+
60
+ # VS Code
61
+ .vscode/
62
+ !.vscode/settings.json
63
+ !.vscode/tasks.json
64
+ !.vscode/launch.json
65
+ !.vscode/extensions.json
66
+ *.code-workspace
67
+
68
+ # PyCauset Specific
69
+ .pycauset/
70
+ *.pycauset
71
+ *.pyd
72
+ *.bin
73
+ test_*.bin
74
+ *_test.bin
75
+
76
+ # Documentation
77
+ .obsidian/workspace
78
+ .obsidian/cache
@@ -0,0 +1,9 @@
1
+ {
2
+ "files.associations": {
3
+ "*.tikz": "latex",
4
+ "bit": "cpp",
5
+ "filesystem": "cpp",
6
+ "random": "cpp",
7
+ "memory": "cpp"
8
+ }
9
+ }
@@ -0,0 +1,77 @@
1
+ cmake_minimum_required(VERSION 3.15)
2
+ project(pycauset VERSION 0.1.0 LANGUAGES CXX)
3
+
4
+ set(CMAKE_CXX_STANDARD 20)
5
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
6
+
7
+ # --- Dependencies ---
8
+
9
+ # 1. Python (Required for the extension)
10
+ find_package(Python COMPONENTS Interpreter Development.Module REQUIRED)
11
+
12
+ # 2. Pybind11 (Required)
13
+ # If built via pip/scikit-build-core, pybind11 is provided.
14
+ # If built manually, we might need to fetch it.
15
+ find_package(pybind11 CONFIG)
16
+ if(NOT pybind11_FOUND)
17
+ include(FetchContent)
18
+ FetchContent_Declare(
19
+ pybind11
20
+ URL https://github.com/pybind/pybind11/archive/refs/tags/v2.12.0.zip
21
+ )
22
+ FetchContent_MakeAvailable(pybind11)
23
+ endif()
24
+
25
+ # 3. OpenMP (Optional but recommended)
26
+ find_package(OpenMP)
27
+
28
+ # --- Source Files ---
29
+ set(PYCAUSET_SOURCES
30
+ src/bindings.cpp
31
+ src/MemoryMapper.cpp
32
+ src/MatrixBase.cpp
33
+ src/TriangularMatrix.cpp
34
+ src/TriangularBitMatrix.cpp
35
+ src/MatrixOperations.cpp
36
+ )
37
+
38
+ # --- Extension Module ---
39
+ # Note: The module name must match what is defined in PYBIND11_MODULE in bindings.cpp (which is "pycauset")
40
+ python_add_library(pycauset MODULE ${PYCAUSET_SOURCES})
41
+
42
+ # Include directories
43
+ target_include_directories(pycauset PRIVATE include)
44
+
45
+ # Link libraries
46
+ target_link_libraries(pycauset PRIVATE pybind11::module)
47
+
48
+ if(OpenMP_CXX_FOUND)
49
+ target_link_libraries(pycauset PRIVATE OpenMP::OpenMP_CXX)
50
+ endif()
51
+
52
+ # --- Installation ---
53
+ # This installs the compiled extension into the python package directory
54
+ install(TARGETS pycauset DESTINATION python/pycauset)
55
+
56
+ # --- Testing (Only if explicitly requested or not a pip build) ---
57
+ option(BUILD_TESTS "Build tests" OFF)
58
+ if(BUILD_TESTS)
59
+ enable_testing()
60
+ include(FetchContent)
61
+ FetchContent_Declare(
62
+ googletest
63
+ URL https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip
64
+ )
65
+ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
66
+ FetchContent_MakeAvailable(googletest)
67
+
68
+ add_executable(causal_tests tests/test_main.cpp ${PYCAUSET_SOURCES})
69
+ # Remove bindings.cpp from tests if it contains the main module definition which might conflict
70
+ # Actually bindings.cpp has PYBIND11_MODULE, which is fine in a library but maybe not in an executable if it has main?
71
+ # test_main.cpp has main(). bindings.cpp does not have main().
72
+
73
+ target_include_directories(causal_tests PRIVATE include)
74
+ target_link_libraries(causal_tests PRIVATE GTest::gtest_main OpenMP::OpenMP_CXX)
75
+
76
+ add_test(NAME CausalTests COMMAND causal_tests)
77
+ endif()
@@ -0,0 +1,124 @@
1
+ Metadata-Version: 2.2
2
+ Name: pycauset
3
+ Version: 0.1.0
4
+ Summary: High-performance Causal Set matrix operations using memory-mapped files
5
+ Author-Email: BrorH <your.email@example.com>
6
+ License: MIT
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Science/Research
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: C++
12
+ Classifier: Operating System :: Microsoft :: Windows
13
+ Classifier: Operating System :: POSIX :: Linux
14
+ Classifier: Operating System :: MacOS
15
+ Project-URL: Homepage, https://github.com/BrorH/pycauset
16
+ Project-URL: Repository, https://github.com/BrorH/pycauset
17
+ Requires-Python: >=3.8
18
+ Description-Content-Type: text/markdown
19
+
20
+ # PyCauset
21
+
22
+ **PyCauset** is a high-performance Python module designed for numerical work with [Causal Sets](https://en.wikipedia.org/wiki/Causal_sets). It is built to handle massive matrices (up to $N=10^6$) that exceed available RAM by leveraging memory-mapped files and efficient C++ backends.
23
+
24
+ ## Why PyCauset?
25
+
26
+ For a causal set of size $N$, the relevant mathematical objects are typically of order $\mathcal O(N^2)$ and operations are $\mathcal O(N^3)$. For even moderate sizes like $N=10,000$, standard in-memory libraries like NumPy can struggle with memory limits.
27
+
28
+ **PyCauset solves this by:**
29
+ * **Memory Mapping**: Storing matrices on disk and loading only necessary chunks into RAM.
30
+ * **Bit Packing**: Storing boolean matrices (causal relations) as individual bits, reducing storage requirements by 8x-64x compared to standard types.
31
+ * **C++ Efficiency**: Core operations are implemented in optimized C++.
32
+
33
+ ## Installation
34
+
35
+ ### Prerequisites
36
+ PyCauset requires a C++ compiler to build the native extension.
37
+ * **Windows**: Install **Visual Studio Build Tools** with the "Desktop development with C++" workload.
38
+ * **Linux/macOS**: Install `gcc` or `clang`.
39
+
40
+ ### Build & Install
41
+ Clone the repository and run the build script:
42
+
43
+ ```powershell
44
+ # Build the C++ extension and Python module
45
+ ./build.ps1 -Python
46
+
47
+ # To run tests as well
48
+ ./build.ps1 -All
49
+ ```
50
+
51
+ ## Quick Start
52
+
53
+ ### 1. Creating Matrices
54
+ The primary structure for causal sets is the `TriangularBitMatrix` (aliased as `CausalMatrix`).
55
+
56
+ ```python
57
+ import pycauset
58
+
59
+ # Create a random 1000x1000 causal matrix (Bernoulli p=0.5)
60
+ C = pycauset.CausalMatrix.random(1000, density=0.5)
61
+
62
+ # Create an empty matrix (initialized to zeros)
63
+ C_empty = pycauset.CausalMatrix(1000)
64
+
65
+ # Create from a NumPy array
66
+ import numpy as np
67
+ arr = np.triu(np.random.randint(0, 2, (10, 10)), k=1).astype(bool)
68
+ C_from_np = pycauset.CausalMatrix(arr)
69
+ ```
70
+
71
+ ### 2. Matrix Operations
72
+ PyCauset supports standard arithmetic and specialized causal set operations.
73
+
74
+ ```python
75
+ # Matrix Multiplication (Counting paths of length 2)
76
+ # Returns an IntegerMatrix
77
+ M = pycauset.matmul(C, C)
78
+
79
+ # Elementwise Multiplication
80
+ E = C * C
81
+
82
+ # Bitwise Inversion (NOT)
83
+ C_inv = ~C
84
+
85
+ # Linear Algebra Inversion (for dense float matrices)
86
+ # Returns a FloatMatrix
87
+ F = pycauset.FloatMatrix(100)
88
+ F_inv = pycauset.invert(F)
89
+ ```
90
+
91
+ ### 3. Computing the K-Matrix
92
+ A common operation in causal set theory is computing $K = C(aI + C)^{-1}$.
93
+
94
+ ```python
95
+ # Compute K with scalar a=1.0
96
+ # Returns a TriangularFloatMatrix
97
+ K = pycauset.compute_k(C, a=1.0)
98
+ ```
99
+
100
+ ## Matrix Types
101
+
102
+ PyCauset uses a template-based architecture to support efficient storage for different data types:
103
+
104
+ | Class | Description | Storage |
105
+ |-------|-------------|---------|
106
+ | `TriangularBitMatrix` | Strictly upper-triangular boolean matrix. | 1 bit / element |
107
+ | `IntegerMatrix` | Dense matrix of 32-bit integers. | 4 bytes / element |
108
+ | `FloatMatrix` | Dense matrix of 64-bit floats. | 8 bytes / element |
109
+ | `TriangularFloatMatrix` | Strictly upper-triangular float matrix. | 8 bytes / element |
110
+
111
+ ## Storage Management
112
+
113
+ PyCauset manages disk storage automatically to keep your workspace clean.
114
+
115
+ * **Temporary Files**: All matrices are created as temporary files in a `.pycauset/` directory. These files are **automatically deleted** when your Python script exits (even if it crashes or is interrupted).
116
+ * **Permanent Storage**: To keep a matrix, you **must** use the `save()` function.
117
+
118
+ ```python
119
+ # This matrix is temporary and will be deleted at exit
120
+ temp = pycauset.CausalMatrix(500)
121
+
122
+ # Save it permanently to a specific path
123
+ pycauset.save(temp, "my_causet.pycauset")
124
+ ```
@@ -0,0 +1,105 @@
1
+ # PyCauset
2
+
3
+ **PyCauset** is a high-performance Python module designed for numerical work with [Causal Sets](https://en.wikipedia.org/wiki/Causal_sets). It is built to handle massive matrices (up to $N=10^6$) that exceed available RAM by leveraging memory-mapped files and efficient C++ backends.
4
+
5
+ ## Why PyCauset?
6
+
7
+ For a causal set of size $N$, the relevant mathematical objects are typically of order $\mathcal O(N^2)$ and operations are $\mathcal O(N^3)$. For even moderate sizes like $N=10,000$, standard in-memory libraries like NumPy can struggle with memory limits.
8
+
9
+ **PyCauset solves this by:**
10
+ * **Memory Mapping**: Storing matrices on disk and loading only necessary chunks into RAM.
11
+ * **Bit Packing**: Storing boolean matrices (causal relations) as individual bits, reducing storage requirements by 8x-64x compared to standard types.
12
+ * **C++ Efficiency**: Core operations are implemented in optimized C++.
13
+
14
+ ## Installation
15
+
16
+ ### Prerequisites
17
+ PyCauset requires a C++ compiler to build the native extension.
18
+ * **Windows**: Install **Visual Studio Build Tools** with the "Desktop development with C++" workload.
19
+ * **Linux/macOS**: Install `gcc` or `clang`.
20
+
21
+ ### Build & Install
22
+ Clone the repository and run the build script:
23
+
24
+ ```powershell
25
+ # Build the C++ extension and Python module
26
+ ./build.ps1 -Python
27
+
28
+ # To run tests as well
29
+ ./build.ps1 -All
30
+ ```
31
+
32
+ ## Quick Start
33
+
34
+ ### 1. Creating Matrices
35
+ The primary structure for causal sets is the `TriangularBitMatrix` (aliased as `CausalMatrix`).
36
+
37
+ ```python
38
+ import pycauset
39
+
40
+ # Create a random 1000x1000 causal matrix (Bernoulli p=0.5)
41
+ C = pycauset.CausalMatrix.random(1000, density=0.5)
42
+
43
+ # Create an empty matrix (initialized to zeros)
44
+ C_empty = pycauset.CausalMatrix(1000)
45
+
46
+ # Create from a NumPy array
47
+ import numpy as np
48
+ arr = np.triu(np.random.randint(0, 2, (10, 10)), k=1).astype(bool)
49
+ C_from_np = pycauset.CausalMatrix(arr)
50
+ ```
51
+
52
+ ### 2. Matrix Operations
53
+ PyCauset supports standard arithmetic and specialized causal set operations.
54
+
55
+ ```python
56
+ # Matrix Multiplication (Counting paths of length 2)
57
+ # Returns an IntegerMatrix
58
+ M = pycauset.matmul(C, C)
59
+
60
+ # Elementwise Multiplication
61
+ E = C * C
62
+
63
+ # Bitwise Inversion (NOT)
64
+ C_inv = ~C
65
+
66
+ # Linear Algebra Inversion (for dense float matrices)
67
+ # Returns a FloatMatrix
68
+ F = pycauset.FloatMatrix(100)
69
+ F_inv = pycauset.invert(F)
70
+ ```
71
+
72
+ ### 3. Computing the K-Matrix
73
+ A common operation in causal set theory is computing $K = C(aI + C)^{-1}$.
74
+
75
+ ```python
76
+ # Compute K with scalar a=1.0
77
+ # Returns a TriangularFloatMatrix
78
+ K = pycauset.compute_k(C, a=1.0)
79
+ ```
80
+
81
+ ## Matrix Types
82
+
83
+ PyCauset uses a template-based architecture to support efficient storage for different data types:
84
+
85
+ | Class | Description | Storage |
86
+ |-------|-------------|---------|
87
+ | `TriangularBitMatrix` | Strictly upper-triangular boolean matrix. | 1 bit / element |
88
+ | `IntegerMatrix` | Dense matrix of 32-bit integers. | 4 bytes / element |
89
+ | `FloatMatrix` | Dense matrix of 64-bit floats. | 8 bytes / element |
90
+ | `TriangularFloatMatrix` | Strictly upper-triangular float matrix. | 8 bytes / element |
91
+
92
+ ## Storage Management
93
+
94
+ PyCauset manages disk storage automatically to keep your workspace clean.
95
+
96
+ * **Temporary Files**: All matrices are created as temporary files in a `.pycauset/` directory. These files are **automatically deleted** when your Python script exits (even if it crashes or is interrupted).
97
+ * **Permanent Storage**: To keep a matrix, you **must** use the `save()` function.
98
+
99
+ ```python
100
+ # This matrix is temporary and will be deleted at exit
101
+ temp = pycauset.CausalMatrix(500)
102
+
103
+ # Save it permanently to a specific path
104
+ pycauset.save(temp, "my_causet.pycauset")
105
+ ```
@@ -0,0 +1,32 @@
1
+ # Setup Instructions
2
+
3
+ ## 1. Install a C++ Compiler
4
+ Your system is missing a C++ compiler. Since you are on Windows, the recommended way is to install **Visual Studio Build Tools**.
5
+
6
+ 1. Download **Visual Studio Community 2022** (Free) from: [https://visualstudio.microsoft.com/vs/community/](https://visualstudio.microsoft.com/vs/community/)
7
+ 2. Run the installer.
8
+ 3. **Crucial Step**: In the "Workloads" tab, check the box for **"Desktop development with C++"**.
9
+ * This ensures the MSVC compiler (`cl.exe`) and Windows SDK are installed.
10
+ 4. Click **Install**.
11
+
12
+ ## 2. Verify Installation
13
+ After installation completes:
14
+ 1. **Restart Visual Studio Code** (completely close and reopen it) to refresh environment variables.
15
+ 2. Open a terminal and try running:
16
+ ```powershell
17
+ cl
18
+ ```
19
+ *Note: `cl` might not be in your global PATH, which is fine. CMake usually finds it automatically.*
20
+
21
+ ## 3. Build & Test
22
+ Use the consolidated build script:
23
+ ```powershell
24
+ # Build everything and run C++ tests + Python module
25
+ .\build.ps1 -All
26
+
27
+ # Only run C++ tests
28
+ .\build.ps1 -Tests
29
+
30
+ # Only build the Python module
31
+ .\build.ps1 -Python
32
+ ```
@@ -0,0 +1,157 @@
1
+ param(
2
+ [switch]$Tests,
3
+ [switch]$Python,
4
+ [switch]$All,
5
+ [string]$PythonVersion,
6
+ [string]$PythonExe
7
+ )
8
+
9
+ if (-not ($Tests -or $Python -or $All)) {
10
+ $All = $true
11
+ }
12
+
13
+ if ($All) {
14
+ $Tests = $true
15
+ $Python = $true
16
+ }
17
+
18
+ $resolvedPythonExe = $null
19
+ if ($PythonExe) {
20
+ if (Test-Path $PythonExe) {
21
+ $resolvedPythonExe = (Resolve-Path $PythonExe).Path
22
+ } else {
23
+ Write-Host "Provided PythonExe path '$PythonExe' was not found." -ForegroundColor Red
24
+ exit 1
25
+ }
26
+ } elseif ($PythonVersion) {
27
+ Write-Host "Resolving Python $PythonVersion using py launcher..." -ForegroundColor Cyan
28
+ try {
29
+ $pyArgs = @("-$PythonVersion", "-c", "import sys; print(sys.executable)")
30
+ $resolvedPythonExe = (& py @pyArgs).Trim()
31
+ if (-not $resolvedPythonExe) {
32
+ throw "py launcher did not return a path."
33
+ }
34
+ } catch {
35
+ Write-Host "Unable to resolve Python version $PythonVersion via py launcher: $_" -ForegroundColor Red
36
+ exit 1
37
+ }
38
+
39
+ if (-not (Test-Path $resolvedPythonExe)) {
40
+ Write-Host "Resolved Python path '$resolvedPythonExe' does not exist." -ForegroundColor Red
41
+ exit 1
42
+ }
43
+ }
44
+
45
+ if ($resolvedPythonExe) {
46
+ Write-Host "Using Python executable: $resolvedPythonExe" -ForegroundColor Yellow
47
+ }
48
+
49
+ Write-Host "Checking for CMake..."
50
+ if (-not (Get-Command cmake -ErrorAction SilentlyContinue)) {
51
+ $commonPaths = @(
52
+ "C:\Program Files\CMake\bin",
53
+ "C:\Program Files (x86)\CMake\bin"
54
+ )
55
+ foreach ($path in $commonPaths) {
56
+ if (Test-Path "$path\cmake.exe") {
57
+ Write-Host "Found CMake at $path. Adding to session PATH." -ForegroundColor Yellow
58
+ $env:Path = "$path;$env:Path"
59
+ break
60
+ }
61
+ }
62
+ }
63
+
64
+ if (-not (Get-Command cmake -ErrorAction SilentlyContinue)) {
65
+ Write-Host "Error: CMake is not in your PATH." -ForegroundColor Red
66
+ exit 1
67
+ }
68
+
69
+ $buildDir = "build"
70
+ if (-not (Test-Path $buildDir)) {
71
+ Write-Host "Creating build directory..."
72
+ New-Item -ItemType Directory -Path $buildDir | Out-Null
73
+ }
74
+
75
+ Push-Location $buildDir
76
+
77
+ $cmakeConfigureArgs = @("..")
78
+ if ($resolvedPythonExe) {
79
+ $normalizedExe = $resolvedPythonExe -replace "\\", "/"
80
+ $cmakeConfigureArgs = @("-DPython3_EXECUTABLE:FILEPATH=$normalizedExe", "-DPython_EXECUTABLE:FILEPATH=$normalizedExe") + $cmakeConfigureArgs
81
+ }
82
+
83
+ Write-Host "Configuring project..." -ForegroundColor Cyan
84
+ cmake @cmakeConfigureArgs
85
+ if ($LASTEXITCODE -ne 0) {
86
+ Write-Host "Configuration failed." -ForegroundColor Red
87
+ Pop-Location
88
+ exit 1
89
+ }
90
+
91
+ if ($Tests) {
92
+ Write-Host "Building tests..." -ForegroundColor Cyan
93
+ cmake --build . --config Release --target causal_tests
94
+ if ($LASTEXITCODE -ne 0) {
95
+ Write-Host "Test build failed." -ForegroundColor Red
96
+ Pop-Location
97
+ exit 1
98
+ }
99
+
100
+ Write-Host "Running tests..." -ForegroundColor Cyan
101
+ $possiblePaths = @(
102
+ ".\Release\causal_tests.exe",
103
+ ".\tests\Release\causal_tests.exe",
104
+ ".\causal_tests.exe",
105
+ ".\tests\causal_tests.exe"
106
+ )
107
+
108
+ $testExe = $null
109
+ foreach ($path in $possiblePaths) {
110
+ if (Test-Path $path) {
111
+ $testExe = $path
112
+ break
113
+ }
114
+ }
115
+
116
+ if ($testExe) {
117
+ Write-Host "Found executable at: $testExe" -ForegroundColor Gray
118
+ & $testExe
119
+ if ($LASTEXITCODE -ne 0) {
120
+ Write-Host "Tests failed." -ForegroundColor Red
121
+ Pop-Location
122
+ exit 1
123
+ }
124
+ } else {
125
+ Write-Host "Could not find test executable." -ForegroundColor Red
126
+ Pop-Location
127
+ exit 1
128
+ }
129
+ }
130
+
131
+ if ($Python) {
132
+ Write-Host "Building pycauset module..." -ForegroundColor Cyan
133
+ cmake --build . --config Release --target pycauset
134
+ if ($LASTEXITCODE -ne 0) {
135
+ Write-Host "Python module build failed." -ForegroundColor Red
136
+ Pop-Location
137
+ exit 1
138
+ }
139
+
140
+ $pydFile = Get-ChildItem -Recurse -Filter "pycauset*.pyd" | Select-Object -First 1
141
+ if ($pydFile) {
142
+ $packageDir = Join-Path .. "python/pycauset"
143
+ if (-not (Test-Path $packageDir)) {
144
+ New-Item -ItemType Directory -Path $packageDir | Out-Null
145
+ }
146
+ Copy-Item $pydFile.FullName -Destination $packageDir -Force
147
+ Copy-Item $pydFile.FullName -Destination ..\ -Force
148
+ Write-Host "Copied module to python/pycauset and project root" -ForegroundColor Green
149
+ } else {
150
+ Write-Host "Could not locate generated pycauset module." -ForegroundColor Red
151
+ Pop-Location
152
+ exit 1
153
+ }
154
+ }
155
+
156
+ Pop-Location
157
+ Write-Host "Build complete." -ForegroundColor Green
@@ -0,0 +1,31 @@
1
+ # Build Python Module
2
+ Write-Host "Building Python Module..." -ForegroundColor Cyan
3
+
4
+ # Create build directory
5
+ if (-not (Test-Path "build")) { New-Item -ItemType Directory -Path "build" | Out-Null }
6
+ Push-Location build
7
+
8
+ # Configure & Build
9
+ cmake ..
10
+ if ($LASTEXITCODE -ne 0) { Write-Host "Configuration failed." -ForegroundColor Red; Pop-Location; exit 1 }
11
+
12
+ cmake --build . --config Release --target pycauset
13
+ if ($LASTEXITCODE -ne 0) { Write-Host "Build failed." -ForegroundColor Red; Pop-Location; exit 1 }
14
+
15
+ # Find the generated .pyd file
16
+ $pydFile = Get-ChildItem -Recurse -Filter "pycauset*.pyd" | Select-Object -First 1
17
+
18
+ if ($pydFile) {
19
+ Write-Host "Found module: $($pydFile.FullName)" -ForegroundColor Green
20
+ $packageDir = Join-Path .. "python/pycauset"
21
+ if (-not (Test-Path $packageDir)) {
22
+ New-Item -ItemType Directory -Path $packageDir | Out-Null
23
+ }
24
+ Copy-Item $pydFile.FullName -Destination $packageDir -Force
25
+ Copy-Item $pydFile.FullName -Destination ..\ -Force
26
+ Write-Host "Copied to python/pycauset/ and project root."
27
+ } else {
28
+ Write-Host "Could not find generated .pyd file." -ForegroundColor Red
29
+ }
30
+
31
+ Pop-Location