Jo Devriendt

## Accessible language

### bool, int, string primitive types

Online editor @ manyworlds.site

``````declare S,E,N,D,M,O,R,Y: -> {0..9}.

1000*S() + 100*E() + 10*N() + D()
+ 1000*M() + 100*O() + 10*R() + E()
//---------------------------------------------
= 10000*M() + 1000*O() + 100*N() + 10*E() + Y().

M() > 0.

distinct(S(),E(),N(),D(),M(),O(),R(),Y()).``````

## Accessible language

declare some 0-arity functions

function that takes arbitrary number of arguments

My mother can understand this. Yours too! :p

write constraints using normal operators

functions

## Accessible language

```= != > < >= =< + - * / % not and or xor implies```

`abs min max count`

`distinct same if-then-else`

Strongly typed and total along bool, int, string

to-do

Builtin functions

## Accessible language

`declare <name>: <type>, <type>, ... -> <finite range>.`

User functions

`declare prime: int -> {true, false}.`

`declare distance: string, string -> {0..1000}.`

`declare cities: string -> bool.`

`declare state: int -> {"busy", "ready", "down"}.`

`declare edge_color: string, string -> {"r", "g", "b"}.`

signature

all ranges have a clear type, but are finite no int or string

`declare n: -> {0..9}.`

## Accessible language

``````declare color: string -> {"r", "g", "b", "y"}.

color("NL") != color("BE").
color("NL") != color("DE").
color("BE") != color("LU").
color("BE") != color("DE").
color("BE") != color("FR").
color("FR") != color("LU").
color("FR") != color("DE").
color("LU") != color("DE").``````

### Map coloring 1

There must be a better way...

## Accessible language

``````declare color: string -> {"r", "g", "b", "y"}.

declare border: string, string -> bool.

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

all [ color(x)!=color(y) for x,y where border(x,y) ].``````

### Map coloring 2

definition fixes meaning of function

FMF expression

total definition

compiling / flattening / unrolling / grounding / instantiating
yields previous disequalities

## Accessible language

### FMF expressions

``max(f(1), f(2), f(3))``
``````all
any
none
count
sum
product
min
max
distinct
same
odd
even``````
``````and
or
not( or )
count
+
*
min
max
distinct
same
xor
not( xor )``````
``max [ f(x) for x where x in {1..3} ]``

## Accessible language

``all [ color(x)!=color(y) for x,y where border(x,y) ].``

### FMF expressions

Filter: select all `x,y` where `border(x,y)` holds

Fold: reduce those `color(x)!=color(y)` to `true` iff `all` are `true`

Map: map those `x,y` to `color(x)!=color(y)`

## Accessible language

``all [ color(x)!=color(y) for x,y where border(x,y) ].``

### FMF expressions

list comprehension

aggregate function converting list to one expression

## Accessible language

### FMF expressions

Flexible!

``````sum [
weight(x)
for x where Item(x) and inKnapsack(x)
] <= capacity().``````

Captures global constraints and global functions.

``````distinct [
color(x)
for x where Country(x) and not color(x)="r"
].``````

"allDiff except 0"

## Accessible language

``````decdef num as {1..9}.

declare cell: int,int -> num.

all [
distinct [ cell(r,c) for c where num(c) ]
for r where num(r) ].
all [
distinct [ cell(r,c) for r where num(r) ]
for c where num(c) ].

declare square: int,int,int -> bool.

define square as ...

all [
distinct [ cell(r,c) for r,c where square(r,c,s)]
for s where num(s) ].

define cell as ...``````

## Accessible language

### FMF expressions

Circuit constraint in TSP

``````decdef City as {"city_" 1..n}.

declare next: string -> City.

declare order: string -> {1..n}.

order("city_1") = 1.

all [ order(next(x)) = order(x) + 1
for x where City(x) and next(x) != "city_1" ].``````

## Accessible language

``````decdef City as {"city_" 1..n}.

declare next: string -> City.

declare order: string -> {1..n}.

order("city_1") = 1.

all [ order(next(x)) = order(x) + 1
for x where City(x) and next(x) != "city_1" ].``````

### FMF caveat: compiler must derive finite instantiation from "where" block

City limits instantations of x as it is a finite set of strings.

## Accessible language

### bool, int, string primitive types

Online editor @ manyworlds.site

## Solve combinatorial problems

### find a consistent world

``````FOUND WORLD

color as {("DE","b"), ("BE","g"), ("FR","r"), ("LU","y"), ("NL","r")}.
``````
``````declare color: string -> {"r", "g", "b", "y"}.

declare border: string, string -> bool.

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

all [ color(x)!=color(y) for x,y where border(x,y) ].``````

## Solve combinatorial problems

### debug no consistent world

``````FOUND BLOCKERS
Line 9: not color("BE")=color("DE")
Line 9: not color("BE")=color("FR")
Line 9: not color("BE")=color("LU")
Line 9: not color("DE")=color("FR")
Line 9: not color("DE")=color("LU")
Line 9: not color("FR")=color("LU")``````
``````declare color: string -> {"r", "g", "b", "y"}.

declare border: string, string -> bool.

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

all [ color(x)!=color(y) for x,y where border(x,y) ].``````

NL is not involved, as it only borders two other countries

## Solve combinatorial problems

### optimize over all worlds

``minimize sum [ distance(x,next(x)) for x where City(x) ].``

find a world now returns

• optimal world
• optimal objective value
• "optimization blockers"

## Solve combinatorial problems

``````declare man: string -> bool.
declare mortal: string -> bool.

all [ man(x) implies mortal(x)
for x where
x in {"Socrates","Athens","poison cup","Zeus"}
].

man("Socrates").
not mortal("Zeus").``````
``````FOUND INTERSECTION

man as {("Socrates",true), ("Zeus",false)}.

mortal as {("Socrates",true), ("Zeus",false)}.``````

## Performance

### BIG to-do

Goal

Means

• C++
• Exact
• strong compilation

### Pipeline

1. fix parsing
2. desugar
3. simplify
4. instantiate
5. simplify
6. unnest 1
7. simplify
8. merge
9. unnest 2

Bad: in each step, full expression tree is rebuilt...

Good: minimal set of compiled constraints

## Motivation

Combinatorial programming is simpler than imperative programming. Why are the languages so hard?

Successful when a 12-year old can do their math homework with ManyWorlds and when a lawyer can recognize ManyWorld-encoded laws.

Caveat: no silver bullet!
But simple problems should have simple solutions.

Problem domain description should match code.

## Usability

• No order on expressions
• e.g., use a function before you declare it
• Deterministic
• syntax mistakes
• compilation errors
• blockers
• Online editor
• No limit on integer type
• Syntax highlighting (to-do)
• Good documentation and tutorials (... to-do)
• ...

## Relation to CPMpy

Both focus on

• ease of use
• flexibility
• solver independence
• explanations

Differences

• library vs system
• expressivity of language

Summer 2024:

Stateful ManyWorlds with Python interface. New backend? ;)

## Little directionality

``sum [ distance(x,next(x)) for x where City(x) ]``
• order of expressions does not matter
• (almost) no distinction between parameters and variables

• even definitions can be used backwards
``````declare fib: int -> {0..1e21}.

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.``````
``````declare fib: int -> {0..1e21}.
declare a,b: -> {0..10}.

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

fib(10)=144.``````

By Jo Devriendt

• 99