Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions .github/workflows/python-package-version-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,21 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8 pytest
python -m pip install ruff pytest
pip install torch==2.6.0
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with ruff
run: |
python -m ruff check pyreason/scripts
- name: Pytest Unit Tests with JIT Disabled
run: |
pytest tests/unit/disable_jit
pytest tests/unit/disable_jit -m "not slow" --tb=short -q
- name: Pytest Unit Tests with JIT Enabled
run: |
pytest tests/unit/dont_disable_jit
pytest tests/unit/dont_disable_jit -m "not slow" --tb=short -q
- name: Pytest API Tests
run: |
pytest tests/unit/api_tests --tb=short -q
- name: Pytest Functional Tests
run: |
pytest tests/functional

pytest tests/functional/ --tb=short
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
__pycache__/
*.py[cod]
*$py.class
"pyreason/.cache_status.yaml
# Cache status file when initialized
# Keep the initial false version in repo, ignore when it becomes true
.DS_STORE
Expand Down Expand Up @@ -174,4 +175,3 @@ cython_debug/

# Sphinx Documentation
/docs/source/_static/css/fonts/

2 changes: 1 addition & 1 deletion .numba_config.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
disable_jit: 0
cache_dir: ./pyreason/cache/
cache_dir: ./pyreason/cache/
22 changes: 18 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,26 +1,40 @@
exclude: 'pyreason/\.cache_status\.yaml'
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: end-of-file-fixer
name: Fix end of files
stages: [pre-commit]

- repo: local
hooks:
# --- COMMIT STAGE: Fast unit tests only ---
- id: ruff-check
name: Run ruff linter
entry: .venv/bin/python -m ruff check pyreason/scripts
language: system
types: [python]
pass_filenames: false
stages: [pre-commit]

- id: pytest-unit-no-jit
name: Run JIT-disabled unit tests
name: Run JIT-disabled unit tests
entry: .venv/bin/python -m pytest tests/unit/disable_jit -m "not slow" --tb=short -q
language: system
pass_filenames: false
stages: [pre-commit]

- id: pytest-unit-jit
name: Run JIT-enabled unit tests
name: Run JIT-enabled unit tests
entry: .venv/bin/python -m pytest tests/unit/dont_disable_jit -m "not slow" --tb=short -q
language: system
pass_filenames: false
stages: [pre-commit]

# --- PUSH STAGE: Complete test suite ---

- id: pytest-unit-api
name: Run pyreason api unit tests
name: Run pyreason api unit tests
entry: .venv/bin/python -m pytest tests/unit/api_tests --tb=short -q
language: system
pass_filenames: false
Expand Down
10 changes: 5 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,10 @@ coverage-xml: ## Show path to XML coverage report
# Development targets
lint: ## Run linting checks
@echo "$(BOLD)$(BLUE)Running linting checks...$(RESET)"
@echo "$(YELLOW)Note: Add your preferred linter commands here$(RESET)"
# Example: flake8 pyreason tests
# Example: black --check pyreason tests
# Example: mypy pyreason
@echo "Fixing end of files..."
@pre-commit run end-of-file-fixer --all-files || true
@echo "Running ruff..."
./.venv/bin/python -m ruff check pyreason/scripts

check-deps: ## Check if required dependencies are installed
@echo "$(BOLD)$(BLUE)Checking dependencies...$(RESET)"
Expand Down Expand Up @@ -176,4 +176,4 @@ info: ## Show project and tool versions
@echo "Pytest: $$($(PYTHON) -c 'import pytest; print(pytest.__version__)' 2>/dev/null || echo 'Not installed')"
@echo "Coverage: $$($(PYTHON) -c 'import coverage; print(coverage.__version__)' 2>/dev/null || echo 'Not installed')"
@echo "Working Directory: $$(pwd)"
@echo "Test Runner: $$(ls -la run_tests.py 2>/dev/null || echo 'Not found')"
@echo "Test Runner: $$(ls -la run_tests.py 2>/dev/null || echo 'Not found')"
2 changes: 1 addition & 1 deletion contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ We are working to update the codebase to comply with `ruff` linting rules. Run
this command to view linting results:

```bash
ruff check .
.venv/bin/python -m ruff check pyreason/scripts
```

## Running Tests
Expand Down
2 changes: 1 addition & 1 deletion docs/hello-world.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,4 @@ After running the python file, the expected output is:
3. For timestep 2, since Justin has just become popular, John now has one popular friend (Justin) and the same pet as Justin (dog). Therefore `Justin -> popular: [1,1]`


We also output two CSV files detailing all the events that took place during reasoning (one for nodes, one for edges)
We also output two CSV files detailing all the events that took place during reasoning (one for nodes, one for edges)
1 change: 0 additions & 1 deletion docs/hello-world.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,3 @@

# Get all interpretations in a dictionary
interpretations_dict = interpretation.get_interpretation_dict()

2 changes: 1 addition & 1 deletion docs/source/api_reference/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ API Documentation
.. automodule:: pyreason
:members:
:undoc-members:
:show-inheritance:
:show-inheritance:
1 change: 0 additions & 1 deletion docs/source/examples_rst/advanced_example.rst
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,3 @@ Advanced Example
# Display filtered node and edge data
print(df1)
print(df2)

