# Appendix: Experimental support for models and counter-examples generation

Alt-Ergo is specialized in program verification, and thus focuses on proving that formulas are **Valid** (**UNSAT**).

However, even in the context of program verification, it may be useful to build *counter-examples*, explaining to the programmer why the formulas are **Invalid**.

In the context of **SAT** (**Invalid** being its negative formulation) this can be interpreted as the construction of a *model* for each formula which is satisfiable.

Alt-Ergo’s support for models and counter-examples is still experimental, but should be extended in future versions.

## Options for model generation

Two options are available to create models/counter-examples.
When alt-ergo is used in command line, they correspond to `--model`

and `--interpretation`

.

Their maximum level are respectively `--model=complete`

and `--interpretation = 3`

.

Using them, here is the kind of output you could get.

Example: No model generation

```
logic x, y: int
goal g:not(
x+y = 8 and
x*y = 12
)
```

Example: Using `model = complete`

```
logic x, y: int
goal g:not(
x+y = 8 and
x*y = 12
)
```

Example: Using `interpretation = 3`

```
logic x, y: int
goal g:not(
x+y = 8 and
x*y = 12
)
```

## Examples

All of the code boxes below have been set up with `interpretation = 3`

.

### Simple equations

Model generation can be used to solve simple equations.

All four examples below come from the fun book “SAT/SMT by example” by Dennis Yurichev.
Don’t hesitate to check his book for more fun applications of SMT-solvers, such as cracking programs using `rand`

, solving nonograms, checking hacks from Henry Warren’s “Hacker’s delight”, or superoptimization.

School-level system of equation

This comes from Yurichev’s 2.2.1, copy pasted from this wikipedia page.

The following code solves this simple system of equations.

```
logic x,y,z:real
goal system: not(
3.*x+2. *y- z = 1. and
2.*x-2. *y+4.*z = -2. and
-x+ .5*y+ z = 0.
)
```

Another school-level system of equations

This comes from Yurichev’s 2.2.2, and was apparently found “somewhere on Facebook”.

The following code solves this system.

```
logic circle, square, triangle: int
goal system: not(
circle + circle = 10 and
circle*square + square = 12 and
circle*square - triangle*circle = circle
)
```

XKCD 287

This comes from Yurichev’s 3.1, inspired by xkcd 287.

```
logic a,b,c,d,e,f:int
axiom positive:
a>=0 and b>=0 and c>=0 and d>=0 and e>=0 and f>=0
goal system: not(
215*a+275*b+335*c+355*d+420*e+580*f=1505
(* Uncomment to find another solution *)
(* and not(a=7 and b=0 and c=0 and d=0 and e=0 and f=0) *)
(* Valid if next line uncommented *)
(* and not(a=1 and b=0 and c=0 and d=2 and e=0 and f=1 *)
)
```

Art of Problem Solving

This comes from Yurichev’s 3.6, inspired by this problem from the Art of Problem Solving.

```
The sum of two nonzero real numbers is 4 times their product.
What is the sum of the reciprocals of the two numbers?
```

```
logic x,y:real
logic res:real
axiom positive:
x>0. and y>0.
axiom result:
res = 1./x + 1./y
goal g:not(
x+y = 4.*x*y
)
```

### Other examples

Primality tester

Strangely enough, Alt-Ergo seems to prove that \(57\), “Grothendieck’s prime”, is not actually prime.

```
logic a,b,n:int
axiom init: n=57
axiom range: 1<=a<=n and 1<=b<=n
goal is_prime:
a*b = n ->
a=1 or b=1
```

Sudoku solver 4*4

This solves the following sudoku puzzle.

```
type one_four = One | Two | Three | Four
logic grid: int, int -> one_four
predicate by_row =
forall i:int. 0<=i<4 ->
distinct(grid(i,0),grid(i,1),grid(i,2),grid(i,3))
predicate by_column =
forall j:int. 0<=j<4 ->
distinct(grid(0,j),grid(1,j),grid(2,j),grid(3,j))
predicate by_square =
forall i,j:int. 0<=i<2 -> 0<=j<2 ->
distinct(grid(2*i,2*j),grid(2*i,2*j+1),grid(2*i+1,2*j),grid(2*i+1,2*j+1))
axiom init:
grid(0,0)=Three and grid(0,1)=Four and grid(0,2)=One and
grid(1,1)=Two and
grid(2,2)=Two and
grid(3,1)=One and grid(3,2)=Four and grid(3,3)=Three
goal g: not
(by_row and by_column and by_square)
```

Sudoku solver 9*9

The following sudoku puzzle has been designed by the Finnish mathematician Arto Inkala, and has been coined “the world’s hardest sudoku” by several newspapers.

Using the following code, Alt-Ergo solves it in about `30 000`

steps, which is ~ \(2\) seconds on a cheap personal computer (not with the in-browser version).

