unicode-fol-kit 0.2.0__tar.gz → 0.2.1__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 (20) hide show
  1. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/PKG-INFO +65 -16
  2. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/README.md +64 -15
  3. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/pyproject.toml +1 -1
  4. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/unicode_fol_kit/__init__.py +1 -1
  5. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/.gitignore +0 -0
  6. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/LICENSE +0 -0
  7. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/unicode_fol_kit/atp/__init__.py +0 -0
  8. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/unicode_fol_kit/atp/prover9_entailment.py +0 -0
  9. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/unicode_fol_kit/atp/z3_equivalence.py +0 -0
  10. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/unicode_fol_kit/fol/__init__.py +0 -0
  11. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/unicode_fol_kit/fol/_fol_nodes.py +0 -0
  12. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/unicode_fol_kit/fol/_msfl_nodes.py +0 -0
  13. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/unicode_fol_kit/fol/grammars/fl.lark +0 -0
  14. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/unicode_fol_kit/fol/grammars/fol.lark +0 -0
  15. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/unicode_fol_kit/fol/grammars/msfl.lark +0 -0
  16. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/unicode_fol_kit/fol/grammars/msfol.lark +0 -0
  17. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/unicode_fol_kit/fol/grammars/terminals.lark +0 -0
  18. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/unicode_fol_kit/fol/msflparser.py +0 -0
  19. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/unicode_fol_kit/fol/naming.py +0 -0
  20. {unicode_fol_kit-0.2.0 → unicode_fol_kit-0.2.1}/unicode_fol_kit/fol/nodes.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: unicode-fol-kit
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Parser and toolkit for first-order logic formulas using Unicode operators
5
5
  Project-URL: Repository, https://github.com/fvossel/unicode-fol-kit
6
6
  Project-URL: Issues, https://github.com/fvossel/unicode-fol-kit/issues
@@ -24,11 +24,11 @@ Description-Content-Type: text/markdown
24
24
 
25
25
  # unicode-fol-kit
26
26
 
27
- A Python toolkit for parsing and working with first-order logic (FOL) formulas written with Unicode operators. The single parser class `MSFLParser` supports three modes — classical FOL, many-sorted FOL (MSFOL), and many-sorted fuzzy logic (MSFL, Łukasiewicz) — selected by constructor flags.
27
+ A Python toolkit for parsing and working with first-order logic (FOL) formulas written with Unicode operators. The single parser class `MSFLParser` supports four modes — classical FOL, many-sorted FOL (MSFOL), many-sorted fuzzy logic (MSFL), and single-sorted fuzzy logic (FL, Łukasiewicz) — selected by constructor flags.
28
28
 
29
29
  ## Features
30
30
 
31
- - **Three parser modes** — FOL, many-sorted FOL (MSFOL), and many-sorted fuzzy/Łukasiewicz logic (MSFL), all from one class
31
+ - **Four parser modes** — FOL, many-sorted FOL (MSFOL), many-sorted fuzzy/Łukasiewicz logic (MSFL), and single-sorted fuzzy/Łukasiewicz logic (FL), all from one class
32
32
  - **Unicode surface syntax** — natural symbols (∀ ∃ ∧ ∨ ¬ → ↔ ⊕ ⊗ = ≠ ≤ ≥) with no ASCII fallbacks needed
33
33
  - **Sorted quantifiers and constants** — `∀x:Human P(x)`, `P(alice:Human)` in MSFOL and MSFL modes
34
34
  - **Łukasiewicz operators** — weak ∧ / ∨ (min/max), strong ⊗ / ⊕ (t-norm/t-conorm), and Łukasiewicz ¬ → ↔ in MSFL mode
@@ -69,7 +69,7 @@ pip install .
69
69
  MSFLParser(many_sorted=False, fuzzy=False) # FOL (default)
70
70
  MSFLParser(many_sorted=True, fuzzy=False) # MSFOL
71
71
  MSFLParser(many_sorted=True, fuzzy=True) # MSFL
