lynxql 0.1.0

A parser for the Lynx declarative modeling language - a statically typed language for expressing combinatorial optimization problems
Documentation

🦊 Lynx Language

Lynx is a declarative modeling language for defining and solving combinatorial optimization problems using Integer Linear Programming (ILP). It allows users to define types, relationships, properties, and optimization goals in a concise and expressive syntax designed specifically for logic-based, constraint-driven models.

✨ Key Features

  • Declarative syntax — no loops, no side effects
  • Strong typing with support for primitive and composite types
  • Expressive constraint and logic composition using built-ins like All, Any, AtLeast, Not, etc.
  • Full support for find, match, sum, solve, and other built-in functions
  • ILP-compatible: all model logic must compile to a linear formulation

📦 Example

// Demonstrates use of match to compute a value based on logic

type Hammer: bool {
  material: string,
  size: int,
  cost: float
}

type Toolbox: All {
  hammers: Any[Hammer],
  weight: int = (t: Toolbox) -> match(t, {
    Any(find((h: Hammer) -> h.material == "steel")): 10,
    Any(find((h: Hammer) -> h.material == "wood")): 7,
    _: 5
  })
}

type Size: int

type Hammer: bool {
  material: string,
  size: Size,
  cost: float
}

type Nail: bool {
  length: int,
  amount: int,
  cost: float
}

type Toolbox: All {
  hammers: AtLeast<1>[Hammer] = (_) -> find((h: Hammer) -> h.size >= 8),
  nails: Any[Nail]?,
  boxType: BoxType
}

type Carpenter: All {
  name: string,
  age: int,
  workable: bool = (c: Carpenter) -> c.age >= 18,
  toolbox: Toolbox,
  salery: float = (c: Carpenter) ->
    +sum(c.toolbox.hammers.cost)
    +sum(c.toolbox.nails, 0.0)
    -20000.0
}

Hammer hammer1 { material: "steel", size: 10 }
Nail nail1 { length: 5, amount: 100 }

Carpenter john {
  name: "John Doe",
  age: 30,
  workable: true,
  toolbox: Toolbox {
    hammers: AtLeast<1> { hammer1 },
    nails: Any { nail1 },
    boxType: BoxType { width: 30, height: 20, depth: 15 }
  }
}

a_solution = solve(john, { nail1: 1.0 }, { Not { hammer1 } })

🧠 Language Concepts

🧱 Type Declarations

  • Primitive types (e.g., bool, int, float) can have additional metadata.
  • Composite types use logical constructors like All, Any, Exactly, etc. to express relationship constraints.
type Product: All {
  options: Exactly<1>[Option],
  price: float = (p: Product) -> sum(p.options.price)
}

🔗 Relationships

Relationships are declared with logical and cardinality operators:

  • All[T] – all connected instances must be satisfied
  • Any[T] – at least one must be satisfied
  • Exactly<N>[T] – exactly N instances must be selected
  • Optional relationships use ? after the type (e.g. Any[Nail]?)

🪮 Computed Properties

Properties can be computed using pure, side-effect-free lambda expressions:

cost: float = (t: Toolbox) -> sum(t.hammers.cost)

🔍 Find & Filter

Use find((x: Type) -> condition) to dynamically match instances:

find((n: Nail) -> n.length >= 10)

🧲 Match & Logic

Use match for piecewise logic:

weight: int = match(t, {
  Any(find((h: Hammer) -> h.material == "steel")): 10,
  Any(find((h: Hammer) -> h.material == "wood")): 7,
  _: 5
})

🚀 Solving

The solve function initiates optimization over a variable with:

  • a weighted objective
  • a set of constraints
solve(john, { nail1: 1.0 }, { Not { hammer1 } })

📜 Design Constraints

Lynx compiles to Integer Linear Programs, which means:

  • ❌ No loops
  • ❌ No recursion
  • ❌ No nonlinear math (e.g. x * y, x / y)
  • ✅ All functions must return linear-compatible results
  • ✅ All expressions are deterministic and pure

🔧 Built-in Functions

Function Description
solve(...) Optimize an instance with objective and constraints
find(...) Select instances based on filter
sum(...) Add numeric values over a collection
propagate(...) Forward-evaluate logical implications
match(...) Piecewise logic mapping
first(...) Get the first element from a list

📃 File Format

Lynx files use the .lynx extension. The parser supports:

  • Single-line comments: // comment
  • Multi-line comments: /* block comment */

📚 Learn More


💠 Roadmap

  • Static linearity checker
  • VSCode syntax extension
  • Type and shape inference
  • Partial evaluation and result caching