lynxql 0.1.3

A parser for the Lynx declarative modeling language - a statically typed language for expressing combinatorial optimization problems
Documentation
// Line Comment
/* Block Coment */

// Boolean variable declaration 
x = Bool()

// Integer variable declaration (y \in {0, 1, 2, 3, 4, 5}) 
y = Integer(0, 5)

// Shorthand for variable declaration (z \in {-2, -1, 0, 1})
z = -2..1

// Composite variable declaration
a = All(x, y, z)

// Finding a solution to "a"
solA = maximize({ x=1.0 }, a)

// Checking that we got expected values by indexing a's subvariables x, y and z
// Note that All(x, y, z) is equivalent to x + y + z >= 1+5+1, e.i geq to the sum of their upper bounds
assert(solA[0] == 1..1)
assert(solA[1] == 5..5)
assert(solA[2] == 1..1)

// Lynx TYPES and ATTRIBUTES
// primitive type declarations
// @ marks that the member is an attribute
type Color : Bool { @tag : str, }
type Wheel : Bool { @tag : str, @weight : float }

// Example instantiation of a custom type
color1 = Color(tag="example color")

// primitive type declaration with Integer
type Week : Integer<0, 52> { @dates: str }

// Example instantiation of an Integer custom type
springWeeks = Week<14, 26>(dates="april-june")

// Example of "not ok" instantiation of Integer custom type
notOkSpringWeeks = Week<-4, 24>(dates="dont know") // Since -4..24 is outside of parent domain

// Composite type declaration. All logical combinators are allowed to use when the type has relationships to other variable types.
// It is not ok to combine a Bool custom type with a relationship member, or, a composite custom type with only attribute members.
type Price : All {
    
    // No @ means a relationship. Here colors and wheel are joint on All logical combinator.
    colors : Any[Color],
    wheel  : Wheel,
    
    // @ means an attribute. Here we say that Price has an float attribute "price".
    @price : float,
}

// Type alias. Just a pointer to a specific type (including type arguments)
alias ColorRule = Exactly<1>[Color]
alias WheelRule = Exactly<1>[Wheel]

// composite
type Bicycle : All {
    colors      : ColorRule,
    wheels      : WheelRule,
    prices      : Free[Price],

    // Lambdas are ok to use when the property is calculated on call. Compilator will make sure the correct type is returned (i hope)
    @totalPrice : float = (Bicycle b) -> sum(b.prices.price),
}

// data declarations
red   = Color(tag = "red")
front = Wheel(tag = "front", weight = 3.2)

price1 = Price(colors = Any(red), wheel = front, price = 150)

// compile-time sets of "red colors" and "front wheels"
// "*" means the full context, i.e. it contains all variables throughout the program
aRed   = filter(*, c -> c.tag == "red")
frontW = filter(*, w -> w.tag == "front")

// Instantiating a Bicycle with red colors, front wheels and a price
myBike = Bicycle(
    colors = ColorRule(...aRed), // "..." means that the set is expanded into arguments
    wheels = WheelRule(...frontW),
    prices = Free(price1),
)

alias Week = Integer<1,52>
productionWeek = Week(4,32)

solution = minimize(
    objective = myBike.totalPrice,
    suchThat  = All(
        // The solution must be a valid Bicycle
        myBike,
        // Constraints on the production week 
        productionWeek >= 12,
        productionWeek <= 26,
    ),
)

chosenColour = solution.colors.firstTrue()