72
- MSFLParser(many_sorted=False, fuzzy=True) # → raises ValueError
72
+ MSFLParser(many_sorted=False, fuzzy=True) # FL
73
73
  ```
74
74
 
75
75
  | `many_sorted` | `fuzzy` | Mode | Quantifiers | Constants | Connectives |
@@ -77,6 +77,7 @@ MSFLParser(many_sorted=False, fuzzy=True) # → raises ValueError
77
77
  | `False` | `False` | **FOL** | unsorted `∀x` | unsorted | classical ∧ ∨ ⊕ ¬ → ↔ |
78
78
  | `True` | `False` | **MSFOL** | sorted `∀x:Sort` | sorted `alice:Sort` | classical ∧ ∨ ¬ → ↔ (no ⊕) |
79
79
  | `True` | `True` | **MSFL** | sorted `∀x:Sort` | sorted `alice:Sort` | weak ∧ ∨, strong ⊗ ⊕, Łuk ¬ → ↔ |
80
+ | `False` | `True` | **FL** | unsorted `∀x` | unsorted | weak ∧ ∨, strong ⊗ ⊕, Łuk ¬ → ↔ |
80
81
 
81
82
  ## Usage
82
83
 
@@ -120,6 +121,26 @@ parser.parse("P(x) → Q(x)") # LukImplication (min{1, 1−x+y})
120
121
  parser.parse("∀x:Human P(x)") # SortedQuantifier
121
122
  ```
122
123
 
124
+ ### FL mode
125
+
126
+ Łukasiewicz operators with **unsorted** quantifiers and plain constants — same connectives as MSFL, same quantifier/constant syntax as FOL:
127
+
128
+ ```python
129
+ parser = MSFLParser(many_sorted=False, fuzzy=True)
130
+
131
+ parser.parse("P(x) ∧ Q(x)") # WeakConjunction (min)
132
+ parser.parse("P(x) ⊗ Q(x)") # StrongConjunction (t-norm: max{0, x+y−1})
133
+ parser.parse("P(x) ⊕ Q(x)") # StrongDisjunction (t-conorm: min{1, x+y})
134
+ parser.parse("¬P(x)") # LukNegation (1−x)
135
+ parser.parse("P(x) → Q(x)") # LukImplication (min{1, 1−x+y})
136
+ parser.parse("∀x P(x)") # unsorted Quantifier (no sort annotation)
137
+ parser.parse("P(alice)") # plain Constant (no sort annotation)
138
+
139
+ # Lambda works in FL mode too
140
+ parser.parse("λx. P(x) ⊗ Q(x)")
141
+ # Lambda(LambdaVar("x"), StrongConjunction(Atom("P",[LambdaVar("x")]), Atom("Q",[LambdaVar("x")])))
142
+ ```
143
+
123
144
  ### ASCII tree view
124
145
 
125
146
  ```python
@@ -365,6 +386,21 @@ Connectives are reinterpreted as Łukasiewicz operators:
365
386
  | `φ ↔ ψ` | Łuk. equivalence | 1 − \|φ − ψ\| |
366
387
  | `∀x:Sort φ`, `∃x:Sort φ` | sorted quantifiers | |
367
388
 
389
+ #### FL mode
390
+
391
+ Same Łukasiewicz connectives as MSFL, but with **unsorted** quantifiers and plain constants (no `:Sort` required):
392
+
393
+ | Syntax | Operator | Semantics |
394
+ |---|---|---|
395
+ | `¬φ` | Łuk. negation | 1 − φ |
396
+ | `φ ∧ ψ` | weak conjunction | min(φ, ψ) |
397
+ | `φ ∨ ψ` | weak disjunction | max(φ, ψ) |
398
+ | `φ ⊗ ψ` | strong conjunction | max(0, φ + ψ − 1) |
399
+ | `φ ⊕ ψ` | strong disjunction | min(1, φ + ψ) |
400
+ | `φ → ψ` | Łuk. implication | min(1, 1 − φ + ψ) |
401
+ | `φ ↔ ψ` | Łuk. equivalence | 1 − \|φ − ψ\| |
402
+ | `∀x φ`, `∃x φ` | unsorted quantifiers | |
403
+
368
404
  A formula may be wrapped in parentheses `( … )` or square brackets `[ … ]`; the two are interchangeable for grouping.
369
405
 
370
406
  ### Operator precedence
@@ -374,7 +410,7 @@ The precedence levels are the same across all three modes (MSFL uses the same sy
374
410
  | Precedence | Operators | Associativity |
375
411
  |---|---|---|
376
412
  | 1 (highest) | `¬`, quantifiers `∀` / `∃` | prefix |
377
- | 2 | `∧` `∨` `⊕` (FOL) / `∧` `∨` (MSFOL) / `∧` `∨` `⊗` `⊕` (MSFL) | left |
413
+ | 2 | `∧` `∨` `⊕` (FOL) / `∧` `∨` (MSFOL) / `∧` `∨` `⊗` `⊕` (MSFL / FL) | left |
378
414
  | 3 | `→` | right |
379
415
  | 4 (lowest) | `↔` | right |
380
416
 
@@ -404,7 +440,7 @@ P(x) ∧ Q(x) ∨ R(x) # rejected
404
440
  (P(x) ∧ Q(x)) ∨ R(x) # accepted
405
441
  ```
