PAP course

Damien Lejosne

2026 - 03 - 23

Introduction

Contexte

PB : Comment vérifier qu’un logiciel fonctionne ?

Pourquoi :

Comment :

Exemple de bugs connus : …

Méthodes formelles : Raisonnement rigoureux, parfois exhaustif, et (semi) automatisé pour garantir l’absence de bugs.

On a aussi utilisé des méthodes “informelles”. Ça passe mal à l’échelle.

Et les méthodes 100% automatiques n’existent pas (indécidabilité de Riesz).

Il y a donc différents niveaux d’automatisation :

Méthode Spécification Preuve Verdict
Preuve assistée par ordi Manuelle, avec HOL Semi manuelle QED / ?
Preuve automatique Semi manuelle, logique ordre 1 Automatique QED / inf / ?
Analyse statique Automatique Automatique QED / ?
Modèle checking Formule en logique temporelle Automatique QED / Contre Exemple

(F* : types incluent logique d’ordre 1)

Dans ce cours

Objectifs

Compétences Développées Prérequis
Spécifier & prouver + ++
Algorithmique ++ + (SAT)
Programmation ++ + (OCaml)
Sémentique langages + (SEM)
Preuve par induction ++ + (ind)
Théorie des modèles ++ + (L3)

Format

Cours

CM / TD / TP mélangés

Évaluation

Biblio

Séance 1 : Logique de programme

Prouver qu’un programme est correct nécessite de spécifier ce que correct signifie.

Exemple :

s = 0
k = 0
while k < N:
    s += k
    k += 1

Que fait ce programme ? Il calcule la somme des N - 1 premiers entiers : 0 + ... + (N - 1) = N (N - 1).

SI N \geq 0 !

Il faut faire attention aux préconditions…

Ici, on va utiliser plusieurs outils.

Notation de Hoare

Informellement, \left< P \right> c \left< Q \right> signifie :

Si on exécute le programme c en partant d’un état initial vérifiant l’état P, alors la post condition Q est vérifiée à la fin de l’exécution, si c termine.

RQ : Il s’agit de correction partielle : ça fonctionne si c termine.

On peut aussi utiliser un critère plus fort de correction totale :

[P] c [Q] signifie la même chose, avec la garantie en plus que c termine sur l’exécution à partir d’état initiaux satisfaisant P.

Exemples :

# x & y des references
def swap(x,y):
    z = x
    x = y
    y = z

Triplet de hoare correspondant :

\left<x = a \land y = b \right> swap \left< x = b \land y = a \right>

Avec a et b des variables “fantômes” non libre dans la commande.

Syntaxe

Un mini langage impératif

c ::= skip
| x := t
| c1; c2
| if t then c1 else c2
| while t do c

On dit que t est un terme, par exemple : x y z 1 3.14 -x -(x+1) sin(x)

Les assertions

Rappels de logique

F ::= <atome>
| not F
| F1 and F2
| F1 or F2
| F1 => F2
| F1 <=> F2
| exists x. F
| forall x. F

Exercice :

Si, \left< P1 \right> c \left< Q1 \right> et \left< P2 \right> c \left< Q2 \right>, Peut on affirmer :

Correction : Les deux sont vraies.

Séance 2 : Logique de Hoare, formalisée

Triplets de Hoare

La logique de Hoare est un sytème déductif de logique de programme. On la définit inductivement (les formules suivantes sont vraies) :

Programmes annotés

Pour éviter d’avoir à écrire des triplets \left< P \right> c \left< Q \right>, et les arbres de dérivations correspondant, on va annoter les programmes avec des assertion intermédiaires.

Exemple :

<y = a> => <I[0/x]>
x := 0
<I>
while y > 0 do
    <I /\ y > 0> => <I[(x+1)/x][(y+1)/y]>
    y := y - 1
    <I[(x+1)/x]>
    x := x + 1
    <I>
<I /\ not y > 0> => <x = a \/ a < 0>