2 changes: 1 addition & 1 deletion docs/source/examples_rst/advanced_output_example.rst
Original file line number Diff line number Diff line change
Expand Up @@ -695,4 +695,4 @@ Advanced Example Full Output
('customer_6', 'Car_6'): {},
('customer_6', 'Pet_4'): {},
('customer_6', 'customer_0'): {'same_color_car': (1.0, 1.0)}}}


1 change: 0 additions & 1 deletion docs/source/examples_rst/annF_average_example.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,3 @@ Average Annotation Function Example
assert interpretation.query('average_function(A, B) : [0.105, 1]'), 'Average function should be [0.105, 1]'

average_annotation_function()

Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,4 @@ Linear Combination Annotation Function Example
assert interpretation.query('linear_combination_function(A, B) : [0.1, 0.4]'), 'Linear combination function should be [0.105, 1]'

# Run the test function
linear_combination_annotation_function()
linear_combination_annotation_function()
2 changes: 1 addition & 1 deletion docs/source/examples_rst/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ Examples

./*



2 changes: 1 addition & 1 deletion docs/source/examples_rst/infer_edges_example.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,4 @@ Infer Edges Example
assert ('Vnukovo_International_Airport', 'Riga_International_Airport') in dataframes[1]['component'].values.tolist() and dataframes[1]['isConnectedTo'].iloc[0] == [1, 1], '(Vnukovo_International_Airport, Riga_International_Airport) should have isConnectedTo bounds [1,1] for t=1 timesteps'

nx.draw(G, with_labels=True, node_color='lightblue', font_weight='bold', node_size=3000)
plt.show()
plt.show()
2 changes: 1 addition & 1 deletion docs/source/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ You will see a message like this when you import PyReason for the first time:

.. code:: text

Imported PyReason for the first time. Initializing caches for faster runtimes ... this will take a minute
Imported PyReason for the first time. Initializing caches for faster runtimes ... this will take a minute
1 change: 0 additions & 1 deletion docs/source/license.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@ Trademark Permission
:width: 50

PyReason™ and PyReason Design Logo |logo| ™ are trademarks of the Arizona Board of Regents/Arizona State University. Users of the software are permitted to use PyReason™ in association with the software for any purpose, provided such use is related to the software (e.g., Powered by PyReason™). Additionally, educational institutions are permitted to use the PyReason Design Logo |logo| ™ for non-commercial purposes.

2 changes: 1 addition & 1 deletion docs/source/tutorials/advanced_tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,4 @@ Below is the expected output at timestep ``0``
('customer_6', 'Car_6'): {},
('customer_6', 'Pet_4'): {},
('customer_6', 'customer_0'): {'same_color_car': (1.0, 1.0)}},


2 changes: 1 addition & 1 deletion docs/source/tutorials/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ Contents
./custom_thresholds.rst
./infer_edges.rst
./annotation_function.rst


3 changes: 0 additions & 3 deletions docs/source/tutorials/infer_edges.rst
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,3 @@ The graph after running shows a new connection from ``Vnukovo_International_Airp

.. image:: ../../../media/infer_edges2.png
:align: center



2 changes: 1 addition & 1 deletion docs/source/user_guide/3_pyreason_rules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -208,4 +208,4 @@ PyReason's ``Threshold`` class is used to define custom thresholds for a rule. T
and the second is either ``"total"`` or ``"available"``. ``"total"`` refers to all groundings of the clause, while ``"available"`` refers to the groundings that have the predicate of the clause.
#. ``thresh`` **(int)**: The value of the threshold

An example usage can be found :ref:`here <custom_thresholds_tutorial>`.
An example usage can be found :ref:`here <custom_thresholds_tutorial>`.
2 changes: 1 addition & 1 deletion docs/source/user_guide/4_pyreason_settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,4 @@ Notes on Parallelism
~~~~~~~~~~~~~~~~~~~~
PyReason is parallelized over rules, so for large rulesets it is recommended that this setting is used. However, for small rulesets,
the overhead might be more than the speedup and it is worth checking the performance on your specific use case.
When possible we recommend using the same number of cores (or a multiple) as the number of rules in the program.
When possible we recommend using the same number of cores (or a multiple) as the number of rules in the program.
2 changes: 1 addition & 1 deletion docs/source/user_guide/5_inconsistent_predicate_list.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ This can be done by using the following code:
pr.add_inconsistent_predicate('sick', 'healthy')

This allows PyReason to automatically update the bounds of the predicates in the inconsistent predicate list to the
negation of a predicate that is updated.
negation of a predicate that is updated.
1 change: 0 additions & 1 deletion docs/source/user_guide/7_jupyter_notebook_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,3 @@ However, if you want to use PyReason in a Jupyter Notebook, make sure you unders

1. When using functions like ``add_rule`` or ``add_fact`` in a Jupyter Notebook, make sure to run the cell only once. Running the cell multiple times will add the same rule/fact multiple times. It is recommended to store all the rules and facts in an array and then add them all at once in one cell towards the end
2. Functions like ``load_graph`` and ``load_graphml`` which are run multiple times can also have the same issue. Make sure to run them only once.

3 changes: 0 additions & 3 deletions docs/source/user_guide/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,3 @@ In this section we demonstrate the functionality of the `pyreason` library and h
:glob:

./*



2 changes: 1 addition & 1 deletion examples/advanced_output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -836,4 +836,4 @@ Filtered Edges:
6 (customer_4, customer_5) [0, 1] [1.0, 1.0]
7 (customer_5, customer_3) [0, 1] [1.0, 1.0]
8 (customer_5, customer_6) [0, 1] [1.0, 1.0]
9 (customer_6, customer_0) [0, 1] [1.0, 1.0]]
9 (customer_6, customer_0) [0, 1] [1.0, 1.0]]
2 changes: 1 addition & 1 deletion examples/temporal_classifier_integration_ex.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,4 @@
trace = pr.get_rule_trace(interpretation)

print("\n=== Reasoning Rule Trace ===")
print(trace[0])
print(trace[0])
2 changes: 1 addition & 1 deletion initialize.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Run this script after cloning repository to generate the numba caches. This script runs the hello-world program internally
print('Initializing PyReason caches')
import pyreason as pr


2 changes: 1 addition & 1 deletion jobs/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
*
*/
!.gitignore
!.gitignore
2 changes: 1 addition & 1 deletion output/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
*
*/
!.gitignore
!.gitignore
2 changes: 1 addition & 1 deletion profiling/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
*
*/
!.gitignore
!.gitignore
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
[build-system]
requires = ['setuptools>=42']
build-backend = 'setuptools.build_meta'