406
442
 
407
- **MSFL mode** — `∧`, `∨`, `⊗`, `⊕` cannot be mixed:
443
+ **MSFL / FL mode** — `∧`, `∨`, `⊗`, `⊕` cannot be mixed:
408
444
 
409
445
  ```text
410
446
  P(x) ∧ Q(x) ⊗ R(x) # rejected
@@ -433,16 +469,16 @@ Quantifiers can be stacked directly: `∀x:H ∀y:H ∃z:A φ`.
433
469
 
434
470
  ### Supported symbols
435
471
 
436
- | Category | FOL | MSFOL | MSFL |
437
- |---|---|---|---|
438
- | Quantifiers | `∀` `∃` (unsorted) | `∀` `∃` (sorted `:Sort`) | `∀` `∃` (sorted `:Sort`) |
439
- | Connectives | `∧` `∨` `⊕` `¬` `→` `↔` | `∧` `∨` `¬` `→` `↔` | `∧` `∨` `⊗` `⊕` `¬` `→` `↔` |
440
- | Lambda | `λ` | `λ` | `λ` |
441
- | Sort annotations | — | `:Sort` | `:Sort` |
442
- | Equality / comparison | `=` `≠` `<` `>` `≤` `≥` | same | same |
443
- | Arithmetic | `+` `-` `*` `/` | same | same |
444
- | Grouping | `(` `)` `[` `]` | same | same |
445
- | Argument separator | `,` | same | same |
472
+ | Category | FOL | MSFOL | MSFL | FL |
473
+ |---|---|---|---|---|
474
+ | Quantifiers | `∀` `∃` (unsorted) | `∀` `∃` (sorted `:Sort`) | `∀` `∃` (sorted `:Sort`) | `∀` `∃` (unsorted) |
475
+ | Connectives | `∧` `∨` `⊕` `¬` `→` `↔` | `∧` `∨` `¬` `→` `↔` | `∧` `∨` `⊗` `⊕` `¬` `→` `↔` | `∧` `∨` `⊗` `⊕` `¬` `→` `↔` |
476
+ | Lambda | `λ` | `λ` | `λ` | `λ` |
477
+ | Sort annotations | — | `:Sort` | `:Sort` | — |
478
+ | Equality / comparison | `=` `≠` `<` `>` `≤` `≥` | same | same | same |
479
+ | Arithmetic | `+` `-` `*` `/` | same | same | same |
480
+ | Grouping | `(` `)` `[` `]` | same | same | same |
481
+ | Argument separator | `,` | same | same | same |
446
482
 
447
483
  Whitespace is insignificant and may be used freely between tokens — including before sort annotation colons.
448
484
 
@@ -535,6 +571,14 @@ parser.parse("(λP. P(x))(Q)")
535
571
  → Recommended(x:Patient, y:Treatment)
536
572
  ```
537
573
 
574
+ ### A complete FL example
575
+
576
+ ```text
577
+ ∀x ∀y
578
+ (Effective(y) ⊗ Tolerable(x, y))
579
+ → Recommended(x, y)
580
+ ```
581
+
538
582
  ## AST nodes
539
583
 
540
584
  All nodes are Python dataclasses and can be imported from `unicode_fol_kit`.
@@ -618,6 +662,11 @@ MSFLParser(many_sorted=True).parse("P(x) ∧ Q(x) ∨ R(x)")
618
662
  MSFLParser(many_sorted=True, fuzzy=True).parse("P(x) ∧ Q(x) ⊗ R(x)")
