Combinatorial programming made simple

2023-07-18

Jo Devriendt

Performance

  • C++ implementation, Exact backend solver
  • responsiveness
    • 60 'edges' (Joost): 18.1s IDP vs 0.7s MW
    • 12 'concretes' (Simon): 3.7s IDP - 0.5s MW
  • speed of propagation inference
    • TODO: find showcase application
    • That's why we're meeting ;)

Motivation

Simplicity

  • minimum of concepts for users to learn
  • syntax close to familiar (programming) languages
  • ease of use (e.g., informative error messages, fewer pitfalls, ...)

Resources

Map coloring example

declare border: string, string -> bool.
define border as {("BE","NL"),("BE","FR"),("BE","LU"),("BE","DE"),
                 ("LU","FR"),("LU","DE"),("NL","DE"),("FR","DE")} else false.
  
declare color: string -> {"r","g","b","y"}.
  
all[color(x)!=color(y) for x,y where border(x,y)].
vocabulary V {
  type country := {BE,NL,FR,LU,DE}
  border: country * country -> Bool
  type rgby := {r,g,b,y}
  color: country -> rgby
}

theory T:V {
  ! (x,z) in border: color(x)~=color(z).
}

structure S:V {
  border := {(BE,NL),(BE,FR),(BE,LU),(BE,DE),(LU,FR),(LU,DE),(NL,DE),(FR,DE)}.
}
vocabulary V {
  type digit := {0..9}
  L: () -> digit
  E: () -> digit
  S: () -> digit
  F: () -> digit
  O: () -> digit
  D: () -> digit
  I: () -> digit
  T: () -> digit
}
theory T:V {
  L() * 1000 + E() * 100 + 11 * S() + F() * 1000 + O() * 110 + D() = 
  D() * 1000 + I() * 100 + E() * 10 + T().
  L()~=E() & L()~=S() & L()~=F() & L()~=O() & L()~=D() & L()~=I() &  L()~=T().
  E()~=S() & E()~=F() & E()~=O() & E()~=D() & E()~=I() & E()~=T().
  S()~=F() & S()~=O() & S()~=D() & S()~=I() & S()~=T().
  F()~=O() & F()~=D() & F()~=I() & F()~=T().
  O()~=D() & O()~=I() & O()~=T().
  D()~=I() & D()~=O() & D()~=T().
  I()~=O() & I()~=T().
  O()~=T().
  L()~=0 & F()~=0 & D()~=0.
}
structure S:V { }

LESS + FOOD = DIET

declare L,E,S,F,O,D,I,T: -> {0..9}.

1000*L() + 100*E() + 10*S() + S() +
1000*F() + 100*O() + 10*O() + D() =
//---------------------------------
1000*D() + 100*I() + 10*E() + T() .

L()>0. F()>0. D()>0.

distinct(L(),E(),S(),F(),O(),D(),I(),T()).

LESS + FOOD = DIET

  • Less advanced language constructs
    • types (TODO)
    • floating point numbers (TODO)
    • inductive definitions (TODO)
    • constructed types
    • partial functions ...
       
  • tooling
    • tutorial (TODO)
    • syntax highlighting (TODO)
    • interactive consultant
    • cDMN ...

Drawbacks

Long term (2023+)

  • multiplication/division/modulo
  • floating point numbers
  • inductive/recursive definitions
  • "first class" tuples
  • enterprise edition
  • ...

To Do

Short term (2023)

  • types
  • documentation, tutorial
  • count inference
  • memory use
  • runtime efficiency
  • syntax highlighting,
    auto completion
  • Windows build
  • ...

 But ManyWorlds is "good enough" to be put to the test!

Translator FO(.) <-> MW

?

Declarations

All functions are total.

Predicates are simply function symbols mapping to bool

(or {true, false})

declare border: string, string -> bool.
declare <id list> : <list of int/bool/string> -> <finite range>

Every symbol is a function symbol mapping to a finite range

declare color: string -> {"r","g","b","y"}.  
declare L,E,S,F,O,D,I,T: -> {0..9}.

Constraints

  • Expressions are (nested) terms
  • Well-typed according to basic types:
  • Simplest terms are values:
     
  • Operators:

     
  • Builtin function symbols:
     
  • Qauntifiers and aggregates:
bool, int, string
true, false, -1, 0, 1, "", "Alice", ...
+, -, *, not, and, or, xor, =, !=, >=, >, <=, <, 
... implies ..., ... if ... else ...
min, max, abs, distinct, same, count
<id> [<term> for <variable id list> where <term>]
all[color(x)!=color(y) for x,y where border(x,y)].
all[color(x)!=color(y) for x,y where border(x,y)].
sum[value(x) for x where Item(x) and inKnapsack(x)].

Definitions

define <id or term> as <definition> else <default value>

All definitions will define total functions, so default is used to cover the remaining cases

define border as {("BE","NL"),("BE","FR"),("BE","LU"),("BE","DE"),
                 ("LU","FR"),("LU","DE"),("NL","DE"),("FR","DE")} else false.

Enumeration:

Classic definition:

define fib(x) as
  0 if x=0 else
  1 if x=1 else
  fib(x-1) + fib(x-2)
where x in {0..100} else 0.

General

  • All statements end with a '.'
  • C-style comments:
    • // this is a line comment
    • /* this is a multiline
      comment */
  • Inference (solve, intersect) is given at command line.