On va définir la syntaxe suivante pour ces programmes “augmentés” :

d ::= skip<Q>
| x := e<Q>
| d; d
| if b do <P1> c1 else <P2> c2 <Q>
| while b do <P> c <Q>
| => <P> d
| d => <Q>

dc ::= <P> d

On définit par ailleurs les 3 fonctions eff, pre et post suivantes, définit inductivement :

eff(<P> d) = eff(d)
eff(skip <Q>) = skip
eff(x := e <Q>) = x := e
eff(while b do <P> c Q) := while b do eff(c)


pre(<P> d) = P

post(<P> d) = post(d)
post(skip <Q>) = Q
post(while b do <P> c <Q>) = Q
post(c1; c2) = post(c2)

L’intuition est que \left< P \right> d est valide ssi \left< P \right> \text{eff}(d) \left< \text{post}(Q) \right>.

\left< P \right> d est dit valide ssi P \vdash d avec \cdot \vdash \cdot définit inductivement par :

RQ : Ce système est totalement dirigé par la syntaxe <3

Mais : Correction, completude… ?

Correction et complètude des programmes annotés dans la logique de Hoare

Correction : Si \left< P \right> d est valide alors \left< P \right> \text{eff}(d) \left< \text{post}(d) \right>

Preuve :

On procède par induction sur d.

On note \mathbf{P}(d) := \forall P, \left< P \right> d \implies \left< P \right> \text{ eff}(d) \left< \text{ post}(d) \right>

Principe d’induction :

Si :

Alors \forall d, \mathbf{P}(d).

Retour à la preuve :

On traite uniquement le cas ‘skip’ ici :

Soit d_1, d_2, supposons que \mathbf{P}(d_1) et \mathbf{P}(d_2).

Soit P tq P \vdash d_1;d2.

Montrons que \left< P \right> \text{eff}(d_1);\text{eff}(d_2) \left< \text{post}(d_2) \right>

  1. Si P \vdash d_1 alors \left< P \right> \text{eff}(d_1) \left< \text{post}(d_1) \right>
  2. Si \text{post}(d_1) \vdash d_1 alors \left< \text{post}(d_1) \right> \text{eff}(d_2) \left< \text{post}(d_2) \right>
  3. Si P \vdash d_1 et \text{post}(d_1) \vdash d_2 : par 1) + 2), on conclut avec la règle de la séquence de \cdot \vdash \cdot.

Complétude :

La proposition suivante est vraie \forall P,c,Q :

\mathbf{P}(P, c, Q) :=
“Si \left< P \right> c \left< Q \right>, il existe d tel que :

  1. \text{eff}(d) = c
  2. \text{post}(d) = Q
  3. P \vdash d

On fait la preuve par induction sur \left< P \right> c \left< Q \right>.

Principe d’induction :

Si :

  1. \forall A, \mathbf{P}(A,\text{skip},A)
  2. \forall I, b, c, si \mathbf{P}(I \land b,c,I) alors \mathbf{P}(I, \text{while } b \text{ do } c, I \land \lnot b).
  3. \forall P, P', Q, Q', c, si \models P \implies P' \land \models Q' \implies Q \land \mathbf{P}(P',c,Q'), alors \mathbf{P}(P, c, Q)

Alors : \forall P, c, Q, \left< P \right> c \left< Q \right> \implies \mathbf{P}(P,c,Q).