619
663
  # SYNTAX_ERROR: … Hint: Cannot mix weak conjunction (∧), weak disjunction (∨),
620
664
  # strong conjunction (⊗), and strong disjunction (⊕) without parentheses
665
+
666
+ # FL mode — same hint as MSFL (Łukasiewicz connectives, unsorted)
667
+ MSFLParser(many_sorted=False, fuzzy=True).parse("P(x) ∧ Q(x) ⊗ R(x)")
668
+ # SYNTAX_ERROR: … Hint: Cannot mix weak conjunction (∧), weak disjunction (∨),
669
+ # strong conjunction (⊗), and strong disjunction (⊕) without parentheses
621
670
  ```
622
671
 
623
672
  ## Citation
@@ -1,10 +1,10 @@
1
1
  # unicode-fol-kit
2
2
 
3
- A Python toolkit for parsing and working with first-order logic (FOL) formulas written with Unicode operators. The single parser class `MSFLParser` supports three modes — classical FOL, many-sorted FOL (MSFOL), and many-sorted fuzzy logic (MSFL, Łukasiewicz) — selected by constructor flags.
3
+ A Python toolkit for parsing and working with first-order logic (FOL) formulas written with Unicode operators. The single parser class `MSFLParser` supports four modes — classical FOL, many-sorted FOL (MSFOL), many-sorted fuzzy logic (MSFL), and single-sorted fuzzy logic (FL, Łukasiewicz) — selected by constructor flags.
4
4
 
5
5
  ## Features
6
6
 
7
- - **Three parser modes** — FOL, many-sorted FOL (MSFOL), and many-sorted fuzzy/Łukasiewicz logic (MSFL), all from one class
7
+ - **Four parser modes** — FOL, many-sorted FOL (MSFOL), many-sorted fuzzy/Łukasiewicz logic (MSFL), and single-sorted fuzzy/Łukasiewicz logic (FL), all from one class
8
8
  - **Unicode surface syntax** — natural symbols (∀ ∃ ∧ ∨ ¬ → ↔ ⊕ ⊗ = ≠ ≤ ≥) with no ASCII fallbacks needed
9
9
  - **Sorted quantifiers and constants** — `∀x:Human P(x)`, `P(alice:Human)` in MSFOL and MSFL modes
10
10
  - **Łukasiewicz operators** — weak ∧ / ∨ (min/max), strong ⊗ / ⊕ (t-norm/t-conorm), and Łukasiewicz ¬ → ↔ in MSFL mode
@@ -45,7 +45,7 @@ pip install .
45
45
  MSFLParser(many_sorted=False, fuzzy=False) # FOL (default)
46
46
  MSFLParser(many_sorted=True, fuzzy=False) # MSFOL
47
47
  MSFLParser(many_sorted=True, fuzzy=True) # MSFL
48
- MSFLParser(many_sorted=False, fuzzy=True) # → raises ValueError
48
+ MSFLParser(many_sorted=False, fuzzy=True) # FL
49
49
  ```
50
50
 
51
51
  | `many_sorted` | `fuzzy` | Mode | Quantifiers | Constants | Connectives |
@@ -53,6 +53,7 @@ MSFLParser(many_sorted=False, fuzzy=True) # → raises ValueError
53
53
  | `False` | `False` | **FOL** | unsorted `∀x` | unsorted | classical ∧ ∨ ⊕ ¬ → ↔ |
54
54
  | `True` | `False` | **MSFOL** | sorted `∀x:Sort` | sorted `alice:Sort` | classical ∧ ∨ ¬ → ↔ (no ⊕) |
55
55
  | `True` | `True` | **MSFL** | sorted `∀x:Sort` | sorted `alice:Sort` | weak ∧ ∨, strong ⊗ ⊕, Łuk ¬ → ↔ |
56
+ | `False` | `True` | **FL** | unsorted `∀x` | unsorted | weak ∧ ∨, strong ⊗ ⊕, Łuk ¬ → ↔ |
56
57
 
57
58
  ## Usage
58
59
 
@@ -96,6 +97,26 @@ parser.parse("P(x) → Q(x)") # LukImplication (min{1, 1−x+y})
96
97
  parser.parse("∀x:Human P(x)") # SortedQuantifier
