torchlogix 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 (31) hide show
  1. torchlogix-0.1.0/.flake8 +8 -0
  2. torchlogix-0.1.0/.gitignore +22 -0
  3. torchlogix-0.1.0/.pre-commit-config.yaml +37 -0
  4. torchlogix-0.1.0/LICENSE +22 -0
  5. torchlogix-0.1.0/MANIFEST.in +30 -0
  6. torchlogix-0.1.0/PKG-INFO +230 -0
  7. torchlogix-0.1.0/README.md +176 -0
  8. torchlogix-0.1.0/assets/logo.png +0 -0
  9. torchlogix-0.1.0/assets/pictogram.png +0 -0
  10. torchlogix-0.1.0/pyproject.toml +97 -0
  11. torchlogix-0.1.0/setup.cfg +4 -0
  12. torchlogix-0.1.0/setup.py +73 -0
  13. torchlogix-0.1.0/src/torchlogix/__init__.py +7 -0
  14. torchlogix-0.1.0/src/torchlogix/compiled_model.py +964 -0
  15. torchlogix-0.1.0/src/torchlogix/functional.py +344 -0
  16. torchlogix-0.1.0/src/torchlogix/layers/__init__.py +4 -0
  17. torchlogix-0.1.0/src/torchlogix/layers/conv.py +706 -0
  18. torchlogix-0.1.0/src/torchlogix/layers/dense.py +354 -0
  19. torchlogix-0.1.0/src/torchlogix/layers/groupsum.py +50 -0
  20. torchlogix-0.1.0/src/torchlogix/layers/thresholding.py +47 -0
  21. torchlogix-0.1.0/src/torchlogix/models/__init__.py +6 -0
  22. torchlogix-0.1.0/src/torchlogix/models/baseline_nn.py +25 -0
  23. torchlogix-0.1.0/src/torchlogix/models/conv.py +436 -0
  24. torchlogix-0.1.0/src/torchlogix/models/dense.py +105 -0
  25. torchlogix-0.1.0/src/torchlogix/models/nn.py +25 -0
  26. torchlogix-0.1.0/src/torchlogix/packbitstensor.py +57 -0
  27. torchlogix-0.1.0/src/torchlogix.egg-info/PKG-INFO +230 -0
  28. torchlogix-0.1.0/src/torchlogix.egg-info/SOURCES.txt +29 -0
  29. torchlogix-0.1.0/src/torchlogix.egg-info/dependency_links.txt +1 -0
  30. torchlogix-0.1.0/src/torchlogix.egg-info/requires.txt +19 -0
  31. torchlogix-0.1.0/src/torchlogix.egg-info/top_level.txt +1 -0
