Metadata-Version: 2.1
Name: typedlogic
Version: 0.1.2
Summary: typedlogic
License: MIT
Author: Author 1
Author-email: author@org.org
Requires-Python: >=3.10,<4.0
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Provides-Extra: clingo
Provides-Extra: clorm
Provides-Extra: llm
Provides-Extra: pydantic
Provides-Extra: pyprover
Provides-Extra: rdflib
Provides-Extra: snakelog
Provides-Extra: sympy
Provides-Extra: tests
Provides-Extra: z3
Requires-Dist: clingo ; extra == "clingo"
Requires-Dist: clorm ; extra == "clorm"
Requires-Dist: importlib-metadata (>=8.2.0)
Requires-Dist: llm ; extra == "llm"
Requires-Dist: pydantic ; extra == "pydantic"
Requires-Dist: pyprover ; extra == "pyprover"
Requires-Dist: rdflib ; extra == "rdflib"
Requires-Dist: snakelog ; extra == "snakelog"
Requires-Dist: sympy ; extra == "sympy"
Requires-Dist: typer (>=0.12.5,<0.13.0)
Requires-Dist: z3-solver ; extra == "z3"
Description-Content-Type: text/markdown

from typedlogic.registry import get_solver

# py-typedlogic: Pythonic logic for your data models.

Define logical predicates directly in Python as Pydantic, dataclasses, SQLModel, or plain python objects:

```python
# links.py
from pydantic import BaseModel
from typedlogic import FactMixin, Term

ID = str

class Link(BaseModel, FactMixin):
    """A link between two entities"""
    source: ID
    target: ID

class Path(BaseModel, FactMixin):
    """An N-hop path between two entities, consisting of one or more links"""
    source: ID
    target: ID
    hops: int
```

This data model has two classes, `Link` and `Path`. These also correspond to *predicate signatures*
in a logical theory.

You can use this to create objects (ground terms, in logic terms) using normal Python code:

```python
links = []
for source, target in [('CA', 'OR'), ('OR', 'WA')]:
   links.append(link)
```

Define logical *constraints* or *rules* using Python syntax:
 
```python
from typedlogic.decorators import axiom

@axiom
def path_from_link(x: ID, y: ID):
    """If there is a link from x to y, there is a path from x to y"""
    if Link(source=x, target=y):
        assert Path(source=x, target=y, hops=1)

@axiom
def transitivity(x: ID, y: ID, z: ID, d1: int, d2: int):
    """Transitivity of paths, plus hop counting"""
    if Path(source=x, target=y, hops=d1) and Path(source=y, target=z, hops=d2):
        assert Path(source=x, target=z, hops=d1+d2)
```

Use a solver to infer new facts:

```python
from typedlogic.registry import get_solver
from links import Link

solver = get_solver("clingo")
solver.load(links) 
links = [Link(source='CA', target='OR'), Link(source='OR', target='WA')]
for link in links:
    solver.add(link)
model = solver.model()
for fact in model.iter_retrieve("Path"):
    print(fact)
```

prints:

```
Path(source='CA', target='OR')
Path(source='OR', target='WA')
Path(source='CA', target='WA')
```

## Key Features

- Write logical axioms and rules using Python syntax (but can also be used independently of this)
- Benefit from strong typing and mypy validation
- Integration with multiple FOL solvers and logic programming engines
- Interconversion between multiple syntaxes for FOL, Rules, and logical models
- Integration with OWL-DL
- Integration with Python libraries like Pydantic
- Command Line and Python interfaces

## Installation

Install TypedLogic using pip:

```bash
pip install "typedlogic"
```

## Next Steps

- Consult the main docs 