97
98
  ```
98
99
 
100
+ ### FL mode
101
+
102
+ Łukasiewicz operators with **unsorted** quantifiers and plain constants — same connectives as MSFL, same quantifier/constant syntax as FOL:
103
+
104
+ ```python
105
+ parser = MSFLParser(many_sorted=False, fuzzy=True)
106
+
107
+ parser.parse("P(x) ∧ Q(x)") # WeakConjunction (min)
108
+ parser.parse("P(x) ⊗ Q(x)") # StrongConjunction (t-norm: max{0, x+y−1})
109
+ parser.parse("P(x) ⊕ Q(x)") # StrongDisjunction (t-conorm: min{1, x+y})
110
+ parser.parse("¬P(x)") # LukNegation (1−x)
111
+ parser.parse("P(x) → Q(x)") # LukImplication (min{1, 1−x+y})
112
+ parser.parse("∀x P(x)") # unsorted Quantifier (no sort annotation)
113
+ parser.parse("P(alice)") # plain Constant (no sort annotation)
114
+
115
+ # Lambda works in FL mode too
116
+ parser.parse("λx. P(x) ⊗ Q(x)")
117
+ # Lambda(LambdaVar("x"), StrongConjunction(Atom("P",[LambdaVar("x")]), Atom("Q",[LambdaVar("x")])))
118
+ ```
119
+
99
120
  ### ASCII tree view
100
121
 
101
122
  ```python
@@ -341,6 +362,21 @@ Connectives are reinterpreted as Łukasiewicz operators:
341
362
  | `φ ↔ ψ` | Łuk. equivalence | 1 − \|φ − ψ\| |
342
363
  | `∀x:Sort φ`, `∃x:Sort φ` | sorted quantifiers | |
343
364
 
365
+ #### FL mode
366
+
367
+ Same Łukasiewicz connectives as MSFL, but with **unsorted** quantifiers and plain constants (no `:Sort` required):
368
+
369
+ | Syntax | Operator | Semantics |
370
+ |---|---|---|
371
+ | `¬φ` | Łuk. negation | 1 − φ |
372
+ | `φ ∧ ψ` | weak conjunction | min(φ, ψ) |
373
+ | `φ ∨ ψ` | weak disjunction | max(φ, ψ) |
374
+ | `φ ⊗ ψ` | strong conjunction | max(0, φ + ψ − 1) |
375
+ | `φ ⊕ ψ` | strong disjunction | min(1, φ + ψ) |
376
+ | `φ → ψ` | Łuk. implication | min(1, 1 − φ + ψ) |
377
+ | `φ ↔ ψ` | Łuk. equivalence | 1 − \|φ − ψ\| |
378
+ | `∀x φ`, `∃x φ` | unsorted quantifiers | |
379
+
344
380
  A formula may be wrapped in parentheses `( … )` or square brackets `[ … ]`; the two are interchangeable for grouping.
345
381
 
346
382
  ### Operator precedence