@@ -0,0 +1,8 @@
1
+ [flake8]
2
+ max-line-length = 88
3
+ extend-ignore = E203, W503, D100, D107, D105
4
+ # excluding files that weren't authored by me
5
+ exclude = .git,__pycache__,build,dist,*.egg-info,experiments
6
+ per-file-ignores =
7
+ __init__.py: F401
8
+ max-complexity = 10
@@ -0,0 +1,22 @@
1
+ venv/
2
+ *pyc
3
+ .idea
4
+ *.so
5
+ *egg-info
6
+ __pycache__/
7
+ .DS_Store
8
+ .ipynb_checkpoints
9
+ *.pytest_cache/
10
+ build/
11
+ experiments/results/
12
+
13
+ # Documentation build artifacts
14
+ docs/_build/
15
+ docs/api/generated/
16
+
17
+ # Sphinx temporary files
18
+ docs/.doctrees/
19
+
20
+ # data in experiments folder
21
+ experiments/data-mnist/
22
+ experiments/data-fmnist/
@@ -0,0 +1,37 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v4.5.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ - id: check-added-large-files
9
+ - id: check-ast
10
+ - id: check-json
11
+ - id: check-merge-conflict
12
+ - id: detect-private-key
13
+
14
+ - repo: https://github.com/hhatto/autopep8
15
+ rev: v2.0.4
16
+ hooks:
17
+ - id: autopep8
18
+ args: [--max-line-length=88, --in-place, --aggressive]
19
+
20
+ - repo: https://github.com/psf/black
21
+ rev: 23.12.1
22
+ hooks:
23
+ - id: black
24
+ language_version: python3
25
+
26
+ - repo: https://github.com/pycqa/isort
27
+ rev: 5.13.2
28
+ hooks:
29
+ - id: isort
30
+ name: isort (python)
31
+
32
+ - repo: https://github.com/pycqa/flake8
33
+ rev: 6.1.0
34
+ hooks:
35
+ - id: flake8
36
+ additional_dependencies: [flake8-docstrings]
37
+ exclude: ^(src/neurodifflogic/difflogic/|src/neurodifflogic/experiments/results_json.py|src/neurodifflogic/experiments/uci_datasets.py|src/neurodifflogic/experiments/mnist_dataset.py|src/neurodifflogic/models/difflog_layers/linear.py)
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021-2023 Dr. Felix Petersen
4
+ Copyright (c) 2024-present Dr. Lino Gerlach
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
@@ -0,0 +1,30 @@
1
+ # Include documentation files
2
+ include README.md
3
+ include LICENSE
4
+ include CHANGELOG.md
5
+
6
+ # Include configuration files
7
+ include pyproject.toml
8
+ include setup.py
9
+ include .flake8
10
+
11
+ # Include assets
12
+ recursive-include assets *.png *.jpg *.jpeg *.svg
13
+
14
+ # Exclude unnecessary files
15
+ global-exclude __pycache__
16
+ global-exclude *.py[cod]
17
+ global-exclude *.so
18
+ global-exclude .DS_Store
19
+ global-exclude *.egg-info
20
+
21
+ # Exclude development and build directories
22
+ prune .git
23
+ prune .github
24
+ prune docs
25
+ prune tests
26
+ prune experiments
27
+ prune venv
28
+ prune build
29
+ prune dist
30
+ prune misc
@@ -0,0 +1,230 @@
1
+ Metadata-Version: 2.4
2
+ Name: torchlogix
3
+ Version: 0.1.0
4
+ Summary: Differentiable Logic Gate Networks in PyTorch
5
+ Home-page: https://github.com/ligerlac/torchlogix
6
+ Author: Lino Gerlach
7
+ Author-email: Lino Gerlach <lino.oscar.gerlach@cern.ch>
8
+ Maintainer-email: Lino Gerlach <lino.oscar.gerlach@cern.ch>
9
+ License: MIT
10
+ Project-URL: Homepage, https://github.com/ligerlac/torchlogix
11
+ Project-URL: Documentation, https://ligerlac.github.io/torchlogix/
12
+ Project-URL: Repository, https://github.com/ligerlac/torchlogix
13
+ Project-URL: Bug Tracker, https://github.com/ligerlac/torchlogix/issues
14
+ Keywords: deep-learning,pytorch,logic-gates,neural-networks,machine-learning
15
+ Classifier: Development Status :: 4 - Beta
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Intended Audience :: Science/Research
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.6
20
+ Classifier: Programming Language :: Python :: 3.7
21
+ Classifier: Programming Language :: Python :: 3.8
22
+ Classifier: Programming Language :: Python :: 3.9
23
+ Classifier: Programming Language :: Python :: 3.10
24
+ Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: License :: OSI Approved :: MIT License
26
+ Classifier: Operating System :: OS Independent
27
+ Classifier: Topic :: Scientific/Engineering
28
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
29
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
30
+ Requires-Python: >=3.6
31
+ Description-Content-Type: text/markdown
32
+ License-File: LICENSE
33
+ Requires-Dist: torch>=1.6.0
34
+ Requires-Dist: numpy>=1.19.0
35
+ Requires-Dist: tqdm>=4.50.0
36
+ Requires-Dist: scikit-learn>=0.24.0
37
+ Requires-Dist: torchvision>=0.8.0
38
+ Requires-Dist: rich>=10.0.0
39
+ Provides-Extra: dev
40
+ Requires-Dist: flake8>=6.1.0; extra == "dev"
41
+ Requires-Dist: black>=23.12.1; extra == "dev"
42
+ Requires-Dist: isort>=5.13.2; extra == "dev"
43
+ Requires-Dist: pre-commit>=3.6.0; extra == "dev"
44
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
45
+ Requires-Dist: autopep8>=2.0.4; extra == "dev"
46
+ Requires-Dist: sphinx>=4.0.0; extra == "dev"
47
+ Requires-Dist: sphinx-rtd-theme>=1.0.0; extra == "dev"
48
+ Provides-Extra: geometric
49
+ Requires-Dist: torch-geometric>=2.0.0; extra == "geometric"
50
+ Dynamic: author
51
+ Dynamic: home-page
52
+ Dynamic: license-file
53
+ Dynamic: requires-python
54
+
55
+ # torchlogix - Differentiable Logic Gate Networks in PyTorch
56
+
57
+ ![torchlogix_logo](assets/logo.png)
58
+
59
+ **Note:** `torchlogix` is based on the original `difflogic` package ([https://github.com/Felix-Petersen/difflogic/](https://github.com/Felix-Petersen/difflogic/)), which serves as the official implementation of the NeurIPS 2022 Paper "Deep Differentiable Logic Gate Networks"
60
+ (Paper @ [ArXiv](https://arxiv.org/abs/2210.08277)) by Felix Petersen et al. As the aforementioned repository is not maintained anymore, `torchlogix` extends `difflogic` by bugfixes and new concepts such as learnable thermometer thresholding and the walsh-decomposition-based reparametrization of differentiable logic gates with 4 instead of 16 parameters as described in "WARP-LUTs - Walsh-Assisted Relaxation for Probabilistic Look Up Tables" (Paper @ [ArXiv](https://www.arxiv.org/abs/2510.15655)). It also implements convolutional logic gate layers as described in the NeurIPS 2024 Paper "Convolutional Logic Gate Networks (Paper @ [ArXiv](https://arxiv.org/pdf/2411.04732)).
61
+
62
+ The goal behind differentiable logic gate networks is to solve machine learning tasks by learning combinations of logic
63
+ gates, i.e., logic gate networks. As the choice of a logic is conventionally non-differentiable, relaxations are applied
64
+ to allow training logic gate networks with gradient-based methods. Specifically, `torchlogix` combines real-valued logic
65
+ and a continuously parameterized approximation of the network. This allows learning which logic gate (out of 16 possible)
66
+ is optimal for each neuron. The resulting discretized logic gate networks achieve fast inference speeds, e.g., beyond a
67
+ million images of MNIST per second on a single CPU core.
68
+
69
+ `torchlogix` is a Python 3.6+ and PyTorch 1.9.0+ based library for training and inference with logic gate networks.
70
+
71
+ ## Installation
72
+
73
+ ```shell
74
+ pip install torchlogix # basic
75
+ pip install "torchlogix[dev]" # with dev tools
76
+ ```
77
+
78
+ ## 📚 Documentation
79
+
80
+ **Full documentation is available at:** [TorchLogix Documentation](https://ligerlac.github.io/torchlogix/)
81
+
82
+ - **[Installation Guide](docs/guides/installation.md)** - Detailed installation instructions
83
+ - **[Quick Start](docs/guides/quickstart.md)** - Get started with TorchLogix in minutes
84
+ - **[Logic Gates Guide](docs/guides/logic_gates.md)** - Understanding the 16 Boolean operations
85
+ - **[Examples](docs/guides/examples.md)** - Complete training examples and tutorials
86
+ - **[API Reference](docs/api/torchlogix.rst)** - Comprehensive API documentation
87
+
88
+ ### Building Documentation
89
+
90
+ ```bash
91
+ cd docs
92
+ pip install -r requirements.txt
93
+ make html
94
+ open _build/html/index.html # macOS
95
+ ```
96
+
97
+ ## 🌱 Intro and Training
98
+
99
+ This library provides a framework for both training and inference with logic gate networks.
100
+ The following gives an example of a definition of a differentiable logic network model for the MNIST data set:
101
+
102
+ ```python
103
+ import torch
104
+ from torchlogix.layers import LogicDense, LogicConv2d, OrPooling, GroupSum, LearnableThermometerThresholding
105
+
106
+ model = torch.nn.Sequential(
107
+ LogicConv2d(in_dim=28, num_kernels=64, receptive_field_size=5),
108
+ OrPooling(kernel_size=2, stride=2, padding=0),
109
+ LogicConv2d(in_dim=12, num_kernels=256, receptive_field_size=3),
110
+ torch.nn.Flatten(),
111
+ LogicLayer(256*10*10, 16_000),
112
+ LogicLayer(16_000, 16_000),
113
+ LogicLayer(16_000, 16_000),
114
+ GroupSum(k=10, tau=30)
115
+ )
116
+ ```
117
+
118
+ This model receives a `(1,28,28)` dimensional input and returns `k=10` values corresponding to the 10 classes of MNIST.
119
+ The model may be trained, e.g., with a `torch.nn.CrossEntropyLoss` similar to how other neural networks models are trained in PyTorch.
120
+ Notably, the Adam optimizer (`torch.optim.Adam`) should be used for training and the recommended default learning rate is `0.01` instead of `0.001`.
121
+ Finally, it is also important to note that the number of neurons in each layer is much higher for logic gate networks compared to
122
+ conventional MLP neural networks because logic gate networks are very sparse.
123
+
124
+ To go into details, for each of these modules, in the following we provide more in-depth examples:
125
+
126
+ ```python
127
+ layer = DenseLogic(
128
+ in_dim=784, # number of inputs
129
+ out_dim=16_000, # number of outputs
130
+ device='cuda', # the device (cuda / cpu)
131
+ connections='random', # the method for the initialization of the connections
132
+ parametrization='raw', # classic 16 weights per node (one per gate) one of two 4-weight parametrizations ('anf' or 'walsh')
133
+ weight_init="residual", # weight initialization scheme ("random" or "residual")
134
+ forward_sampling="soft" # Method for the foward pass: "soft", "hard", "gumbel_soft", or "gumbel_hard"
135
+ )
136
+ layer = LogicConv2d(
137
+ in_dim=28, # dimension of input (can be two-tuple for non-quadratic shapes)
138
+ channels=3, # number of channels of the input (1 for grey-scale)
139
+ num_kernels=32, # number of convolutional kernels (filters)
140
+ tree_depth=3, # depth of the binary logic tree that make up each kernel
141
+ receptive_field_size=3, # comparable to kernel size in ordinary convolutional kernels (can be two-tuple for non-quadratic shapes)
142
+ padding=0,
143
+ ... # all other keyword arguments like dense layer above
144
+ )
145
+ ```
146
+
147
+ At this point, it is important to discuss the options for `device` and the provided implementations. Specifically,
148
+ `torchlogix` provides two implementations (both of which work with PyTorch):
149
+
150
+ * **`python`** the Python implementation is a substantially slower implementation that is easy to understand as it is implemented directly in Python with PyTorch and does not require any C++ / CUDA extensions. It is compatible with `device='cpu'` and `device='cuda'`.
151
+
152
+ To aggregate output neurons into a lower dimensional output space, we can use `GroupSum`, which aggregates a number of output neurons into
153
+ a `k` dimensional output, e.g., `k=10` for a 10-dimensional classification setting.
154
+ It is important to set the parameter `tau`, which the sum of neurons is divided by to keep the range reasonable.
155
+ As each neuron has a value between 0 and 1 (or in inference a value of 0 or 1), assuming `n` output neurons of the last `LogicLayer`,
156
+ the range of outputs is `[0, n / k / tau]`.
157
+
158
+ ## 🖥 Model Inference
159
+
160
+ During training, the model should remain in the PyTorch training mode (`.train()`), which keeps the model differentiable.
161
+ However, we can easily switch the model to a hard / discrete / non-differentiable model by calling `model.eval()`, i.e., for inference.
162
+ Typically, this will simply discretize the model but not make it faster per se.
163
+
164
+ However, there are two modes that allow for fast inference:
165
+
166
+ ### `PackBitsTensor`
167
+
168
+ The first option is to use a `PackBitsTensor`.
169
+ `PackBitsTensor`s allow efficient dynamic execution of trained logic gate networks on GPU.
170
+
171
+ A `PackBitsTensor` can package a tensor (of shape `b x n`) with boolean
172
+ data type in a way such that each boolean entry requires only a single bit (in contrast to the full byte typically
173
+ required by a bool) by packing the bits along the batch dimension. If we choose to pack the bits into the `int32` data
174
+ type (the options are 8, 16, 32, and 64 bits), we would receive a tensor of shape `ceil(b/32) x n` of dtype `int32`.
175
+ To create a `PackBitsTensor` from a boolean tensor `data`, simply call:
176
+ ```python
177
+ data_bits = torchlogix.PackBitsTensor(data)
178
+ ```
179
+ To apply a model to the `PackBitsTensor`, simply call:
180
+ ```python
181
+ output = model(data_bits)
182
+ ```
183
+ This requires that the `model` is in `.eval()` mode, and if supplied with a `PackBitsTensor`, will automatically use
184
+ a logic gate-based inference on the tensor. This also requires that `model.implementation = 'cuda'` as the mode is only
185
+ implemented in CUDA.
186
+ It is notable that, while the model is in `.eval()` mode, we can still also feed float tensors through the model, in
187
+ which case it will simply use a hard variant of the real-valued logics.
188
+
189
+ ### `CompiledLogicNet`
190
+
191
+ The second option is to use a `CompiledLogicNet`.
192
+ This allows especially efficient static execution of a fixed trained logic gate network on CPU.
193
+ Specifically, `CompiledLogicNet` converts a model into efficient C code and can compile this code into a binary that
194
+ can then be efficiently run or exported for applications.
195
+ The following is an example for creating `CompiledLogicNet` from a trained `model`:
196
+
197
+ ```python
198
+ compiled_model = torchlogix.CompiledLogicNet(
199
+ model=model, # the trained model (should be a `torch.nn.Sequential` with `LogicLayer`s)
200
+ num_bits=64, # the number of bits of the datatype used for inference (typically 64 is fastest, should not be larger than batch size)
201
+ cpu_compiler='gcc', # the compiler to use for the c code (alternative: clang)
202
+ verbose=True
203
+ )
204
+ compiled_model.compile(
205
+ save_lib_path='my_model_binary.so', # the (optional) location for storing the binary such that it can be reused
206
+ verbose=True
207
+ )
208
+
209
+ # to apply the model, we need a 2d numpy array of dtype bool, e.g., via `data = data.bool().numpy()`
210
+ output = compiled_model(data)
211
+ ```
212
+
213
+ This will compile a model into a shared object binary, which is then automatically imported.
214
+ To export this to other applications, one may either call the shared object binary from another program or export
215
+ the model into C code via `compiled_model.get_c_code()`.
216
+ A limitation of the current `CompiledLogicNet` is that the compilation time can become long for large models.
217
+
218
+ We note that between publishing the paper and the publication of `torchlogix`, we have substantially improved the implementations.
219
+ Thus, the model inference modes have some deviation from the implementations for the original paper as we have
220
+ focussed on making it more scalable, efficient, and easier to apply in applications.
221
+ We have especially focussed on modularity and efficiency for larger models and have opted to polish the presented
222
+ implementations over publishing a plethora of different competing implementations.
223
+
224
+ ## 🧪 Experiments
225
+
226
+ There are experiments on CIFAR-10 in the `experiments` directory. We will add more soon.
227
+
228
+ ## 📜 License
229
+
230
+ `torchlogix` is released under the MIT license. See [LICENSE](LICENSE) for additional details about it.
@@ -0,0 +1,176 @@
1
+ # torchlogix - Differentiable Logic Gate Networks in PyTorch
2
+
3
+ ![torchlogix_logo](assets/logo.png)
4
+
5
+ **Note:** `torchlogix` is based on the original `difflogic` package ([https://github.com/Felix-Petersen/difflogic/](https://github.com/Felix-Petersen/difflogic/)), which serves as the official implementation of the NeurIPS 2022 Paper "Deep Differentiable Logic Gate Networks"
6
+ (Paper @ [ArXiv](https://arxiv.org/abs/2210.08277)) by Felix Petersen et al. As the aforementioned repository is not maintained anymore, `torchlogix` extends `difflogic` by bugfixes and new concepts such as learnable thermometer thresholding and the walsh-decomposition-based reparametrization of differentiable logic gates with 4 instead of 16 parameters as described in "WARP-LUTs - Walsh-Assisted Relaxation for Probabilistic Look Up Tables" (Paper @ [ArXiv](https://www.arxiv.org/abs/2510.15655)). It also implements convolutional logic gate layers as described in the NeurIPS 2024 Paper "Convolutional Logic Gate Networks (Paper @ [ArXiv](https://arxiv.org/pdf/2411.04732)).
7
+
8
+ The goal behind differentiable logic gate networks is to solve machine learning tasks by learning combinations of logic
9
+ gates, i.e., logic gate networks. As the choice of a logic is conventionally non-differentiable, relaxations are applied
10
+ to allow training logic gate networks with gradient-based methods. Specifically, `torchlogix` combines real-valued logic
11
+ and a continuously parameterized approximation of the network. This allows learning which logic gate (out of 16 possible)
12
+ is optimal for each neuron. The resulting discretized logic gate networks achieve fast inference speeds, e.g., beyond a
13
+ million images of MNIST per second on a single CPU core.
14
+
15
+ `torchlogix` is a Python 3.6+ and PyTorch 1.9.0+ based library for training and inference with logic gate networks.
16
+
17
+ ## Installation
18
+
19
+ ```shell
20
+ pip install torchlogix # basic
21
+ pip install "torchlogix[dev]" # with dev tools
22
+ ```
23
+
24
+ ## 📚 Documentation
25
+
26
+ **Full documentation is available at:** [TorchLogix Documentation](https://ligerlac.github.io/torchlogix/)
27
+
28
+ - **[Installation Guide](docs/guides/installation.md)** - Detailed installation instructions
29
+ - **[Quick Start](docs/guides/quickstart.md)** - Get started with TorchLogix in minutes
30
+ - **[Logic Gates Guide](docs/guides/logic_gates.md)** - Understanding the 16 Boolean operations
31
+ - **[Examples](docs/guides/examples.md)** - Complete training examples and tutorials
32
+ - **[API Reference](docs/api/torchlogix.rst)** - Comprehensive API documentation
33
+
34
+ ### Building Documentation
35
+
36
+ ```bash
37
+ cd docs
38
+ pip install -r requirements.txt
39
+ make html
40
+ open _build/html/index.html # macOS
41
+ ```
42
+
43
+ ## 🌱 Intro and Training
44
+
45
+ This library provides a framework for both training and inference with logic gate networks.
46
+ The following gives an example of a definition of a differentiable logic network model for the MNIST data set:
47
+
48
+ ```python
49
+ import torch
50
+ from torchlogix.layers import LogicDense, LogicConv2d, OrPooling, GroupSum, LearnableThermometerThresholding
51
+
52
+ model = torch.nn.Sequential(
53
+ LogicConv2d(in_dim=28, num_kernels=64, receptive_field_size=5),
54
+ OrPooling(kernel_size=2, stride=2, padding=0),
55
+ LogicConv2d(in_dim=12, num_kernels=256, receptive_field_size=3),
56
+ torch.nn.Flatten(),
57
+ LogicLayer(256*10*10, 16_000),
58
+ LogicLayer(16_000, 16_000),
59
+ LogicLayer(16_000, 16_000),
60
+ GroupSum(k=10, tau=30)
61
+ )
62
+ ```
63
+
64
+ This model receives a `(1,28,28)` dimensional input and returns `k=10` values corresponding to the 10 classes of MNIST.
65
+ The model may be trained, e.g., with a `torch.nn.CrossEntropyLoss` similar to how other neural networks models are trained in PyTorch.
66
+ Notably, the Adam optimizer (`torch.optim.Adam`) should be used for training and the recommended default learning rate is `0.01` instead of `0.001`.
67
+ Finally, it is also important to note that the number of neurons in each layer is much higher for logic gate networks compared to
68
+ conventional MLP neural networks because logic gate networks are very sparse.
69
+
70
+ To go into details, for each of these modules, in the following we provide more in-depth examples:
71
+
72
+ ```python
73
+ layer = DenseLogic(
74
+ in_dim=784, # number of inputs
75
+ out_dim=16_000, # number of outputs
76
+ device='cuda', # the device (cuda / cpu)
77
+ connections='random', # the method for the initialization of the connections
78
+ parametrization='raw', # classic 16 weights per node (one per gate) one of two 4-weight parametrizations ('anf' or 'walsh')
79
+ weight_init="residual", # weight initialization scheme ("random" or "residual")
80
+ forward_sampling="soft" # Method for the foward pass: "soft", "hard", "gumbel_soft", or "gumbel_hard"
81
+ )
82
+ layer = LogicConv2d(
83
+ in_dim=28, # dimension of input (can be two-tuple for non-quadratic shapes)
84
+ channels=3, # number of channels of the input (1 for grey-scale)
85
+ num_kernels=32, # number of convolutional kernels (filters)
86
+ tree_depth=3, # depth of the binary logic tree that make up each kernel
87
+ receptive_field_size=3, # comparable to kernel size in ordinary convolutional kernels (can be two-tuple for non-quadratic shapes)
88
+ padding=0,
89
+ ... # all other keyword arguments like dense layer above
90
+ )
91
+ ```
92
+
93
+ At this point, it is important to discuss the options for `device` and the provided implementations. Specifically,
94
+ `torchlogix` provides two implementations (both of which work with PyTorch):
95
+
96
+ * **`python`** the Python implementation is a substantially slower implementation that is easy to understand as it is implemented directly in Python with PyTorch and does not require any C++ / CUDA extensions. It is compatible with `device='cpu'` and `device='cuda'`.
97
+
98
+ To aggregate output neurons into a lower dimensional output space, we can use `GroupSum`, which aggregates a number of output neurons into
99
+ a `k` dimensional output, e.g., `k=10` for a 10-dimensional classification setting.
100
+ It is important to set the parameter `tau`, which the sum of neurons is divided by to keep the range reasonable.
101
+ As each neuron has a value between 0 and 1 (or in inference a value of 0 or 1), assuming `n` output neurons of the last `LogicLayer`,
102
+ the range of outputs is `[0, n / k / tau]`.
103
+
104
+ ## 🖥 Model Inference
105
+
106
+ During training, the model should remain in the PyTorch training mode (`.train()`), which keeps the model differentiable.
107
+ However, we can easily switch the model to a hard / discrete / non-differentiable model by calling `model.eval()`, i.e., for inference.
108
+ Typically, this will simply discretize the model but not make it faster per se.
109
+
110
+ However, there are two modes that allow for fast inference:
111
+
112
+ ### `PackBitsTensor`
113
+
114
+ The first option is to use a `PackBitsTensor`.
115
+ `PackBitsTensor`s allow efficient dynamic execution of trained logic gate networks on GPU.
116
+
117
+ A `PackBitsTensor` can package a tensor (of shape `b x n`) with boolean
118
+ data type in a way such that each boolean entry requires only a single bit (in contrast to the full byte typically
119
+ required by a bool) by packing the bits along the batch dimension. If we choose to pack the bits into the `int32` data
120
+ type (the options are 8, 16, 32, and 64 bits), we would receive a tensor of shape `ceil(b/32) x n` of dtype `int32`.
121
+ To create a `PackBitsTensor` from a boolean tensor `data`, simply call:
122
+ ```python
123
+ data_bits = torchlogix.PackBitsTensor(data)
124
+ ```
125
+ To apply a model to the `PackBitsTensor`, simply call:
126
+ ```python
127
+ output = model(data_bits)
128
+ ```
129
+ This requires that the `model` is in `.eval()` mode, and if supplied with a `PackBitsTensor`, will automatically use
130
+ a logic gate-based inference on the tensor. This also requires that `model.implementation = 'cuda'` as the mode is only
131
+ implemented in CUDA.
132
+ It is notable that, while the model is in `.eval()` mode, we can still also feed float tensors through the model, in
133
+ which case it will simply use a hard variant of the real-valued logics.
134
+
135
+ ### `CompiledLogicNet`
136
+
137
+ The second option is to use a `CompiledLogicNet`.
138
+ This allows especially efficient static execution of a fixed trained logic gate network on CPU.
139
+ Specifically, `CompiledLogicNet` converts a model into efficient C code and can compile this code into a binary that
140
+ can then be efficiently run or exported for applications.
141
+ The following is an example for creating `CompiledLogicNet` from a trained `model`:
142
+
143
+ ```python
144
+ compiled_model = torchlogix.CompiledLogicNet(
145
+ model=model, # the trained model (should be a `torch.nn.Sequential` with `LogicLayer`s)
146
+ num_bits=64, # the number of bits of the datatype used for inference (typically 64 is fastest, should not be larger than batch size)
147
+ cpu_compiler='gcc', # the compiler to use for the c code (alternative: clang)
148
+ verbose=True
149
+ )
150
+ compiled_model.compile(
151
+ save_lib_path='my_model_binary.so', # the (optional) location for storing the binary such that it can be reused
152
+ verbose=True
153
+ )
154
+
155
+ # to apply the model, we need a 2d numpy array of dtype bool, e.g., via `data = data.bool().numpy()`
156
+ output = compiled_model(data)
157
+ ```
158
+
159
+ This will compile a model into a shared object binary, which is then automatically imported.
160
+ To export this to other applications, one may either call the shared object binary from another program or export
161
+ the model into C code via `compiled_model.get_c_code()`.
162
+ A limitation of the current `CompiledLogicNet` is that the compilation time can become long for large models.
163
+
164
+ We note that between publishing the paper and the publication of `torchlogix`, we have substantially improved the implementations.
165
+ Thus, the model inference modes have some deviation from the implementations for the original paper as we have
166
+ focussed on making it more scalable, efficient, and easier to apply in applications.
167
+ We have especially focussed on modularity and efficiency for larger models and have opted to polish the presented
168
+ implementations over publishing a plethora of different competing implementations.
169
+
170
+ ## 🧪 Experiments
171
+
172
+ There are experiments on CIFAR-10 in the `experiments` directory. We will add more soon.
173
+
174
+ ## 📜 License
175
+
176
+ `torchlogix` is released under the MIT license. See [LICENSE](LICENSE) for additional details about it.
Binary file
Binary file
@@ -0,0 +1,97 @@
1
+ [build-system]
2
+ requires = ["setuptools>=45", "wheel", "setuptools_scm>=6.2"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "torchlogix"
7
+ version = "0.1.0"
8
+ description = "Differentiable Logic Gate Networks in PyTorch"
9
+ readme = "README.md"
10
+ requires-python = ">=3.6"
11
+ license = {text = "MIT"}
12
+ authors = [
13
+ {name = "Lino Gerlach", email = "lino.oscar.gerlach@cern.ch"}
14
+ ]
15
+ maintainers = [
16
+ {name = "Lino Gerlach", email = "lino.oscar.gerlach@cern.ch"}
17
+ ]
18
+ keywords = ["deep-learning", "pytorch", "logic-gates", "neural-networks", "machine-learning"]
19
+ classifiers = [
20
+ "Development Status :: 4 - Beta",
21
+ "Intended Audience :: Developers",
22
+ "Intended Audience :: Science/Research",
23
+ "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3.6",
25
+ "Programming Language :: Python :: 3.7",
26
+ "Programming Language :: Python :: 3.8",
27
+ "Programming Language :: Python :: 3.9",
28
+ "Programming Language :: Python :: 3.10",
29
+ "Programming Language :: Python :: 3.11",
30
+ "License :: OSI Approved :: MIT License",
31
+ "Operating System :: OS Independent",
32
+ "Topic :: Scientific/Engineering",
33
+ "Topic :: Scientific/Engineering :: Mathematics",
34
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
35
+ ]
36
+
37
+ dependencies = [
38
+ "torch>=1.6.0",
39
+ "numpy>=1.19.0",
40
+ "tqdm>=4.50.0",
41
+ "scikit-learn>=0.24.0",
42
+ "torchvision>=0.8.0",
43
+ "rich>=10.0.0",
44
+ ]
45
+
46
+ [project.optional-dependencies]
47
+ dev = [
48
+ "flake8>=6.1.0",
49
+ "black>=23.12.1",
50
+ "isort>=5.13.2",
51
+ "pre-commit>=3.6.0",
52
+ "pytest>=8.0.0",
53
+ "autopep8>=2.0.4",
54
+ "sphinx>=4.0.0",
55
+ "sphinx-rtd-theme>=1.0.0",
56
+ ]
57
+ geometric = [
58
+ "torch-geometric>=2.0.0",
59
+ ]
60
+
61
+ [project.urls]
62
+ Homepage = "https://github.com/ligerlac/torchlogix"
63
+ Documentation = "https://ligerlac.github.io/torchlogix/"
64
+ Repository = "https://github.com/ligerlac/torchlogix"
65
+ "Bug Tracker" = "https://github.com/ligerlac/torchlogix/issues"
66
+
67
+ [tool.setuptools]
68
+ package-dir = {"" = "src"}
69
+
70
+ [tool.setuptools.packages.find]
71
+ where = ["src"]
72
+
73
+ [tool.black]
74
+ line-length = 88
75
+ target-version = ['py36']
76
+ include = '\.pyi?$'
77
+ extend-exclude = '''
78
+ # A regex preceded with ^/ will apply only to files and directories
79
+ # in the root of the project.
80
+ ^/docs
81
+ '''
82
+
83
+ [tool.isort]
84
+ profile = "black"
85
+ multi_line_output = 3
86
+ include_trailing_comma = true
87
+ force_grid_wrap = 0
88
+ use_parentheses = true
89
+ line_length = 88
90
+ skip = ['.git', 'build', 'dist', '*.egg-info']
91
+
92
+ [tool.pytest.ini_options]
93
+ testpaths = ["tests"]
94
+ python_files = ["test_*.py"]
95
+ python_classes = ["Test*"]
96
+ python_functions = ["test_*"]
97
+ addopts = "-v --strict-markers"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+