[tool.ruff.lint]
# Ignore ambiguous variable name errors (E741) in interpretation files
[tool.ruff.lint.per-file-ignores]
"pyreason/scripts/interpretation/*.py" = ["E741"]
1 change: 1 addition & 0 deletions pyreason/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# ruff: noqa: F403 F405 (Ignore Pyreason import * for public api)
# Set numba environment variable
import os
package_path = os.path.abspath(os.path.dirname(__file__))
Expand Down
13 changes: 7 additions & 6 deletions pyreason/pyreason.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# This is the file that will be imported when "import pyreason" is called. All content will be run automatically
# ruff: noqa: F401 (Ignore Pyreason import * for public api)
import importlib
import networkx as nx
import numba
import time
Expand All @@ -25,15 +27,14 @@
import pyreason.scripts.numba_wrapper.numba_types.fact_edge_type as fact_edge
import pyreason.scripts.numba_wrapper.numba_types.interval_type as interval
from pyreason.scripts.utils.reorder_clauses import reorder_clauses
try:
import torch
except ImportError:
if importlib.util.find_spec("torch") is not None:
from pyreason.scripts.learning.classification.classifier import LogicIntegratedClassifier
from pyreason.scripts.learning.utils.model_interface import ModelInterfaceOptions
else:
LogicIntegratedClassifier = None
ModelInterfaceOptions = None
print('torch is not installed, model integration is disabled')
else:
from pyreason.scripts.learning.classification.classifier import LogicIntegratedClassifier
from pyreason.scripts.learning.utils.model_interface import ModelInterfaceOptions



# USER VARIABLES
Expand Down
8 changes: 3 additions & 5 deletions pyreason/scripts/annotation_functions/annotation_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ def _check_bound(lower, upper):
if lower > upper:
return (0, 1)
else:
l = min(lower, 1)
u = min(upper, 1)
return (l, u)
lower_bound = min(lower, 1)
upper_bound = min(upper, 1)
return (lower_bound, upper_bound)


@numba.njit
Expand Down Expand Up @@ -99,5 +99,3 @@ def minimum(annotations, weights):
lower, upper = _check_bound(min_lower, min_upper)

return interval.closed(lower, upper)


2 changes: 1 addition & 1 deletion pyreason/scripts/components/label.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ def __hash__(self):
return hash(str(self))

def __repr__(self):
return self.get_value()
return self.get_value()
11 changes: 4 additions & 7 deletions pyreason/scripts/components/world.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ class World:
def __init__(self, labels):
self._labels = labels
self._world = numba.typed.Dict.empty(key_type=label.label_type, value_type=interval.interval_type)
for l in labels:
self._world[l] = interval.closed(0.0, 1.0)
for lbl in labels:
self._world[lbl] = interval.closed(0.0, 1.0)

@property
def world(self):
Expand All @@ -29,9 +29,6 @@ def is_satisfied(self, label, interval):
return result

def update(self, label, interval):
lwanted = None
bwanted = None

current_bnd = self._world[label]
new_bnd = current_bnd.intersection(interval)
self._world[label] = new_bnd
Expand All @@ -48,7 +45,7 @@ def get_world(self):

def __str__(self):
result = ''
for label in self._world.keys():
result = result + label.get_value() + ',' + self._world[label].to_str() + '\n'
for lbl in self._world.keys():
result = result + lbl.get_value() + ',' + self._world[lbl].to_str() + '\n'

return result
Loading