@@ -350,7 +386,7 @@ The precedence levels are the same across all three modes (MSFL uses the same sy
350
386
  | Precedence | Operators | Associativity |
351
387
  |---|---|---|
352
388
  | 1 (highest) | `¬`, quantifiers `∀` / `∃` | prefix |
353
- | 2 | `∧` `∨` `⊕` (FOL) / `∧` `∨` (MSFOL) / `∧` `∨` `⊗` `⊕` (MSFL) | left |
389
+ | 2 | `∧` `∨` `⊕` (FOL) / `∧` `∨` (MSFOL) / `∧` `∨` `⊗` `⊕` (MSFL / FL) | left |
354
390
  | 3 | `→` | right |
355
391
  | 4 (lowest) | `↔` | right |
356
392
 
@@ -380,7 +416,7 @@ P(x) ∧ Q(x) ∨ R(x) # rejected
380
416
  (P(x) ∧ Q(x)) ∨ R(x) # accepted
381
417
  ```
382
418
 
383
- **MSFL mode** — `∧`, `∨`, `⊗`, `⊕` cannot be mixed:
419
+ **MSFL / FL mode** — `∧`, `∨`, `⊗`, `⊕` cannot be mixed:
384
420
 
385
421
  ```text
386
422
  P(x) ∧ Q(x) ⊗ R(x) # rejected
@@ -409,16 +445,16 @@ Quantifiers can be stacked directly: `∀x:H ∀y:H ∃z:A φ`.
409
445
 
410
446
  ### Supported symbols
411
447
 
412
- | Category | FOL | MSFOL | MSFL |
413
- |---|---|---|---|
414
- | Quantifiers | `∀` `∃` (unsorted) | `∀` `∃` (sorted `:Sort`) | `∀` `∃` (sorted `:Sort`) |
415
- | Connectives | `∧` `∨` `⊕` `¬` `→` `↔` | `∧` `∨` `¬` `→` `↔` | `∧` `∨` `⊗` `⊕` `¬` `→` `↔` |
416
- | Lambda | `λ` | `λ` | `λ` |
417
- | Sort annotations | — | `:Sort` | `:Sort` |
418
- | Equality / comparison | `=` `≠` `<` `>` `≤` `≥` | same | same |
419
- | Arithmetic | `+` `-` `*` `/` | same | same |
420
- | Grouping | `(` `)` `[` `]` | same | same |
421
- | Argument separator | `,` | same | same |
448
+ | Category | FOL | MSFOL | MSFL | FL |
449
+ |---|---|---|---|---|
450
+ | Quantifiers | `∀` `∃` (unsorted) | `∀` `∃` (sorted `:Sort`) | `∀` `∃` (sorted `:Sort`) | `∀` `∃` (unsorted) |
451
+ | Connectives | `∧` `∨` `⊕` `¬` `→` `↔` | `∧` `∨` `¬` `→` `↔` | `∧` `∨` `⊗` `⊕` `¬` `→` `↔` | `∧` `∨` `⊗` `⊕` `¬` `→` `↔` |
452
+ | Lambda | `λ` | `λ` | `λ` | `λ` |
453
+ | Sort annotations | — | `:Sort` | `:Sort` | — |
454
+ | Equality / comparison | `=` `≠` `<` `>` `≤` `≥` | same | same | same |
455
+ | Arithmetic | `+` `-` `*` `/` | same | same | same |
456
+ | Grouping | `(` `)` `[` `]` | same | same | same |
457
+ | Argument separator | `,` | same | same | same |
422
458
 
423
459
  Whitespace is insignificant and may be used freely between tokens — including before sort annotation colons.
424
460
 
@@ -511,6 +547,14 @@ parser.parse("(λP. P(x))(Q)")
511
547
  → Recommended(x:Patient, y:Treatment)
512
548
  ```
513
549
 
550
+ ### A complete FL example
551
+
552
+ ```text
553
+ ∀x ∀y
554
+ (Effective(y) ⊗ Tolerable(x, y))
555
+ → Recommended(x, y)
556
+ ```
557
+
514
558
  ## AST nodes
515
559
 
516
560
  All nodes are Python dataclasses and can be imported from `unicode_fol_kit`.
@@ -594,6 +638,11 @@ MSFLParser(many_sorted=True).parse("P(x) ∧ Q(x) ∨ R(x)")
594
638
  MSFLParser(many_sorted=True, fuzzy=True).parse("P(x) ∧ Q(x) ⊗ R(x)")
595
639
  # SYNTAX_ERROR: … Hint: Cannot mix weak conjunction (∧), weak disjunction (∨),
596
640
  # strong conjunction (⊗), and strong disjunction (⊕) without parentheses
641
+
642
+ # FL mode — same hint as MSFL (Łukasiewicz connectives, unsorted)
643
+ MSFLParser(many_sorted=False, fuzzy=True).parse("P(x) ∧ Q(x) ⊗ R(x)")
644
+ # SYNTAX_ERROR: … Hint: Cannot mix weak conjunction (∧), weak disjunction (∨),
645
+ # strong conjunction (⊗), and strong disjunction (⊕) without parentheses
597
646
  ```
598
647
 
599
648
  ## Citation
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "unicode-fol-kit"
7
- version = "0.2.0"
7
+ version = "0.2.1"
8
8
  description = "Parser and toolkit for first-order logic formulas using Unicode operators"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -17,7 +17,7 @@ from .fol import (
17
17
  )
18
18
  from .atp import formulas_are_equivalent, check_logical_entailment
19
19
 
20
- __version__ = "0.2.0"
20
+ __version__ = "0.2.1"
21
21
 
22
22
  __all__ = [
23
23
  "MSFLParser",
File without changes