> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stateset.com/llms.txt
> Use this file to discover all available pages before exploring further.

# NSR-L Language Reference

> Prolog-inspired logic programming language for symbolic reasoning, constraint specification, and knowledge representation in AI systems.

# NSR-L Language Reference

**NSR-L** (Neuro-Symbolic Reasoning Language) is a Prolog-inspired logic programming language designed for symbolic reasoning, constraint specification, and knowledge representation in AI systems.

## Table of Contents

1. [Overview](#overview)
2. [Lexical Elements](#lexical-elements)
3. [Terms](#terms)
4. [Logical Expressions](#logical-expressions)
5. [Statements](#statements)
6. [Operators](#operators)
7. [Built-in Predicates](#built-in-predicates)
8. [List Operations](#list-operations)
9. [Arithmetic](#arithmetic)
10. [Constraints](#constraints)
11. [Negation](#negation)
12. [Quantifiers](#quantifiers)
13. [Comments](#comments)
14. [Complete Grammar](#complete-grammar)
15. [Examples](#examples)

***

## Overview

NSR-L combines classical logic programming with modern features for AI guardrails:

* **First-order logic** with variables, predicates, and quantifiers
* **Prolog-style rules** with `Head :- Body` syntax
* **Classical and non-monotonic negation** (`~` and `\+`)
* **Hard and soft constraints** for flexible validation
* **Arithmetic evaluation** with the `is` operator
* **List operations** for data manipulation
* **Belief revision** with confidence intervals

### Hello World

```prolog theme={null}
% Facts
human(socrates).
human(plato).

% Rules
mortal(X) :- human(X).

% Query
?- mortal(socrates).
```

***

## Lexical Elements

### Atoms

Atoms are constant identifiers. They must start with a lowercase letter or be quoted.

```prolog theme={null}
% Unquoted atoms (start with lowercase)
hello
customer_service
product123
x

% Quoted atoms (any characters)
'Hello World'
'contains spaces'
'special-chars!'
```

### Variables

Variables start with an uppercase letter or underscore.

```prolog theme={null}
X              % Regular variable
Name           % Descriptive variable
CustomerID     % CamelCase variable
_              % Anonymous variable (matches anything, not bound)
_Unused        % Named but intentionally unused
```

**Important:** Variables starting with `_` suppress singleton variable warnings.

### Numbers

```prolog theme={null}
42             % Integer
-17            % Negative integer
3.14           % Float
-0.5           % Negative float
1.0e10         % Scientific notation
```

### Strings

```prolog theme={null}
"hello world"           % Double-quoted string
"contains \"quotes\""   % Escaped quotes
"line1\nline2"          % Escape sequences
```

***

## Terms

Terms are the fundamental data structures in NSR-L.

### Constants

```prolog theme={null}
atom           % Atom constant
42             % Integer constant
3.14           % Float constant
"string"       % String constant
```

### Variables

```prolog theme={null}
X              % Unbound variable
_              % Anonymous variable
```

### Compound Terms (Functors)

```prolog theme={null}
person(john, 30)                    % Functor with arguments
node(left(a), right(b))             % Nested structure
pair(X, Y)                          % With variables
address(city("NYC"), zip(10001))    % Complex nesting
```

### Lists

Lists use square bracket notation with `|` for head/tail decomposition.

```prolog theme={null}
[]                        % Empty list
[a, b, c]                 % List of atoms
[1, 2, 3]                 % List of integers
[X, Y, Z]                 % List of variables
[Head | Tail]             % Head/tail decomposition
[A, B | Rest]             % First two elements + rest
[[1,2], [3,4]]            % Nested lists
```

***

## Logical Expressions

### Atomic Propositions

```prolog theme={null}
predicate(arg1, arg2, ...)
```

Examples:

```prolog theme={null}
human(socrates)
parent(tom, mary)
age(john, 30)
product(wide_awake, eye_cream)
```

### Conjunction (AND)

Use `&` or `,` for conjunction:

```prolog theme={null}
human(X) & mortal(X)          % Using &
human(X), mortal(X)           % Using ,
parent(X, Y) & parent(Y, Z)   % Grandparent pattern
```

### Disjunction (OR)

Use `|` or `;` for disjunction:

```prolog theme={null}
male(X) | female(X)           % Using |
cat(X) ; dog(X)               % Using ;
```

### Implication

```prolog theme={null}
Head :- Body                  % Prolog-style rule
human(X) -> mortal(X)         % Arrow notation
A <-> B                       % Biconditional (iff)
```

### Negation

```prolog theme={null}
~positive(X)                  % Classical negation (strong)
\+ found(X)                   % Negation as failure (weak)
not(present(X))               % Alternative NAF syntax
```

***

## Statements

NSR-L programs consist of three types of statements:

### Facts

Facts are ground assertions (no variables, or universally quantified).

```prolog theme={null}
human(socrates).
product(wide_awake, eye_cream).
return_window_days(30).
prohibited_phrase("contact the manufacturer").
~ships_internationally.           % Negative fact
```

### Rules

Rules define logical implications with head and body.

```prolog theme={null}
% Basic rule
mortal(X) :- human(X).

% Rule with conjunction
grandparent(X, Z) :- parent(X, Y) & parent(Y, Z).

% Rule with disjunction
animal(X) :- cat(X) | dog(X) | bird(X).

% Rule with negation
eligible(X) :- member(X) & ~suspended(X).

% Rule with comparison
adult(X) :- age(X, Age) & Age >= 18.

% Complex rule
response_valid(R) :-
    ~response_invalid(R) &
    ~contains_internal_reasoning(R) &
    ~promises_replacement(R).
```

### Queries

Queries ask the system to prove or find solutions.

```prolog theme={null}
?- mortal(socrates).              % Yes/no query
?- parent(X, mary).               % Find X
?- ancestor(X, Y).                % Find all pairs
?- age(john, Age), Age > 18.      % Query with condition
```

***

## Operators

### Logical Operators

| Operator | Meaning             | Example                 |
| -------- | ------------------- | ----------------------- |
| `&`      | Conjunction (AND)   | `a(X) & b(X)`           |
| `,`      | Conjunction (AND)   | `a(X), b(X)`            |
| `\|`     | Disjunction (OR)    | `a(X) \| b(X)`          |
| `;`      | Disjunction (OR)    | `a(X) ; b(X)`           |
| `~`      | Classical negation  | `~alive(X)`             |
| `\+`     | Negation as failure | `\+ found(X)`           |
| `not`    | Negation as failure | `not(found(X))`         |
| `->`     | Implication         | `human(X) -> mortal(X)` |
| `:-`     | Rule implication    | `head :- body`          |
| `<->`    | Biconditional       | `a <-> b`               |

### Comparison Operators

| Operator     | Meaning              | Example       |
| ------------ | -------------------- | ------------- |
| `=`          | Unification          | `X = foo`     |
| `\=`         | Not unifiable        | `X \= Y`      |
| `==`         | Identical            | `X == Y`      |
| `\==`        | Not identical        | `X \== Y`     |
| `<`          | Less than            | `X < 10`      |
| `>`          | Greater than         | `X > 0`       |
| `=<` or `<=` | Less or equal        | `X =< 100`    |
| `>=`         | Greater or equal     | `X >= 0`      |
| `=:=`        | Arithmetic equal     | `X + 1 =:= Y` |
| `=\=`        | Arithmetic not equal | `X =\= 0`     |

### Arithmetic Operators

| Operator     | Meaning          | Example   |
| ------------ | ---------------- | --------- |
| `+`          | Addition         | `X + Y`   |
| `-`          | Subtraction      | `X - Y`   |
| `*`          | Multiplication   | `X * Y`   |
| `/`          | Division         | `X / Y`   |
| `//`         | Integer division | `X // Y`  |
| `mod` or `%` | Modulo           | `X mod Y` |

### Operator Precedence (lowest to highest)

1. `:-`, `->`, `<->`
2. `;`, `|`
3. `,`, `&`
4. `\+`, `not`, `~`
5. `=`, `\=`, `<`, `>`, `=<`, `>=`, `=:=`, `=\=`
6. `+`, `-`
7. `*`, `/`, `//`, `mod`
8. Unary `-`

***

## Built-in Predicates

### Unification & Comparison

```prolog theme={null}
X = Y                  % Unify X and Y
X \= Y                 % X and Y do not unify
X == Y                 % X and Y are identical
X \== Y                % X and Y are not identical
```

### Type Checking

```prolog theme={null}
atom(X)                % X is an atom
number(X)              % X is a number
integer(X)             % X is an integer
float(X)               % X is a float
compound(X)            % X is a compound term
is_list(X)             % X is a list
var(X)                 % X is unbound
nonvar(X)              % X is bound
ground(X)              % X contains no variables
```

### Arithmetic Evaluation

```prolog theme={null}
X is Expr              % Evaluate Expr and bind to X

% Examples:
Sum is 2 + 3.          % Sum = 5
Prod is X * Y.         % Prod = X * Y
Mod is 17 mod 5.       % Mod = 2
```

### Arithmetic Functions

```prolog theme={null}
abs(X)                 % Absolute value
min(X, Y)              % Minimum
max(X, Y)              % Maximum
sqrt(X)                % Square root
X ** Y                 % Power (X^Y)
sin(X), cos(X), tan(X) % Trigonometric
log(X), exp(X)         % Logarithm, exponential
floor(X), ceiling(X)   % Rounding
round(X)               % Round to nearest integer
```

### Control

```prolog theme={null}
!                      % Cut (commit to current choice)
true                   % Always succeeds
false                  % Always fails
fail                   % Always fails
```

***

## List Operations

NSR-L provides Prolog-standard list predicates.

### member/2

Check if element is in list, or enumerate elements.

```prolog theme={null}
member(X, [a, b, c])           % X = a; X = b; X = c
member(b, [a, b, c])           % true
member(d, [a, b, c])           % false
```

### append/3

Concatenate lists or split a list.

```prolog theme={null}
append([1,2], [3,4], Result)   % Result = [1,2,3,4]
append(X, [4,5], [1,2,3,4,5])  % X = [1,2,3]
append(X, Y, [a,b,c])          % Generate all splits
```

### length/2

Get or check list length.

```prolog theme={null}
length([a,b,c], N)             % N = 3
length(L, 5)                   % L = [_,_,_,_,_]
```

### reverse/2

Reverse a list.

```prolog theme={null}
reverse([1,2,3], R)            % R = [3,2,1]
```

### nth0/3, nth1/3

Access element by index.

```prolog theme={null}
nth0(0, [a,b,c], X)            % X = a (0-indexed)
nth1(1, [a,b,c], X)            % X = a (1-indexed)
nth0(Index, [a,b,c], b)        % Index = 1
```

### last/2

Get last element.

```prolog theme={null}
last([a,b,c], X)               % X = c
```

### sort/2, msort/2

Sort lists.

```prolog theme={null}
sort([3,1,2,1], S)             % S = [1,2,3] (removes duplicates)
msort([3,1,2,1], S)            % S = [1,1,2,3] (keeps duplicates)
```

### sumlist/2

Sum numeric elements.

```prolog theme={null}
sumlist([1,2,3,4], Sum)        % Sum = 10
```

### flatten/2

Flatten nested lists.

```prolog theme={null}
flatten([[1,2],[3,[4,5]]], F)  % F = [1,2,3,4,5]
```

### permutation/2

Generate or check permutations.

```prolog theme={null}
permutation([1,2,3], P)        % P = [1,2,3]; P = [1,3,2]; ...
```

***

## Arithmetic

### The `is` Operator

Evaluates arithmetic expressions and binds result.

```prolog theme={null}
X is 2 + 3.                    % X = 5
Y is X * 2.                    % Y = 10
Z is sqrt(16).                 % Z = 4.0
```

### Arithmetic Comparisons

```prolog theme={null}
X < Y                          % X less than Y
X > Y                          % X greater than Y
X =< Y                         % X less than or equal to Y
X >= Y                         % X greater than or equal to Y
X =:= Y                        % X arithmetically equal to Y
X =\= Y                        % X arithmetically not equal to Y
```

### Examples

```prolog theme={null}
% Check if adult
adult(Person) :-
    age(Person, Age),
    Age >= 18.

% Calculate discount
final_price(Product, Price) :-
    base_price(Product, Base),
    discount(Product, Percent),
    Price is Base * (100 - Percent) / 100.

% Factorial (recursive)
factorial(0, 1).
factorial(N, F) :-
    N > 0,
    N1 is N - 1,
    factorial(N1, F1),
    F is N * F1.
```

***

## Constraints

NSR-L supports hard, soft, and weighted constraints for validation.

### Constraint Types

| Type         | Behavior                       | Use Case                           |
| ------------ | ------------------------------ | ---------------------------------- |
| **Hard**     | Violation = rejection          | Prohibited phrases, security rules |
| **Soft**     | Violation = confidence penalty | Style guidelines, recommendations  |
| **Weighted** | Contributes to score           | Optimization objectives            |

### Defining Constraints in Rules

```prolog theme={null}
% Hard constraint: Never say prohibited phrases
response_invalid(R) :-
    prohibited_phrase(P) &
    contains_text(R, P).

% Soft preference: Include link when relevant
should_include_link(R, Link) :-
    topic_detected(R, Topic) &
    required_link(Topic, Link) &
    ~contains_text(R, Link).
```

### Constraint API (HTTP)

```json theme={null}
{
  "id": "no_prohibited_phrases",
  "description": "Response must not contain prohibited phrases",
  "strength": {"type": "hard"},
  "expression": "~violates_prohibited_phrase(Response, Phrase)",
  "source": "domain_rule"
}
```

***

## Negation

NSR-L supports two forms of negation:

### Classical Negation (`~`)

Strong negation that asserts the opposite is true.

```prolog theme={null}
~alive(X)                      % X is definitely not alive
~ships_internationally.        % Definitely does not ship internationally
```

### Negation as Failure (`\+` or `not`)

Weak negation - true if the goal cannot be proven.

```prolog theme={null}
\+ found(X)                    % X was not found (maybe doesn't exist)
not(member(X, L))              % X is not provably in L
```

### Difference

```prolog theme={null}
% Classical: We know X is not alive
~alive(zombie).

% NAF: We cannot prove X is alive (doesn't mean X is dead)
\+ alive(X).
```

### Closed World Assumption

NAF follows the closed-world assumption: if something cannot be proven true, it is assumed false.

```prolog theme={null}
% Database only has:
employee(alice).
employee(bob).

% Query: Is carol an employee?
?- employee(carol).        % Fails (no fact)
?- \+ employee(carol).     % Succeeds (NAF)
?- ~employee(carol).       % Fails (no explicit negative fact)
```

***

## Quantifiers

NSR-L supports first-order quantifiers.

### Universal Quantification (forall)

```prolog theme={null}
forall X (human(X) -> mortal(X))
```

Equivalent rule form:

```prolog theme={null}
mortal(X) :- human(X).         % Implicitly forall X
```

### Existential Quantification (exists)

```prolog theme={null}
exists X (person(X) & rich(X))
```

Can be expressed as:

```prolog theme={null}
has_rich_person :- person(X), rich(X).
```

### Scoping

```prolog theme={null}
% All humans have some parent
forall X (human(X) -> exists Y parent(Y, X))

% There exists someone who is everyone's friend
exists X forall Y friend(X, Y)
```

***

## Comments

### Line Comments

```prolog theme={null}
% This is a line comment
human(socrates).  % Inline comment
```

### Multi-line Comments (block style in code)

```prolog theme={null}
% ==============================================================================
% SECTION HEADER
% ==============================================================================
%
% Multiple lines of explanation.
% Each line starts with %.
%
% ==============================================================================
```

***

## Complete Grammar

### EBNF Grammar

```ebnf theme={null}
program     = { statement } ;

statement   = fact | rule | query ;

fact        = expression "." ;

rule        = expression ":-" expression "." ;

query       = "?-" expression "." ;

expression  = disjunction ;

disjunction = conjunction { ( "|" | ";" ) conjunction } ;

conjunction = unary { ( "&" | "," ) unary } ;

unary       = "~" unary
            | "\+" unary
            | "not" "(" expression ")"
            | "forall" variable "(" expression ")"
            | "exists" variable "(" expression ")"
            | comparison ;

comparison  = arithmetic [ comp_op arithmetic ] ;

comp_op     = "=" | "\=" | "==" | "\=="
            | "<" | ">" | "=<" | "<=" | ">="
            | "=:=" | "=\=" | "is" ;

arithmetic  = term { ( "+" | "-" ) term } ;

term        = factor { ( "*" | "/" | "//" | "mod" | "%" ) factor } ;

factor      = [ "-" ] primary ;

primary     = atom [ "(" args ")" ]
            | variable
            | number
            | string
            | list
            | "(" expression ")"
            | "!" ;                         (* cut *)

args        = expression { "," expression } ;

list        = "[" [ list_items ] "]" ;

list_items  = expression { "," expression } [ "|" expression ] ;

atom        = lowercase { alphanumeric | "_" }
            | "'" { any_char } "'" ;

variable    = uppercase { alphanumeric | "_" }
            | "_" { alphanumeric | "_" } ;

number      = integer | float ;

integer     = [ "-" ] digit { digit } ;

float       = [ "-" ] digit { digit } "." digit { digit } [ exponent ] ;

exponent    = ( "e" | "E" ) [ "+" | "-" ] digit { digit } ;

string      = '"' { string_char } '"' ;

string_char = any_char_except_quote | '\\"' | "\\n" | "\\t" | "\\\\" ;

lowercase   = "a" | ... | "z" ;

uppercase   = "A" | ... | "Z" | "_" ;

digit       = "0" | ... | "9" ;

alphanumeric = lowercase | uppercase | digit ;
```

***

## Examples

### Example 1: Family Relationships

```prolog theme={null}
% Facts
parent(tom, mary).
parent(tom, jim).
parent(mary, ann).
parent(mary, pat).
parent(jim, bob).

male(tom).
male(jim).
male(bob).
male(pat).

female(mary).
female(ann).

% Rules
father(X, Y) :- parent(X, Y) & male(X).
mother(X, Y) :- parent(X, Y) & female(X).

grandparent(X, Z) :- parent(X, Y) & parent(Y, Z).

ancestor(X, Y) :- parent(X, Y).
ancestor(X, Y) :- parent(X, Z) & ancestor(Z, Y).

sibling(X, Y) :- parent(P, X) & parent(P, Y) & X \= Y.

% Queries
?- father(tom, X).          % X = mary; X = jim
?- grandparent(tom, X).     % X = ann; X = pat; X = bob
?- sibling(mary, X).        % X = jim
```

### Example 2: Customer Service Rules

```prolog theme={null}
% Products
product(wide_awake, eye_cream).
product(skin_glow_primer, primer).
has_mini(skin_glow_primer).
~has_mini(wide_awake).

% Prohibited phrases
prohibited_phrase("contact the manufacturer").
prohibited_phrase("30-40 pumps").

% Validation rules
response_invalid(R) :-
    prohibited_phrase(P) &
    contains_text(R, P).

response_valid(R) :-
    ~response_invalid(R) &
    ~contains_internal_reasoning(R).

% Escalation rules
requires_escalation(allergic_reaction).
requires_escalation(skin_irritation).

should_escalate(Topic) :-
    requires_escalation(Topic) &
    detected_topic(Topic).

% Topic detection
topic_detected(Inquiry, returns) :-
    contains_text(Inquiry, "return") |
    contains_text(Inquiry, "refund").

topic_detected(Inquiry, allergic_reaction) :-
    contains_text(Inquiry, "allergic") |
    contains_text(Inquiry, "rash").
```

### Example 3: Arithmetic and Lists

```prolog theme={null}
% Sum of list
sum([], 0).
sum([H|T], S) :- sum(T, S1), S is H + S1.

% List length
len([], 0).
len([_|T], N) :- len(T, N1), N is N1 + 1.

% Maximum in list
max_list([X], X).
max_list([H|T], Max) :-
    max_list(T, MaxT),
    Max is max(H, MaxT).

% Filter positive numbers
filter_positive([], []).
filter_positive([H|T], [H|R]) :- H > 0, filter_positive(T, R).
filter_positive([H|T], R) :- H =< 0, filter_positive(T, R).

% Quicksort
quicksort([], []).
quicksort([H|T], Sorted) :-
    partition(H, T, Less, Greater),
    quicksort(Less, SortedLess),
    quicksort(Greater, SortedGreater),
    append(SortedLess, [H|SortedGreater], Sorted).

partition(_, [], [], []).
partition(Pivot, [H|T], [H|Less], Greater) :-
    H =< Pivot, partition(Pivot, T, Less, Greater).
partition(Pivot, [H|T], Less, [H|Greater]) :-
    H > Pivot, partition(Pivot, T, Less, Greater).
```

### Example 4: Belief Revision and Constraints

```prolog theme={null}
% Initial beliefs with confidence
belief(human(socrates), 1.0).
belief(philosopher(socrates), 1.0).
belief(lived_in(socrates, athens), 0.95).

% Derived rules
mortal(X) :- human(X).
wise(X) :- philosopher(X).

% Hard constraint: Cannot live in two places at once
~valid_kb :-
    lived_in(X, Place1) &
    lived_in(X, Place2) &
    Place1 \= Place2 &
    overlapping_time(Place1, Place2).

% Soft constraint: Philosophers usually teach
expected(teaches(X)) :- philosopher(X).

% Query with explanation
?- mortal(socrates).
% Result: true
% Explanation: mortal(socrates) via human(socrates)
```

***

## Error Messages

NSR-L provides helpful error messages with source locations:

```
error: Unexpected ')' after expression
  --> 3:15
   |
3  | mortal(X) :- human(X)).
   |              ^^^^^^^^^
   = help: Check for unbalanced parentheses
```

### Common Errors

| Error                    | Cause                     | Fix                                        |
| ------------------------ | ------------------------- | ------------------------------------------ |
| `Singleton variable 'X'` | Variable used only once   | Rename to `_X` or use it                   |
| `Unexpected token`       | Syntax error              | Check operators and parentheses            |
| `Unbound variable`       | Variable not instantiated | Ensure variable is bound before arithmetic |
| `Division by zero`       | Arithmetic error          | Add guard: `Y \= 0`                        |
| `Wrong arity`            | Wrong number of arguments | Check predicate definition                 |

***

## API Endpoints

| Endpoint               | Method | Purpose                           |
| ---------------------- | ------ | --------------------------------- |
| `/api/v1/nsrl/parse`   | POST   | Parse NSR-L code (syntax check)   |
| `/api/v1/nsrl/assert`  | POST   | Add facts/rules to knowledge base |
| `/api/v1/nsrl/execute` | POST   | Execute queries                   |
| `/api/v1/nsrl/prove`   | POST   | Prove entailment                  |
| `/api/v1/nsrl/retract` | POST   | Remove facts/rules                |

### Example API Call

```bash theme={null}
curl -X POST "$BASE_URL/api/v1/nsrl/execute" \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "human(socrates). mortal(X) :- human(X). ?- mortal(X).",
    "persist": false
  }'
```

***

## Best Practices

### 1. Use Descriptive Predicate Names

```prolog theme={null}
% Good
customer_eligible_for_discount(C) :- ...

% Avoid
ced(C) :- ...
```

### 2. Handle Edge Cases

```prolog theme={null}
% Always handle empty list
process([], []).
process([H|T], Result) :- ...
```

### 3. Use Anonymous Variables

```prolog theme={null}
% When you don't need the value
has_child(X) :- parent(X, _).
```

### 4. Document with Comments

```prolog theme={null}
% Calculate final price after applying all discounts
% Precondition: base_price(Product, Price) exists
% Returns: Final price after discounts
final_price(Product, Final) :- ...
```

### 5. Avoid Infinite Recursion

```prolog theme={null}
% Bad: left recursion
ancestor(X, Y) :- ancestor(X, Z), parent(Z, Y).

% Good: base case first
ancestor(X, Y) :- parent(X, Y).
ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y).
```

***

## Related Documentation

* [YSE Beauty API Workflow](./yse_beauty_api_workflow.md) - Practical examples
* [Temporal Agent Orchestration](./temporal_agent_orchestration.md) - Integration guide
* [Recursive Policy Learning](./recursive_policy_learning.md) - Self-improving rules
