prete 2.5.1__py3-none-any.whl

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.
@@ -0,0 +1,503 @@
1
+ Metadata-Version: 2.4
2
+ Name: prete
3
+ Version: 2.5.1
4
+ Summary: Pure-Python implementation of the Rete algorithm for production rule systems
5
+ Project-URL: Homepage, https://github.com/stefano-bragaglia/pRETE
6
+ Project-URL: Source, https://github.com/stefano-bragaglia/pRETE
7
+ Project-URL: Changelog, https://github.com/stefano-bragaglia/pRETE/blob/main/CHANGELOG.md
8
+ Author-email: Stefano Bragaglia <stefano-bragaglia@users.noreply.github.com>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: expert-system,inference,pattern-matching,production-rules,rete,rule-engine,rules
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Requires-Python: >=3.10
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest-cov==7.1.0; extra == 'dev'
26
+ Requires-Dist: pytest==9.1.1; extra == 'dev'
27
+ Requires-Dist: radon==6.0.1; extra == 'dev'
28
+ Requires-Dist: ruff==0.15.18; extra == 'dev'
29
+ Requires-Dist: xenon==0.9.3; extra == 'dev'
30
+ Description-Content-Type: text/markdown
31
+
32
+ # pRETE (Python RETE)
33
+
34
+ A pure-Python implementation of the Rete algorithm for production rule systems,
35
+ matching over arbitrary Python objects (POPOs — Plain Old Python Objects).
36
+
37
+ ![pRETE logo](https://raw.githubusercontent.com/stefano-bragaglia/pRETE/main/images/pRETE-logo-small.png)
38
+
39
+ [![CI](https://github.com/stefano-bragaglia/pRETE/actions/workflows/ci.yml/badge.svg)](https://github.com/stefano-bragaglia/pRETE/actions/workflows/ci.yml)
40
+ [![PyPI version](https://img.shields.io/pypi/v/prete)](https://pypi.org/project/prete/)
41
+ [![Python versions](https://img.shields.io/pypi/pyversions/prete)](https://pypi.org/project/prete/)
42
+ [![License](https://img.shields.io/github/license/stefano-bragaglia/pRETE)](LICENSE)
43
+
44
+ > **v2.0.0 breaking change:** the `(id, attribute, value)` triple model has
45
+ > been replaced by Drools-style pattern matching over `@dataclass` objects.
46
+ > `WME`, `Condition`, and `WILDCARD` are removed; use `Fact`, `Pattern`, and
47
+ > `JoinSpec` instead. See [CHANGELOG.md](CHANGELOG.md).
48
+
49
+ > **v2.1.0 — pRETE Rule Language (PRL):** rules can now be written in `.prl`
50
+ > text files (a Python-flavoured subset of Drools Rule Language) and loaded
51
+ > directly into the engine via `load_prl()`. The RETE engine itself is
52
+ > unchanged.
53
+
54
+ > **v2.5.0 — PRL Extra Features:** ten new PRL language constructs — type
55
+ > inheritance (`extends`), identity keys (`@key`), positional/named constraint
56
+ > shorthand, `@no-loop` tag, `import` / `from … import`, `or` disjunction,
57
+ > `forall`, `exists`, CEP event semantics (`@role`, `@timestamp`, `@expires`),
58
+ > and `accumulate` with built-in aggregation functions. New engine nodes:
59
+ > `ExistsNode`, `AccumulateNode`; logical clock for CEP.
60
+
61
+ ## Background
62
+
63
+ Implements the algorithm from:
64
+ - Forgy, C. L. (1982). Rete: A fast algorithm for the many pattern/many object
65
+ pattern match problem. *Artificial Intelligence*, 19(1), 17–37.
66
+ - Doorenbos, R. B. (1995). *Production system techniques for large rule bases*
67
+ (CMU-CS-95-113). Carnegie Mellon University.
68
+
69
+ v1.x represented working memory as `(id, attribute, value)` triples per
70
+ Doorenbos §2.1. v2.0 follows the Drools model: any Python object may be a
71
+ fact; patterns match by type then by callable field tests; variable bindings
72
+ are named and carried in the token.
73
+
74
+ ---
75
+
76
+ ## Install
77
+
78
+ ```bash
79
+ pip install prete
80
+ ```
81
+
82
+ For development:
83
+
84
+ ```bash
85
+ pip install -e ".[dev]"
86
+ ```
87
+
88
+ ---
89
+
90
+ ## Core concepts
91
+
92
+ | Term | What it is |
93
+ |------|-----------|
94
+ | `Fact(obj)` | Wraps any Python object as a working-memory element (identity semantics — two `Fact`s wrapping equal objects are distinct) |
95
+ | `Pattern(type_, alpha_tests, join_tests, bindings, negated)` | Matches facts by `isinstance` check then by callable field tests |
96
+ | `JoinSpec(attr_of_fact, var_name)` | Compile-time cross-fact constraint declared inside a `Pattern`; resolved at join time |
97
+ | `Production(lhs, rhs)` | A rule: a list of `Pattern`s / `NccGroup`s and a Python callable that receives the matched `Token` |
98
+ | `Token` | An immutable sequence of matched `Fact`s plus a `bindings: dict[str, Any]` of named variable values |
99
+ | `ReteNetwork` | The compiled network; call `add_fact` / `remove_fact` / `add_production` |
100
+ | `InferenceEngine` | Wraps `ReteNetwork` with a select-and-fire loop; adds `update_fact` |
101
+
102
+ Variable names start with `$`. A variable binds to an object attribute on its
103
+ first match (`Pattern.bindings`) and must equal that value in every subsequent
104
+ condition that references it (`Pattern.join_tests` / `JoinSpec`).
105
+
106
+ ---
107
+
108
+ ## Quick start
109
+
110
+ ### Single-pattern rule
111
+
112
+ ```python
113
+ from dataclasses import dataclass
114
+ from rete import Fact, Pattern, Production, ReteNetwork
115
+
116
+ @dataclass
117
+ class Temperature:
118
+ sensor: str
119
+ value: float
120
+
121
+ def too_hot(obj: Temperature) -> bool:
122
+ return obj.value >= 80.0
123
+
124
+ net = ReteNetwork()
125
+ alarms = []
126
+
127
+ net.add_production(Production(
128
+ lhs=[Pattern(Temperature, alpha_tests=(too_hot,),
129
+ bindings=(("$sensor", "sensor"),))],
130
+ rhs=lambda token: alarms.append(token.bindings["$sensor"]),
131
+ ))
132
+
133
+ net.add_fact(Fact(Temperature("T1", 60.0)))
134
+ net.add_fact(Fact(Temperature("T2", 95.0)))
135
+
136
+ for inst in net.conflict_set:
137
+ inst.production.rhs(inst.token)
138
+
139
+ print(alarms) # ['T2']
140
+ ```
141
+
142
+ ### Cross-fact binding
143
+
144
+ Use `bindings` to capture a variable and `JoinSpec` to require it in a later
145
+ pattern.
146
+
147
+ ```python
148
+ from dataclasses import dataclass
149
+ from rete import Fact, JoinSpec, Pattern, Production, ReteNetwork
150
+
151
+ @dataclass
152
+ class Color:
153
+ block: str
154
+ color: str
155
+
156
+ @dataclass
157
+ class Size:
158
+ block: str
159
+ size: str
160
+
161
+ def is_red(obj: Color) -> bool: return obj.color == "red"
162
+ def is_large(obj: Size) -> bool: return obj.size == "large"
163
+
164
+ net = ReteNetwork()
165
+
166
+ net.add_production(Production(
167
+ lhs=[
168
+ # bind $block = Color.block
169
+ Pattern(Color, alpha_tests=(is_red,), bindings=(("$block", "block"),)),
170
+ # require Size.block == $block
171
+ Pattern(Size, alpha_tests=(is_large,),
172
+ join_tests=(JoinSpec("block", "$block"),)),
173
+ ],
174
+ rhs=lambda token: print(f"Block {token.bindings['$block']} is red and large"),
175
+ ))
176
+
177
+ net.add_fact(Fact(Color("B1", "red")))
178
+ net.add_fact(Fact(Size("B1", "large")))
179
+ net.add_fact(Fact(Color("B2", "red"))) # B2 has no matching Size → no match
180
+
181
+ for inst in net.conflict_set:
182
+ inst.production.rhs(inst.token)
183
+ # Block B1 is red and large
184
+ ```
185
+
186
+ > **Alpha sharing note:** two `Pattern`s that pass the **same function object**
187
+ > in `alpha_tests` share one alpha memory. Always use stable, module-level
188
+ > functions — not inline lambdas — when sharing matters.
189
+
190
+ ### Negated conditions
191
+
192
+ `negated=True` makes the pattern a blocking condition: the rule fires only when
193
+ **no** fact satisfies it.
194
+
195
+ ```python
196
+ @dataclass
197
+ class Marker:
198
+ block: str
199
+ key: str
200
+
201
+ def is_broken(obj: Marker) -> bool:
202
+ return obj.key == "broken"
203
+
204
+ net.add_production(Production(
205
+ lhs=[
206
+ Pattern(Color, alpha_tests=(is_red,), bindings=(("$block", "block"),)),
207
+ Pattern(Marker, alpha_tests=(is_broken,),
208
+ join_tests=(JoinSpec("block", "$block"),), negated=True),
209
+ ],
210
+ rhs=lambda token: print(f"{token.bindings['$block']} is red and not broken"),
211
+ ))
212
+ ```
213
+
214
+ ### Negated conjunctive conditions (NCC)
215
+
216
+ `NccGroup` wraps several patterns that must **not** jointly match.
217
+
218
+ ```python
219
+ from rete import NccGroup
220
+
221
+ net.add_production(Production(
222
+ lhs=[
223
+ Pattern(Color, alpha_tests=(is_red,), bindings=(("$block", "block"),)),
224
+ NccGroup(conditions=(
225
+ Pattern(Marker, alpha_tests=(is_broken,),
226
+ join_tests=(JoinSpec("block", "$block"),)),
227
+ )),
228
+ ],
229
+ rhs=lambda token: print("match"),
230
+ ))
231
+ ```
232
+
233
+ See `src/examples/programmatic/fraud_detection.py` for a full NCC round-trip example.
234
+
235
+ ### Retraction
236
+
237
+ Removing a `Fact` automatically retracts every match that depended on it.
238
+
239
+ ```python
240
+ f = Fact(Temperature("T3", 90.0))
241
+ net.add_fact(f)
242
+ # ... conflict set has a new entry ...
243
+ net.remove_fact(f)
244
+ # conflict set entry is gone
245
+ ```
246
+
247
+ ### Mutation — `update_fact`
248
+
249
+ POPOs are mutable. Mutate an attribute in place, then call `update_fact` to
250
+ resync the network (equivalent to Drools `modify`). Object identity is
251
+ preserved across the retract / re-assert cycle.
252
+
253
+ ```python
254
+ engine = InferenceEngine()
255
+ # ... add productions and facts ...
256
+ fact.obj.approved = False # mutate in place
257
+ engine.update_fact(fact) # retract → re-assert
258
+ engine.run()
259
+ ```
260
+
261
+ ### Inference engine — select-and-fire loop
262
+
263
+ `InferenceEngine` wraps `ReteNetwork` with a `run()` loop.
264
+
265
+ ```python
266
+ from rete import Fact, InferenceEngine, Pattern, Production
267
+
268
+ @dataclass
269
+ class Item:
270
+ name: str
271
+
272
+ engine = InferenceEngine()
273
+ found = []
274
+
275
+ engine.add_production(Production(
276
+ lhs=[Pattern(Item, bindings=(("$name", "name"),))],
277
+ rhs=lambda token: found.append(token.bindings["$name"]),
278
+ ))
279
+
280
+ engine.add_fact(Fact(Item("apple")))
281
+ engine.add_fact(Fact(Item("banana")))
282
+
283
+ fired = engine.run()
284
+ print(f"Fired {fired} rule(s): {sorted(found)}")
285
+ # Fired 2 rule(s): ['apple', 'banana']
286
+ ```
287
+
288
+ The default conflict-resolution strategy is **recency** (last-added wins).
289
+ `InferenceEngine.fifo_strategy` is also available; pass any callable as
290
+ `InferenceEngine(strategy=...)` for a custom policy.
291
+
292
+ ---
293
+
294
+ ## MRO dispatch
295
+
296
+ The alpha network dispatches by `type(fact.obj).__mro__`, so a `Dog` fact
297
+ reaches a `Pattern(type_=Animal)` automatically. No explicit registration
298
+ needed.
299
+
300
+ ---
301
+
302
+ ## pRETE Rule Language (PRL)
303
+
304
+ PRL is a text notation for writing rules without touching Python — a strict
305
+ subset of [Drools Rule Language](https://docs.drools.org) adapted for pRETE.
306
+ Rules live in `.prl` files; `load_prl()` compiles them into `Production`
307
+ objects and hands them to the engine.
308
+
309
+ ### What PRL supports
310
+
311
+ #### Core (v2.1.0)
312
+
313
+ | Construct | Example |
314
+ |---|---|
315
+ | Fact-type declaration | `declare Temperature value: double end` |
316
+ | OOPath pattern | `/Temperature[value >= 80]` |
317
+ | Traditional pattern | `Temperature(value >= 80)` |
318
+ | Fact binding | `$t: Temperature(value >= 80)` |
319
+ | Field binding | `$v: value` inside a pattern |
320
+ | Cross-fact join | `field == $bound_var` |
321
+ | Single negation | `not Temperature(value < 0)` |
322
+ | Conjunctive negation (NCC) | `not ( Pattern1() Pattern2() )` |
323
+ | Rule salience | `salience 10` |
324
+ | RHS helpers | `insert(obj)`, `retract(obj)`, `update(obj)` |
325
+
326
+ #### Extra features (v2.5.0)
327
+
328
+ | Construct | Example |
329
+ |---|---|
330
+ | Type inheritance | `declare Dog extends Animal` |
331
+ | Identity key | `@key` before a field in `declare` — custom `__eq__`/`__hash__` |
332
+ | Positional constraints | `Point(0, 0)` — values matched left-to-right by declaration order |
333
+ | Named constraints | `Point(y=0)` — any subset, any order |
334
+ | `@no-loop` tag | `@no-loop` before `rule` — prevents self-re-activation |
335
+ | Python imports | `from myapp.models import Customer` at top of `.prl` file |
336
+ | `or` disjunction | `PatternA() or PatternB()` — compiler expands to N productions |
337
+ | `forall` | `forall(Order(status=="pending"), Approval(orderId==$o.id))` |
338
+ | `exists` | `exists Invoice(overdue == true)` — fires once per left context |
339
+ | `@role(event)` / `@timestamp` / `@expires` | CEP — events expire automatically after `advance_clock(t)` |
340
+ | `accumulate` | `accumulate(Order($a: amount); $total: sum($a); $total > 1000)` |
341
+
342
+ ### Quick start
343
+
344
+ ```
345
+ // temperature_alarm.prl
346
+ declare Temperature
347
+ sensor: str
348
+ value: float
349
+ end
350
+
351
+ declare Alert
352
+ message: str
353
+ end
354
+
355
+ rule "Too Hot"
356
+ salience 10
357
+ when
358
+ $t: /Temperature[value >= 80]
359
+ then
360
+ insert(Alert("Sensor " + t.obj.sensor + " too hot"))
361
+ end
362
+ ```
363
+
364
+ ```python
365
+ from pathlib import Path
366
+ from rete import Fact, InferenceEngine, load_prl
367
+
368
+ engine = InferenceEngine()
369
+ types, productions = load_prl(
370
+ Path("temperature_alarm.prl").read_text(), engine=engine
371
+ )
372
+ for p in productions:
373
+ engine.add_production(p)
374
+
375
+ Temperature = types["Temperature"]
376
+ engine.add_fact(Fact(Temperature(sensor="S1", value=95.0)))
377
+ engine.run()
378
+ ```
379
+
380
+ ### v2.5.0 feature examples
381
+
382
+ **Type inheritance** — a rule on the parent type fires for child facts:
383
+
384
+ ```
385
+ declare Animal name: String end
386
+ declare Dog extends Animal breed: String end
387
+
388
+ rule "greet animal"
389
+ when
390
+ $a: Animal()
391
+ then
392
+ greet(a)
393
+ end
394
+ ```
395
+
396
+ **`exists`** — fires once per account regardless of how many overdue invoices exist:
397
+
398
+ ```
399
+ rule "alert account"
400
+ when
401
+ $acc: Account()
402
+ exists Invoice(accountId == $acc.id, overdue == true)
403
+ then
404
+ alert(acc)
405
+ end
406
+ ```
407
+
408
+ **`accumulate`** — aggregate and constrain in the LHS:
409
+
410
+ ```
411
+ rule "flag high spend"
412
+ when
413
+ accumulate(
414
+ Order($amount: amount);
415
+ $total: sum($amount);
416
+ $total > 1000
417
+ )
418
+ then
419
+ results.append(total)
420
+ end
421
+ ```
422
+
423
+ **CEP** — events expire automatically after the logical clock advances:
424
+
425
+ ```
426
+ @role(event)
427
+ @expires(30s)
428
+ declare StockTick
429
+ @timestamp
430
+ ts: float
431
+ symbol: String
432
+ price: float
433
+ end
434
+ ```
435
+
436
+ ```python
437
+ engine.add_fact(Fact(StockTick(ts=0.0, symbol="ACME", price=42.0)))
438
+ engine.advance_clock(31.0) # tick expired — retracted before next run()
439
+ engine.run()
440
+ ```
441
+
442
+ The grammar is documented in [`reference/prl-grammar.ebnf`](reference/prl-grammar.ebnf).
443
+
444
+ ---
445
+
446
+ ## Bundled examples
447
+
448
+ Examples are split into two folders:
449
+
450
+ ```bash
451
+ # src/examples/programmatic/ — pure Python, no .prl files
452
+ python src/examples/programmatic/blocks_world.py # §2.1 — three-pattern join
453
+ python src/examples/programmatic/negation.py # §2.7 — negated condition
454
+ python src/examples/programmatic/sharing.py # §2.3 — two productions sharing a beta node
455
+ python src/examples/programmatic/loan_application.py # update_fact; cross-fact binding
456
+ python src/examples/programmatic/temperature_alarm.py # alpha test; RHS inserts new facts
457
+ python src/examples/programmatic/family_tree.py # transitive inference
458
+ python src/examples/programmatic/fraud_detection.py # NccGroup; retraction round-trip
459
+
460
+ # src/examples/declarative/ — load rules from .prl files in declarative/prl/
461
+ python src/examples/declarative/blocks_world_prl.py # PRL equivalent of blocks_world
462
+ python src/examples/declarative/negation_prl.py
463
+ python src/examples/declarative/sharing_prl.py
464
+ python src/examples/declarative/loan_application_prl.py
465
+ python src/examples/declarative/temperature_alarm_prl.py
466
+ python src/examples/declarative/family_tree_prl.py
467
+ python src/examples/declarative/fraud_detection_prl.py
468
+ python src/examples/declarative/inheritance_prl.py # ES-1: extends
469
+ python src/examples/declarative/identity_key_prl.py # ES-3: @key
470
+ python src/examples/declarative/compact_patterns_prl.py # ES-4: positional/named constraints
471
+ python src/examples/declarative/self_modify_prl.py # ES-2: @no-loop
472
+ python src/examples/declarative/imported_types_prl.py # ES-5: import
473
+ python src/examples/declarative/disjunction_prl.py # ES-6: or
474
+ python src/examples/declarative/universal_prl.py # ES-6: forall
475
+ python src/examples/declarative/existence_check_prl.py # ES-7: exists
476
+ python src/examples/declarative/event_stream_prl.py # ES-8: CEP
477
+ python src/examples/declarative/aggregation_prl.py # ES-9: accumulate
478
+ ```
479
+
480
+ ---
481
+
482
+ ## Dev
483
+
484
+ ```bash
485
+ hatch run check # xenon (complexity A) + ruff + pytest --cov (fail-under 80)
486
+ ```
487
+
488
+ Individual tools:
489
+ ```bash
490
+ xenon --max-absolute A --max-modules A --max-average A src/ tests/
491
+ ruff check src/ tests/
492
+ pytest --cov
493
+ ```
494
+
495
+ ---
496
+
497
+ ## History
498
+ - **v2.5.1** — test suite expanded to 99%+ coverage
499
+ - **v2.5.0** — ten PRL language extensions: `extends`, `@key`, positional/named constraints, `@no-loop` tag, `import`, `or`/`forall`, `exists`, CEP (`@role`/`@timestamp`/`@expires`), `accumulate`; new `ExistsNode` and `AccumulateNode` beta nodes; logical clock; examples reorganised into `declarative/` and `programmatic/`
500
+ - **v2.1.0** — PRL parser: `load_prl()`, `.prl` files, lexer / AST / compiler pipeline
501
+ - **v2.0.0** — Drools-style POPO matching: `Fact`, `Pattern`, `JoinSpec`; `update_fact`; MRO dispatch; named variable bindings on `Token`
502
+ - **v1.0.1** — incremental fixes
503
+ - **v1.0.0** — triple WME model (`WME`, `Condition`)
@@ -0,0 +1,15 @@
1
+ rete/__init__.py,sha256=50r1hJHT1_8VvKLuSBtZ3XgD2xO3UtyHna-1h3R6e6g,1045
2
+ rete/alpha.py,sha256=blU5eokmUY7ypOOpuK2AJzRSJqfKlLdj2dnlMA0TyTE,4989
3
+ rete/beta.py,sha256=Sqern2FJ8YHgUtTBCpxB_0CFua1xVpQCcIdh_MPFxEw,31897
4
+ rete/condition.py,sha256=VraQQ5pQR1D4fdjw4IpvWI0d451Se0-NKKFkHJb90LE,5402
5
+ rete/engine.py,sha256=WC4bYB8CrfjBYVLhuX9fowUPcts-si8rLO2LuDCG-xs,6433
6
+ rete/fact.py,sha256=LHJw-AQ71H5HcsZIq4AfOJ1Q-td8aYvCKLYxeJgRCjo,1223
7
+ rete/network.py,sha256=tfW78t8KjnxFyxJ1M7ubx9IgsPZFxmN550tlo5he-ac,22381
8
+ rete/prl.py,sha256=zSc7jKhZ8xWcCgv-WIHcIDjh_JAxbfOcGZ4qE7OWGhM,29493
9
+ rete/prl_ast.py,sha256=53tnA1cHoVkt4kFwkxDVFMbXI11-YfJQ97z0vyxYEH4,8933
10
+ rete/prl_lexer.py,sha256=ohydbfW8YZWJqKQh6FbC1IkEJ6AgqdPxxN1rhX2xFiI,7127
11
+ rete/prl_parser.py,sha256=7z65zTDf9eaxzhPom2J5pssqwByaKR4ckGSe1RsfqLI,22292
12
+ prete-2.5.1.dist-info/METADATA,sha256=AmHpncQxjyL-mKcOB-p6x9o5M00Q5iWDJpCq6hKxX6I,16420
13
+ prete-2.5.1.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
14
+ prete-2.5.1.dist-info/licenses/LICENSE,sha256=Jh-H3Km2nsWIL9fCg17ABcOkEraKHnRczvHq--UGBl0,1074
15
+ prete-2.5.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.30.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Stefano Bragaglia
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
rete/__init__.py ADDED
@@ -0,0 +1,52 @@
1
+ """Pure-Python implementation of the Rete algorithm (Forgy 1982, Doorenbos 1995)."""
2
+
3
+ from rete.alpha import AlphaMemory, RootNode
4
+ from rete.beta import (
5
+ BaseJoinNode,
6
+ BetaMemory,
7
+ DummyTopNode,
8
+ Instantiation,
9
+ JoinNode,
10
+ JoinTest,
11
+ LeftNode,
12
+ NccNode,
13
+ NccPartnerNode,
14
+ NccToken,
15
+ NegativeJoinNode,
16
+ NegativeToken,
17
+ PNode,
18
+ RightNode,
19
+ )
20
+ from rete.condition import JoinSpec, NccGroup, Pattern, Production
21
+ from rete.engine import InferenceEngine
22
+ from rete.fact import Fact, Token
23
+ from rete.network import ReteNetwork
24
+ from rete.prl import load_prl
25
+
26
+ __all__ = [
27
+ "AlphaMemory",
28
+ "BaseJoinNode",
29
+ "BetaMemory",
30
+ "DummyTopNode",
31
+ "Fact",
32
+ "InferenceEngine",
33
+ "Instantiation",
34
+ "JoinNode",
35
+ "JoinSpec",
36
+ "JoinTest",
37
+ "LeftNode",
38
+ "load_prl",
39
+ "NccGroup",
40
+ "NccNode",
41
+ "NccPartnerNode",
42
+ "NccToken",
43
+ "NegativeJoinNode",
44
+ "NegativeToken",
45
+ "Pattern",
46
+ "PNode",
47
+ "Production",
48
+ "ReteNetwork",
49
+ "RightNode",
50
+ "RootNode",
51
+ "Token",
52
+ ]