Retour à la preuve (uniquement le cas 5) :

  1. Appelons d' tq c=\text{while } b \text{ do } c'

    1. \text{eff}(d') = c'
    2. \text{post}(d') = I
    3. I \land b \vdash d'

    Considérons d = \text{while } b \text{ do } \left< I \land b \right> d' \left< I \land \lnot b' \right>. Il vérifie :

    1. \text{eff}(d) = \text{while } b \text{ do } \text{eff}(d') = c
    2. \text{post}(d) = I \land \lnot b
    3. I \vdash d d’après la règle du while

Exo : Annoter le programme suivant de sorte à ce qu’il soit valide :

<y >= 0>

p := 0

k := 1

while k <= y do

    p := p+x

    k := k + 1
done

<p = x*y>

Correction :

<y >= 0>
=> <I[1/k]> *
p := 0
k := 1
<I:= p = (k-1)*x /\ k <= y+1>
while k <= y do
    <I and k <= y>
    => <I[(k+1)/k][(p+x)/p]> **
    p := p+x
    <I[(k+1)/k]>
    k := k + 1
    <I>
done
<I /\ not k <= y>
=> <p = x*y> ***

* : \models y \geq 0 \implies 0 = (1-1)w \land 1 \leq y + 1 \square

** : \models I \land k \leq y \implies p+x=((k+1)-1)x \land k+1 \leq y + 1 \square

*** : I \land \lnot k \leq y \implies p = k x \square

Séance 3 : Obligations de preuves

\rightarrow Repartons de la logique IMP, en modifiant la structure du while.

c ::= ... | <I> while b do c

et la règle associée devient :

\left< I \land b \right> c \left< I \right> \rightarrow \left< I \right> \text{while } b \text{ do } c \left< \left< I \right> I \land \lnot b \right>

Construisons maintenant une formule PO(P,c,Q) telle que : \models PO(P,c,Q) \iff \left< P \right> c \left< Q \right>

Calculons d’abors la “meilleure” précondition pour c et Q donné :

VC (Verification Condition) :

Ce qui nous donne :

PO(P, c, Q = P \implies pre(c,Q) \land VC(c,Q)

Correction: Si \models PO(P,c,Q) alors \left< P \right> c \left< Q \right>

Preuve :

On procède par induction sur c :

Complétude: Si \left< P \right> c \left< Q \right> Alors \models PO(P,c,Q)

On le prouve à l’aide de 2 lemmes intermédiaires :

Complétude 1: Si \left< P \right> c \left< Q \right> Alors \models P \implies pre(c,Q)

Preuve par induction sur \left< P \right> c \left< Q \right> :

Complétude 2: Si \left< P \right> c \left< Q \right> Alors \models P \implies VC(c,Q)

Encore une fois, on procède par induction sur \left< P \right> c \left< Q \right> :

Séance 4 : Solveurs SMT

Notations

(CF cours de logique aussi).

T \models F signifie, F est valide (universellement) dans la théorie T.

On appelle théorie des axiomes (sous forme close), et une signature (symboles de fonctions et de prédicats).

La théorie vide n’a pas d’axiomes, et une infinité de symboles.

Solveurs SAT

On appelle problème SAT le pb consistant en :

Ce pb est NP complet.

Cependant, les solveurs SAT résolvent des pb à en gros 100 variables et 1000 clauses en quelques minutes.

Naivement, on pourrait essayer de faire du brute force avec une table de vérité… Mais c’est mauvais même en pratique.

DPLL

Il s’agit de l’algorithme de Davis–Putnam–Logemann–Loveland. Il procède par backtracking et usage d’heuristiques.

Fonctionnement

On se donne un état, consistant en une pile de couples (littéral, statut décidé / propagé) (on peut le voir comme un modèle partiel).

À chaque étape, l’algorithme va assigner une valeur au littéral courant, simplifier la formule et vérifier si elle est satisfiable. Si c’est le cas, il renvoit vrai, sinon, il backtrack, jusqu’à avoir parcouru l’ensemble des possibles.

Par rapport à un backtracking classique, DPLL va appliquer à chaque étape les actions suivantes de sorte à optimiser les performances :

On peut le formaliser de la manière suivante sous forme de transitions avec la pile :

  1. Décide : M \rightarrow M l^D si l \not \in M \land \lnot l \not \in M
  2. Prop Unitaire (l) : M \rightarrow M l si : \exists C \lor l \in F, M \models \lnot C \land l \not \in M \land \lnot l \not \in M.
  3. Backtrack : M l^D N \rightarrow M \lnot l si \exists C \in F, M l^D N \models \lnot C, et N n’a pas de littéraux de décision.
  4. Fail : M \rightarrow UNSAT, si M n’a pas de décision et M \models \lnot F
  5. Success : M \rightarrow SAT si M \models F

Avec la notation : l^D signifie : on est en train de décider le littéral l.

RQ : Il reste un partie difficile… C’est de faire 2) efficacement.

CDCL (Conflict Driven Clause Learning)

Cet algorithme est souvent plus efficace dans l’ellagage que DPLL.

Il se base sur le même principe que DPLL, mais par rapport à ce dernier :

Ce qui nous donne :

  1. Décide (l) : M, F \rightarrow M l^D, F si …
  2. Backjumping (C, l') : M l^D N, F \rightarrow M l', F \land (C \lor l') si F \models C \lor l' et M \models \lnot C.

RQ 1 : Truc difficile : Comment choisir C ? CF cours logique L3.

RQ 2 : On peut séparer la règle de Backjump en 2 :

Exemple d’application :

\begin{aligned} F &= (c_1 := a \lor b)\\ &\land (c_2 := a \lor \lnot b)\\ &\land (c_3 := \lnot a \lor c \lor d)\\ &\land (c_4 := \lnot a \lor c \lor \lnot d)\\ &\land (c_5 := \lnot a \lor \lnot c \lor d)\\ &\land (c_6 := \lnot a \land \lnot c \lor \lnot d)\\ &\end{aligned}

M F Règle
\emptyset F \text{Decide} (a)
a^D F \text{Decide} (c)
a^D c^D F \text{UnitProp} (c_5, d)
a^D c^D d F \text{BackJump} (\lnot a, \lnot c)
a^D \lnot c F \land (c_7 := \lnot a \lor \lnot c) \text{UnitProp} (c_3, d)
a^D \lnot c d F \land c_7 \text{BackJump} (\top, \lnot a)
\lnot a F \land c_7 \land (c_8 := \lnot a) \text{UnitProp} (c_1, b)
\lnot a b \text{UNSAT} \text{Fail} (c_2)

FOL (First Order Logic) sans quantificateurs ?

Solveur de théorie : pour répondre au pb, \left< F | T \models F \right>

Notation : / Q : Quantifiée. / QF : pas quantifiée.

Théorie Décidable ? Complexité RQ
FOL NON
Eq / Q NON Théorie de l’égalité
Eq / QF OUI ~ linéaire
EUF / Q NON Eq + Congruence : \forall xny, x = y \implies f x = f y
EUF / QF OUI n \log n
Peano NON
Presburger OUI NP complet (peano sans le *)
Réels OUI O(2^{2^k |F|})
Arithméique Linéaire Rationelle OUI O(2^n) (simplex) (+, -, =, \leq, sur \mathbb{Q})
Tableaux* / Q NON =, store, get
Tableaux* / QF OUI NP complet =, store, get

* : 3 axiomes :

Combiner solveur SAT et solveur de théories ?

On se base sur des formules CNF : il existe une transformation linéaire (de Tseitin) qui transforme une formule F en une formule CNF F_{CNF} qui lui est équisatisfiable.

Combinaison EAGER

Exemple :

\begin{aligned} F &= (P := g(a) = c)\\ &\land ((\lnot Q := f(g(a))) \neq f(c)) \lor (M := g(a = d))\\ &\land (\lnot S := c \neq d) \end{aligned}

On utilise une abstraction booléenne :

D’où : \alpha(F) := p \land q \land (\lnot q \lor r) \land \lnot s

On ajoute alors les contraintes encodant (partiellemen) les axiomes de la théorie (ici EUF) :

Et on donne au solveur SAT : H_1 \land H_2 \land \alpha(F), qui prouve UNSAT.

Combinaison LAZY

On conserve l’idée d’abstraction booléenne \alpha, mais on va chercher à avoir une interaction plus fine.

Lazy “simple”

On introduit la transformation inverse de \alpha, \gamma (aussi appelée concrétisation).

Exemple : On reprend celui de la combinaison eager.

M_1 := p \land \lnot q \land \lnot r \land \lnot s

\gamma (M_1) := g(a) = c \land f(g(a)) \neq f(c) \land g(a) \neq d \land c \neq d

Mais un SAT solveur ne donne en général qu’un modèle booléen dans le cas SAT. Pour le forcer à tout donner, on peut :

Si il nous donne un modèle M, ajouter \lnot M à la formule, et recommencer jusqu’à UNSAT.

DPLL (T) e.g DPLL modulo Théorie

RQ : On peut aussi (évidemment) utiliser CDCL.

On crée une boucle d’instanciation entre DPLL et le solveur de théorie.

RQ : Ce tableau ce lit de gauche à droite, de bas en haut. On peut voir ça de la manière suivante :

Et cela jusqu’à ce que DPLL soit UNSAT.

DPLL EUF
\alpha(F) = p \land (\lnot q \lor r) \land \lnot s p \land q \land \lnot s, puis via \gamma : g(a) = c \land f(g(a)) \neq f(c) \land c \neq d, puis via EUF UNSAT : g(a) = c \land f(g(a)) \neq f(c) =: p \land \lnot q
F_ 1 = F \land (\lnot p \lor q) p \land q \land r \land \lnot s =: M_3, puis via \gamma : … puis via EUF UNSAT : g(a) = c \land g(a) = d \land c \neq d =: p r s
F_2 = F_1 \land (\lnot p \lor \lnot r \lor s ) qui est UNSAT : fin

Plus précisément :

Cela nous donne les règles suivante pour notre algorithme :

Règle Transition Condition
\text{Decide}(l) (M,F) \rightarrow (Ml^D, F) l indéfini dans M
\text{UnitProp}(C,l) (M,F) \rightarrow (Ml, F) C \lor l \in \alpha(F), M \models \lnot C, l indéfini dans M
\text{Learn}(C) (M,F) \rightarrow (M, F \land \gamma(C)) \alpha(F) \models C
\text{Backjump}(C, l') (M_1 l^D M_2,F) \rightarrow (M_1 l', F) C \lor l' \in \alpha(F), M_1 \models \lnot C, l' indéfini dans M
\text{Fail}(C) (M,F) \rightarrow \text{UNSAT} C \in \alpha(F), M \models \lnot C, M sans décision, \gamma(M) \models_T \lnot \gamma(C)
$ (M,F) \rightarrow \text{SAT} M \models \alpha(F), \gamma(M) est T - \text{SAT}
\text{T - Conflict}(C) (M,F) \rightarrow (M, F \land C) \models_T C, M \models \lnot \alpha(C)
\text{T - Propagation}(l) (Optimisation) (M,F) \rightarrow (Ml, F) \gamma(M) \models_T \gamma(l), l indéfini dans M

Exemple (on reprend la formule F) :

Trace de \text{DPLL}(T) :

M F Transition Condition
\emptyset F \text{UnitProp}(C_1, p)
p F \text{UnitProp}(C_3, \lnot s)
p \lnot s F \text{T-Propagate}(q) \gamma(p \land \lnot s) \models \gamma (q)
p \lnot s q F \text{UnitProp}(C_2, r) M \models q
p \lnot s q r F \land C_3 \text{UnitProp}(C_1, p) M \models \alpha(\lnot (C_4^T := \gamma(\lnot p \lor \lnot q \lor s))), \models C_4
p \lnot s q r F \land C_4^T \text{Fail}(C_4^T), C_4 = \alpha(C_4^T) C_4 \in \alpha(F \land C_4^T), M \models \lnot C_4, M sans décision, \gamma(M) \models_T \lnot \gamma(C_4)

RQ : Les règles de Backjump et Fail n’ont pas besoin de T-solveur, car on sait déjà : M \models \lnot C.

Le T-solveur n’est utilise que T-propagate et T-conflict.

Reprenons par ailleurs l’exemple, sans T-propagate pour montrer l’optimisation qu’elle apporte.

M F Règle Justification
\emptyset F \text{UnitProp}(C_1, p)
p F \text{UnitProp}(C_4, \lnot s)
p \lnot s F \text{Decide}(\lnot q)
p \lnot s (\lnot q)^D F \text{T-conflict}() \gamma(p \land \lnot s \land \not q) \equiv g(a) = c \land c \neq d \land f(g(a)) \neq f(c), donc C_4^T=g(a) \neq c \lor f(g(a)) = f(c), et \models_T C_4^T, M \models \lnot p \lor q, C_4 = \alpha(C_4^T)
p \lnot s {\lnot q}^D F \land C_4^T \text{Backjump}(\lnot p, q) C = \lnot p, p \models \lnot C, C \in F \land C
p \lnot s q F \land C_4^T \text{UnitProp}(C_2, r) C \in F \land C
p \lnot s q r F \land C_4^T \text{T-conflict}() C_5^T = \gamma(C_5), C_5 = \lnot p \lor \lnot a \lor s, \models_T C_5^T, M \models C_5
p \lnot s q r F \land C_4^T \land C_5^T \text{Fail}(C_5^T) M \models \lnot C_5

RQ : On ne peut cependant pas se passer de T-conflict.

Conclusion

Séance 5 : Théorie de l’égalité

On a vu que dans un SMT solveur, on s’intéressait à combiner un SAT solveur avec un solveur de théorie.

Aujourd’hui, on va s’intéresser à une théorie particulière, la théorie EUF (Equality + Uninterpreted Functions).

Théorie EUF

Langage EUF :

Exemple de formules : \forall x,y, f(x) = g(y) \implies g(x) = f(y)

Ici, on se restreint à QFEUF (Quantifier Free EUF).

Axiomes d’EUF :

Un monome est une formule CNF de EUF.

Procédure de décision pour SAT QFEUF

Idée : On recherche la cloture par congruence de égalités du monome c’est à dire la plus petite relation de congruence qui contient ces égalités.

Structure d’equity graph (e-graph)

Ingrédients :

On appelle e-graph un graphe orienté biparti G = ((N,C), E).

Ses sommets sont bipartis en N l’ensemble des e-nodes et C l’ensemble des e-classes.

Un e-graph G = ((N,C), E) représente un ensemble de termes Rep(G) :

RQ : Un terme t \in Rep(G) est représenté par une unique e-classe et un unique e-node.

Algorithmique des E Graphes

Un e-graphe affiche l’interface suivante :

Séance 6 : Instanciation des quantificateurs

Idée : On essaie de se ramener à des formules sans quantificateurs ?

Dans certaines théorie, il existe une procédure pour transformer toute formule \Phi en une formule \tilde{\Phi} équisatisfiable. Ces procédures n’existe pas dans le cas général, et sont souvent couteuses en calculs.

Cependant, pour montrer qu’une formule quantifiée est UNSAT, on peut juste exiber un contre exemple. Autrement trouver une instatiation des variables quantifiées qui la transforme en formule non quantifiée UNSAT, ce qui est calculable. On va donc essayer, dans la suite, de trouver une “bonne” instantiation.

On commence par se placer dans un cas d’étude restreint :

On considère les formules de la forme Q \land UQ est une conjonction de formules avec quantificateurs et U est une CNF à formules sans quantificateurs.

On le fait sans perte de généralité.

Mise en forme des formules quantifiées

Dans Q on élimine les implications et on pousse les négations aux feuilles.

Gestion des \exists

Pour toute sous formule existencielle \exists x, \Phi(x) dans Q, on skolémise : On introduit un nouveau symbole e_x dans le langage et on remplace \exists x, \Phi(x) par \Phi(e_x).

/!\ : \forall x, \exists y, P(x,y) devient : \forall x, P(x, f_y(x))

Cela nous donne une formule équisatisfiable (cf cours de logique du premier ordre).

Gestion des \forall

Mise sous forme PCNF (Prenex CNF).
- On renomme les variables liées au \forall pour que chaque \forall ait sa variable unique.
- On fait remonter les \forall à la racine de la formule. - On obtient ainsi une formule équisatisfiable \forall x, y, z, ..., \Phi(x,y,z,...). On met \Phi en forme CNF.

Résultat

On se ramène à une formule Q \land UU est une CNF sans quantificateurs (appelée faits de base) et Q est une conjonction de formules PCNF (on pourrait juste avoir une PCNF, mais pas très utile) appelée les universelles.

On va donc devoir utiliser un moteur d’instantiation pour tenter d’instancier les variables quantifiées universellements, pour la satisfiabilité :

Principe de communication entre moteur d’instantiation, SAT et SMT solveurs

Défi : Comment trouver les instanciations pertinentes ?

E-matching

Le procédé de matching : recherche dans U des instanciations pour nos déclencheur.

En pratique, on stocke U dans un e-graph (car les théorie sont souvent dotées de la congruence).

Les e-graph proposent alors une opération nommée e-matching, adaptée à la recherche d’instanciations de déclencheurs.

Notations :

Soit c \in C une e-clause et v une substitution. On dit que c,v est une occurence de p dans l’e-graph si :

\{ p(t_x, ..., t_y) | \forall y \in Free(p), t_y \in Rep(\sigma(y)) \} \subseteq Repr(c)

Procédé d’e-matching :

Séance 7 : Théorie de l’arithmétique linéaire (Simplexe)

Ici, on va s’intéresser à des formules particulières :

On cherche à résoudre le problème suivant :

T_{LRA} := \{F | F_{SAT}\}

Ce problème est polynomial par programmation linéaire, d’après Dantzig (1947).

Problème en forme normale

On peut toujours représenter une instance de T_{LRA} par M = (A,B,N,(e_i), (u_i)) avec :

telle que :

F \in T_{LRA} équivalent à l’existence d’ube solution pour le problème S_M suivant :

Algorithme itératif

On défini un état de l’algorithme par :

Invariants :

On prend l’algorithme suivant :

L’état initial est \beta(_) = 0.

Tant que exists x_i in B, tq beta(x_i) < e_i ou beta(x_i) > u_i :
    SI on détecte S_M = vide : Renvoie UNSAT
    SINON : choisir x_j in N tel que :
        (M', beta') = PIVOT(M, beta, x_i, x_j)
        M', beta' satisfait (I_1) et (I_2) et S_M = vide <=> S_m' = vide

L’invariant est initialement vrai.

Démo :

Exemple :

N = \{x, y\}, B = \{s_1, s_2, s_3\}, \beta = 0

1er test de boucle :

\rightarrow \beta ne satisfait pas 2 \leq \beta(s_1). On veut “augmenter” \beta(s_1) jusqu’à 2, et on va permuter s_1 et x dans B et N.

Pivot de Gauss :

On exprime x en fonction de s_1 :

(M, \beta) \leftarrow (M', \beta').

2e test de boucle :

\rightarrow il faut augmenter \beta(s_3) : -2 \rightarrow^{+3} 1

En augmentant \beta(y) de 1 :

Pivot de Gauss :

s_3 \leftrightarrow y

Alors :

Donc B = \{x, s_2, y\}, N = \{s_1, s_3\}

3e test de boucle :

FIN : F est SAT pour x = 1, y = 1

Séance 8 : Combinaison de théorie Nelson-Oppen

Motivation

Considérons F = (A_1 := f(f(x) - f(y))) \neq f(z) \land x < z \land y + z \leq x \land 0 \leq z

On se situe dans la théorie des fonctions non interprétées, donc pas LRA, et pas EUF car il n’y pas que des inégalités.

La méthode de Nelson Oppen permet alors de créer une théorie que l’on peut utiliser pour résoudre ce problème, en en réutilisant (et plus précisément en en combinant) des déjà connues. La théorie finale utilisée sera la théorie union.

/!\ : Limitation : Les théories considérées doivent être à signature disjointe.

Purification

Sépare F en sous formules pures.

Soit F une conjonction de littéraux sur la signature \Sigma_1 \cup \Sigma_2 avec \Sigma_1 \cap \Sigma_2 = \{ = \}

On appelle purification de F les deux conjonctions :

telles que F et F_1 \land F_2 soient équisatisfiables.

Procédé :

La purification peut se faire de la manière suivante. Pour chaque sous terme de T_1 qui apparait dans un terme de T_2, on instancie une variable fraiche et une égalité.

Exemple sur le F de la motivation :

  1. On introduit u pour f(x)
  2. On introduit v pour f(y)
  3. On introduit l’égalité u = f(x) \in EUF
  4. On introduit l’égalité v = f(y) \in EUF
  5. On introduit l’égalité w = u - v \in LRA
  6. A_1 devient f(w) \neq f(z) \in EUF.

Le reste ne change pas, on obtient donc :

Algorithme

On peut alors créer un algorithme résolvant notre problème initial :

Représentation schématique de l’algorithme de Nelson-Oppen
Nelson-Oppen(F):
    F1,F2 <- Purification(F)
    T1.assume(F1)
    T2.assume(F2)
    Tant que T1.sat() ou T2.sat() :
        Si il existe i,x,y tq Ti.propagate() equiv x=y:
            j <- 2 - i
            Tj.assume(x = y)
        Sinon renvoie SAT
    renvoie UNSAT

Exemple :

Étape EUF LRA
0 u = f(x), v = f(y), f(w) \neq f(z) w = u - v, x \leq y, y + z \leq x, 0 \leq z
1 déduit x = y
2 reçoit x = y
3 déduit u = v
4 reçoit u = v
5 déduit w = z
6 reçoit w = z, UNSAT

Pour montrer la correction et la complètude de cet algorithme, on introduit la notion de convexité de théorie :

Une théorie T est dite convexe si, pour toute conjonction de littéraux F et toute disjonction d’égalité \lor_{i=1}^n x_i = y_i :

Si F \models_T D, alors \exists i, F \models_T x_i = y_i

Exemples :

Si les théories T_1(\Sigma_1) et T_2(\Sigma_2) vérifient :

  1. \Sigma_1 \cap \Sigma_2 = \{ = \}
  2. T_1 et T_2 sont stablement infinies, càd toute conjonction de littéraux T_i SAT admet un modèle infini.
  3. Convexité : T_1 et T_2 sont convexes.

Alors Nelson-Oppen est correct et complet.

Exemple de théorie non totalement infinie :

Assertions de la logique de séparation

Points-to

E \mapsto F est vraie dans l’état (s,h) ssi :

E,s \Downarrow l \in Loc F,s \Downarrow v \in Val

dom(h) = \right< l \left>, h(l) = v

Tas vide : emp

(s, h) \models emp ssi h est vide.

Conjonction séparante

P \ast Q est vraie dans (s,h) ssi il existe deux tas h_1 et h_2 tels que :

Remarque : emp est neutre pour \ast.

On notera aussi : E \mapsto F_0, ..., F_n \equiv E \mapsto F_0 \ast E + 1 \mapsto F_1 \ast ... \ast E + n \mapsto F_n

Application aux listes chainées

Soit \alpha une liste mathématique dans \cup_n Exp^n.

On définit de manière inductive (s, l) \models list(\alpha, e) :

MAIN WEBPAGE