```
type one_nine = One | Two | Three
| Four | Five | Six
| Seven | Eight | Nine
logic grid: int, int -> one_nine
predicate by_row =
distinct(grid(0,0),grid(0,1),grid(0,2),
grid(0,3),grid(0,4),grid(0,5),
grid(0,6),grid(0,7),grid(0,8)) and
distinct(grid(1,0),grid(1,1),grid(1,2),
grid(1,3),grid(1,4),grid(1,5),
grid(1,6),grid(1,7),grid(1,8)) and
distinct(grid(2,0),grid(2,1),grid(2,2),
grid(2,3),grid(2,4),grid(2,5),
grid(2,6),grid(2,7),grid(2,8)) and
distinct(grid(3,0),grid(3,1),grid(3,2),
grid(3,3),grid(3,4),grid(3,5),
grid(3,6),grid(3,7),grid(3,8)) and
distinct(grid(4,0),grid(4,1),grid(4,2),
grid(4,3),grid(4,4),grid(4,5),
grid(4,6),grid(4,7),grid(4,8)) and
distinct(grid(5,0),grid(5,1),grid(5,2),
grid(5,3),grid(5,4),grid(5,5),
grid(5,6),grid(5,7),grid(5,8)) and
distinct(grid(6,0),grid(6,1),grid(6,2),
grid(6,3),grid(6,4),grid(6,5),
grid(6,6),grid(6,7),grid(6,8)) and
distinct(grid(7,0),grid(7,1),grid(7,2),
grid(7,3),grid(7,4),grid(7,5),
grid(7,6),grid(7,7),grid(7,8)) and
distinct(grid(8,0),grid(8,1),grid(8,2),
grid(8,3),grid(8,4),grid(8,5),
grid(8,6),grid(8,7),grid(8,8))
predicate by_column =
distinct(grid(0,0),grid(1,0),grid(2,0),
grid(3,0),grid(4,0),grid(5,0),
grid(6,0),grid(7,0),grid(8,0)) and
distinct(grid(0,1),grid(1,1),grid(2,1),
grid(3,1),grid(4,1),grid(5,1),
grid(6,1),grid(7,1),grid(8,1)) and
distinct(grid(0,2),grid(1,2),grid(2,2),
grid(3,2),grid(4,2),grid(5,2),
grid(6,2),grid(7,2),grid(8,2)) and
distinct(grid(0,3),grid(1,3),grid(2,3),
grid(3,3),grid(4,3),grid(5,3),
grid(6,3),grid(7,3),grid(8,3)) and
distinct(grid(0,4),grid(1,4),grid(2,4),
grid(3,4),grid(4,4),grid(5,4),
grid(6,4),grid(7,4),grid(8,4)) and
distinct(grid(0,5),grid(1,5),grid(2,5),
grid(3,5),grid(4,5),grid(5,5),
grid(6,5),grid(7,5),grid(8,5)) and
distinct(grid(0,6),grid(1,6),grid(2,6),
grid(3,6),grid(4,6),grid(5,6),
grid(6,6),grid(7,6),grid(8,6)) and
distinct(grid(0,7),grid(1,7),grid(2,7),
grid(3,7),grid(4,7),grid(5,7),
grid(6,7),grid(7,7),grid(8,7)) and
distinct(grid(0,8),grid(1,8),grid(2,8),
grid(3,8),grid(4,8),grid(5,8),
grid(6,8),grid(7,8),grid(8,8))
predicate by_square =
distinct(grid(0,0),grid(0,1),grid(0,2),
grid(1,0),grid(1,1),grid(1,2),
grid(2,0),grid(2,1),grid(2,2)) and
distinct(grid(0,3),grid(0,4),grid(0,5),
grid(1,3),grid(1,4),grid(1,5),
grid(2,3),grid(2,4),grid(2,5)) and
distinct(grid(0,6),grid(0,7),grid(0,8),
grid(1,6),grid(1,7),grid(1,8),
grid(2,6),grid(2,7),grid(2,8)) and
distinct(grid(3,0),grid(3,1),grid(3,2),
grid(4,0),grid(4,1),grid(4,2),
grid(5,0),grid(5,1),grid(5,2)) and
distinct(grid(3,3),grid(3,4),grid(3,5),
grid(4,3),grid(4,4),grid(4,5),
grid(5,3),grid(5,4),grid(5,5)) and
distinct(grid(3,6),grid(3,7),grid(3,8),
grid(4,6),grid(4,7),grid(4,8),
grid(5,6),grid(5,7),grid(5,8)) and
distinct(grid(6,0),grid(6,1),grid(6,2),
grid(7,0),grid(7,1),grid(7,2),
grid(8,0),grid(8,1),grid(8,2)) and
distinct(grid(6,3),grid(6,4),grid(6,5),
grid(7,3),grid(7,4),grid(7,5),
grid(8,3),grid(8,4),grid(8,5)) and
distinct(grid(6,6),grid(6,7),grid(6,8),
grid(7,6),grid(7,7),grid(7,8),
grid(8,6),grid(8,7),grid(8,8))
axiom init:
grid(0,0)=Eight and grid(1,2)=Three and grid(2,1)=Seven and
grid(1,3)=Six and grid(2,4)=Nine and
grid(2,6)=Two and
grid(3,2)=Five and
grid(3,5)=Seven and grid(4,4)=Four and grid(4,5)=Five and grid(5,3)=One and
grid(4,6)=Seven and grid(5,7)=Three and
grid(6,2)=One and grid(7,2)=Eight and grid(8,1)=Nine and
grid(7,3)=Five and
grid(6,7)=Six and grid(6,8)=Eight and grid(7,7)=One and grid(8,6)=Four
goal g: not
(by_row and by_column and by_square)
```

The output provided by Alt-Ergo is

```
( (by_row FT:[by_row]) (by_column FT:[by_row]) (by_square FT:[by_row])
((grid 8 6) X5(Sum):[Four])
((grid 6 0) X5(Sum):[Four])
((grid 7 5) X5(Sum):[Four])
((grid 3 7) X5(Sum):[Four])
((grid 1 8) X5(Sum):[Four])
((grid 2 3) X5(Sum):[Four])
((grid 5 1) X5(Sum):[Four])
((grid 4 4) X5(Sum):[Four])
((grid 0 2) X5(Sum):[Four])
((grid 8 4) X5(Sum):[One])
((grid 6 2) X5(Sum):[One])
((grid 7 7) X5(Sum):[One])
((grid 3 8) X5(Sum):[One])
((grid 1 6) X5(Sum):[One])
((grid 2 5) X5(Sum):[One])
((grid 5 3) X5(Sum):[One])
((grid 4 0) X5(Sum):[One])
((grid 0 1) X5(Sum):[One])
((grid 8 3) X5(Sum):[Eight])
((grid 6 8) X5(Sum):[Eight])
((grid 7 2) X5(Sum):[Eight])
((grid 3 6) X5(Sum):[Eight])
((grid 1 5) X5(Sum):[Eight])
((grid 2 7) X5(Sum):[Eight])
((grid 5 4) X5(Sum):[Eight])
((grid 4 1) X5(Sum):[Eight])
((grid 0 0) X5(Sum):[Eight])
((grid 8 5) X5(Sum):[Six])
((grid 6 7) X5(Sum):[Six])
((grid 7 1) X5(Sum):[Six])
((grid 3 4) X5(Sum):[Six])
((grid 1 3) X5(Sum):[Six])
((grid 2 2) X5(Sum):[Six])
((grid 5 0) X5(Sum):[Six])
((grid 4 8) X5(Sum):[Six])
((grid 0 6) X5(Sum):[Six])
((grid 8 7) X5(Sum):[Five])
((grid 6 1) X5(Sum):[Five])
((grid 7 3) X5(Sum):[Five])
((grid 3 2) X5(Sum):[Five])
((grid 1 4) X5(Sum):[Five])
((grid 2 0) X5(Sum):[Five])
((grid 5 6) X5(Sum):[Five])
((grid 4 5) X5(Sum):[Five])
((grid 0 8) X5(Sum):[Five])
((grid 8 1) X5(Sum):[Nine])
((grid 6 5) X5(Sum):[Nine])
((grid 7 6) X5(Sum):[Nine])
((grid 3 3) X5(Sum):[Nine])
((grid 1 0) X5(Sum):[Nine])
((grid 2 4) X5(Sum):[Nine])
((grid 5 8) X5(Sum):[Nine])
((grid 4 2) X5(Sum):[Nine])
((grid 0 7) X5(Sum):[Nine])
((grid 8 0) X5(Sum):[Three])
((grid 6 6) X5(Sum):[Three])
((grid 7 4) X5(Sum):[Three])
((grid 3 1) X5(Sum):[Three])
((grid 1 2) X5(Sum):[Three])
((grid 2 8) X5(Sum):[Three])
((grid 5 7) X5(Sum):[Three])
((grid 4 3) X5(Sum):[Three])
((grid 0 5) X5(Sum):[Three])
((grid 8 8) X5(Sum):[Seven])
((grid 6 4) X5(Sum):[Seven])
((grid 7 0) X5(Sum):[Seven])
((grid 3 5) X5(Sum):[Seven])
((grid 1 7) X5(Sum):[Seven])
((grid 2 1) X5(Sum):[Seven])
((grid 5 2) X5(Sum):[Seven])
((grid 4 6) X5(Sum):[Seven])
((grid 0 3) X5(Sum):[Seven])
((grid 8 2) X5(Sum):[Two])
((grid 6 3) X5(Sum):[Two])
((grid 7 8) X5(Sum):[Two])
((grid 3 0) X5(Sum):[Two])
((grid 1 1) X5(Sum):[Two])
((grid 2 6) X5(Sum):[Two])
((grid 5 5) X5(Sum):[Two])
((grid 4 7) X5(Sum):[Two])
((grid 0 4) X5(Sum):[Two])
)
File "", line 105, characters 9-53:
I don't know (1.9514) (30079 steps) (goal g)
```