Satisfiability Modulo Theories
Lecture 9 - Extending OpenSMT for fun and profit∗
(slides revision: Saturday 14th
March, 2015, 11:47)
Roberto Bruttomesso
Seminario di Logica Matematica
(Corso Prof. Silvio Ghilardi)
22 Dicembre 2011
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 1 / 22
Outline
1 A simple logic
2 Phase 0 - Compiling OpenSMT
3 Phase 1 - Setting up files and directories
4 Phase 2 - Connecting the T -solver
5 Phase 3 - Implementing the T -solver
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 2 / 22
A simple logic
For this tutorial we use a theory that we call “simple order” (SO)
Atoms of this theory are of the form
x ≤ y
but ≤ it is just a symbol to intend “x is before y”
A set of constraints is unsatisfiable iff there is a cycle
x ≤ y, y ≤ z, . . . , w ≤ x
A model is therefore is any “acyclic” set of constraints
x ≤ y
y ≤ z
z ≤ x
x y z
unsat
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 3 / 22
A simple logic
For this tutorial we use a theory that we call “simple order” (SO)
Atoms of this theory are of the form
x ≤ y
but ≤ it is just a symbol to intend “x is before y”
A set of constraints is unsatisfiable iff there is a cycle
x ≤ y, y ≤ z, . . . , w ≤ x
A model is therefore is any “acyclic” set of constraints
x ≤ y
y ≤ z
x ≤ z
x y z
sat
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 3 / 22
Phase 0 - Compiling OpenSMT for the first time
$ autoreconf --install [--force]
$ mkdir debug
$ cd debug
debug $ ../configure --disable-optimization
[--with-gmp=/opt/local]
debug $ make [-j4]
debug $ cd ..
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 4 / 22
Phase 1 - Setting up files and directories
1. Create a new directory for SO-solver
a. $ cd src/tsolvers
b. src/tsolvers $ cp -r emptysolver sosolver
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 5 / 22
Phase 1 - Setting up files and directories
1. Create a new directory for SO-solver
a. $ cd src/tsolvers
b. src/tsolvers $ cp -r emptysolver sosolver
2. Rename files
a. src/tsolvers $ cd sosolver
b. src/tsolvers/sosolver $ mv EmptySolver.h SOSolver.h
c. src/tsolvers/sosolver $ mv EmptySolver.C SOSolver.C
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 5 / 22
Phase 1 - Setting up files and directories
1. Create a new directory for SO-solver
a. $ cd src/tsolvers
b. src/tsolvers $ cp -r emptysolver sosolver
2. Rename files
a. src/tsolvers $ cd sosolver
b. src/tsolvers/sosolver $ mv EmptySolver.h SOSolver.h
c. src/tsolvers/sosolver $ mv EmptySolver.C SOSolver.C
3. Adjust Makefile.am
a. src/tsolvers/sosolver $ rm Makefile.in
b. src/tsolvers/sosolver $ vim Makefile.am
c. Find-replace “empty” with “so” and “Empty” with “SO” in the file
(:%s/empty/so/g and :%s/Empty/SO/g with vim)
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 5 / 22
Phase 1 - Setting up files and directories
4. Adjust source files
a. src/tsolvers/sosolver $ vim SOSolver.h
b. Find-replace “EMPTY” with “SO” (:%s/EMPTY/SO/g with vim)
c. Find-replace “Empty” with “SO” (:%s/Empty/SO/g with vim)
d. src/tsolvers/sosolver $ vim SOSolver.C
e. Find-replace “Empty” with “SO” (:%s/Empty/SO/g with vim)
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 6 / 22
Phase 1 - Setting up files and directories
4. Adjust source files
a. src/tsolvers/sosolver $ vim SOSolver.h
b. Find-replace “EMPTY” with “SO” (:%s/EMPTY/SO/g with vim)
c. Find-replace “Empty” with “SO” (:%s/Empty/SO/g with vim)
d. src/tsolvers/sosolver $ vim SOSolver.C
e. Find-replace “Empty” with “SO” (:%s/Empty/SO/g with vim)
5. Adjust ../Makefile.am
a. src/tsolvers/sosolver $ cd ..
b. src/tsolvers $ vim Makefile.am
c. Add sosolver in SUBDIR list
d. Add sosolver/libsosolver.la
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 6 / 22
Phase 1 - Setting up files and directories
4. Adjust source files
a. src/tsolvers/sosolver $ vim SOSolver.h
b. Find-replace “EMPTY” with “SO” (:%s/EMPTY/SO/g with vim)
c. Find-replace “Empty” with “SO” (:%s/Empty/SO/g with vim)
d. src/tsolvers/sosolver $ vim SOSolver.C
e. Find-replace “Empty” with “SO” (:%s/Empty/SO/g with vim)
5. Adjust ../Makefile.am
a. src/tsolvers/sosolver $ cd ..
b. src/tsolvers $ vim Makefile.am
c. Add sosolver in SUBDIR list
d. Add sosolver/libsosolver.la
6. Adjust ../../configure.ac
a. src/tsolvers $ cd ../..
b. $ vim configure.ac
c. Add -I${top_srcdir}/src/tsolvers/sosolver 
d. Add src/tsolvers/sosolver/Makefile 
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 6 / 22
Phase 1 - Setting up files and directories
7. Compile again
a. $ cd debug
b. debug $ make -j4
c. debug $ cd ..
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 7 / 22
Phase 2 - Connecting the T -solver
1. Create a new logic
a. $ vim src/common/Global.h
b. Add , QF_SO around line 196
c. Add else if ( l == QF_SO ) return "QF_SO"; around line 312
d. Add using opensmt::QF_SO; around line 346
e. $ vim src/api/OpenSMTContext.C
f. Add else if ( strcmp( str, "QF_SO" ) == 0 ) l = QF_SO;
around line 88
g. Compile again $ cd debug; make; cd .. (to see if any typo was
introduced)
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 8 / 22
Phase 2 - Connecting the T -solver
2. Allocate the solver
a. $ vim src/egraph/EgraphSolver.C
b. Add #include "SOSolver.h" around line 29
c. Add around line 853
else if ( config.logic == QF_SO )
{
tsolvers.push_back( new SOSolver( tsolvers.size( )
, "Simple Order Solver"
, config
, *this
, sort_store
, explanation
, deductions
, suggestions ) );
#ifdef STATISTICS
tsolvers_stats.push_back( new TSolverStats( ) );
#endif
}
2. Compile again $ cd debug; make; cd .. (to see if any typo was
introduced)
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 9 / 22
Phase 3 - Implementing the solver
Playing with the Enodes
The Enode is the data structure that stores any term and formula
There are three kinds of Enode
Symbol
+
Term
+
List
-
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 10 / 22
Phase 3 - Implementing the solver
Playing with the Enodes
The Enode is the data structure that stores any term and formula
There are three kinds of Enode
Symbol
+
Term
+
List
-
E.g. the term x ≤ y is represented as
If e is the Enode for x ≤ y, we retrieve the
Enode for x with
Enode * lhs = e->get1st( )
and the Enode for y with
Enode * rhs = e->get2nd( )
≤
x
y
-
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 10 / 22
Phase 3 - Implementing the solver
Playing with the Enodes
The polarity of an Enode can be retrieved with
lbool sign = e->getPolarity( );
and it could be l_True or l_False
An Enode e can be simply printed with
cerr << "printing enode: " << e << endl;
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 11 / 22
Phase 3 - Implementing the solver
A set of constraints is unsatisfiable iff there is a cycle
x ≤ y, y ≤ z, . . . , w ≤ x
A model is therefore is any “acyclic” set of constraints
x ≤ y
y ≤ z
z ≤ x
x y z
unsat
Therefore we need to
1 Represent the graph from the received constraints
2 Check if the graph contains a cycle
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 12 / 22
Phase 3 - Implementing the solver
Representing the graph
We represent the graph with adjacency lists, i.e., every node
(variable) is assigned to a list of outgoing edges
We use STL to make the following data structure
map< Enode *, vector< Enode * > > adj_list;
that we declare as private attribute in SOSolver.h, so that it will be
accessible everywhere in the class
When we receive a new constraint with assertLit, we update
adj_list with
adj_list[ from ].push_back( e );
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 13 / 22
Phase 3 - Implementing the solver
Checking for a cycle
When check is called we have to see if there is a cycle in the current graph
We use a simple depth-first search using the following high-level recursive function:
Input: a node “from”
Output: true iff a cycle containing “from” is found
1 function findCycle( Enode * from )
2 if ( “from was seen before” ) return true
3 for each “from ≤ y” in adj list of from
4 res = findCycle( y )
5 if ( res == true ) return true
6 return false
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 14 / 22
Phase 3 - Implementing the solver
Checking for a cycle
In SOSolver.C
...
bool SOSolver::findCycle( Enode * from )
{
if ( seen.find( from ) != seen.end( ) )
return true;
seen.insert( from );
vector< Enode * > & adj_list_from = adj_list[ from ];
for ( size_t i = 0 ; i < adj_list_from.size( ) ; i ++ )
{
const bool cycle_found = findCycle( adj_list_from[ i ]->get2nd( ) );
if ( cycle_found )
return true;
}
seen.erase( from );
return false;
}
...
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 15 / 22
Phase 3 - Implementing the solver
Checking for a cycle
In SOSolver.C
bool SOSolver::check( bool complete )
{
for ( map< Enode *, vector< Enode * > >::iterator it = adj_list.begin( )
; it != adj_list.end( )
; it ++ )
{
seen.clear( );
Enode * from = it->first;
const bool cycle_found = findCycle( from );
if ( cycle_found )
return false;
}
return true;
}
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 16 / 22
Phase 3 - Implementing the solver
Checking for a cycle
In SOSolver.h
private:
bool findCycle ( Enode * );
map< Enode *, vector< Enode * > > adj_list;
set< Enode * > seen;
We can try to compile, and test it with files so example 1.smt2 and
so example 2.smt2
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 17 / 22
Phase 3 - Implementing the solver
Computing conflicts
Conflicts can be computed by keeping track of the edges that form the last cycle detected
We add a map< Enode *, Enode * > parent_edge map which we use to store the edge used
to reach a node in the depth-serch traversal
When during findCycle we discover an already visited node, we backward visit the
parent edge relation to retrieve the cycle
void SOSolver::computeExplanation( Enode * from )
{
assert( explanation.empty( ) );
Enode * x = from;
do
{
x = parent_edge[ x ]->get1st( );
explanation.push_back( parent_edge[ x ] );
}
while( x != from );
}
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 18 / 22
Phase 3 - Implementing the solver
Computing conflicts
Again in SOSolver.C
void SOSolver::findCycle( Enode * from )
{
if ( seen.find( from ) != seen.end( ) )
{
computeExplanation( from );
return true;
}
...
}
Again in SOSolver.h
map< Enode *, Enode * > parent_edge;
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 19 / 22
Phase 3 - Implementing the solver
Incrementality - Backtrackability
Last thing we need is to handle incrementality/backtrackability
For simplicity, solving will not be incremental nor backtrackable in this
lecture
However we still have to keep adj_list updated with constraints
received/dropped
For this aim we introduce two more vectors in SOSolver.h
vector< Enode * > used_constr;
vector< size_t > backtrack_points;
used_constr keeps track of the order of constraints received, while
backtrack_points keeps track of the size of used_constr when a new
backtrack point is requested
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 20 / 22
Phase 3 - Implementing the solver
Incrementality - Backtrackability
void SOSolver::pushBacktrackPoint ( )
{
backtrack_points.push_back( used_constr.size( ) );
}
void SOSolver::popBacktrackPoint ( )
{
assert( !backtrack_points.empty( ) );
const size_t new_size = backtrack_points.back( );
backtrack_points.pop_back( );
while ( new_size < used_constr.size( ) )
{
Enode * e = used_constr.back( );
Enode * from = e->get1st( );
Enode * to = e->get2nd( );
assert( adj_list[ from ].back( ) == e );
adj_list[ from ].pop_back( );
used_constr.pop_back( );
}
}
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 21 / 22
Exercizes
The current code for check has worst-case quadratic complexity (a lot
of redundant work is done). Modify it to make it linear (hint: use
another set< Enode * > to keep track of . . . )
R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 22 / 22

More Related Content

PDF
Pdr ppt
PDF
The Ring programming language version 1.3 book - Part 17 of 88
PDF
"A 1,500 line (!!) switch statement powers your Python!" - Allison Kaptur, !!...
PDF
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
PDF
4. Обработка ошибок, исключения, отладка
PDF
Bytes in the Machine: Inside the CPython interpreter
PDF
Javascript basics
PDF
The Ring programming language version 1.6 book - Part 81 of 189
Pdr ppt
The Ring programming language version 1.3 book - Part 17 of 88
"A 1,500 line (!!) switch statement powers your Python!" - Allison Kaptur, !!...
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
4. Обработка ошибок, исключения, отладка
Bytes in the Machine: Inside the CPython interpreter
Javascript basics
The Ring programming language version 1.6 book - Part 81 of 189

What's hot (20)

KEY
Post Exploitation Bliss: Loading Meterpreter on a Factory iPhone, Black Hat U...
PDF
Coroutines in Kotlin. UA Mobile 2017.
PDF
The Ring programming language version 1.5.1 book - Part 74 of 180
PDF
The Ring programming language version 1.7 book - Part 29 of 196
PDF
3. Объекты, классы и пакеты в Java
ODP
EcmaScript 6
PDF
The Ring programming language version 1.5.1 book - Part 24 of 180
PPTX
Grand Central Dispatch in Objective-C
PDF
The Ring programming language version 1.2 book - Part 57 of 84
PDF
The Ring programming language version 1.5.3 book - Part 25 of 184
PDF
Lisp
PDF
The Ring programming language version 1.5.2 book - Part 25 of 181
PDF
User-Defined Table Generating Functions
PPTX
การเขียนคำสั่งควบคุมแบบวนซ้ำ ppt
PPTX
FRP: What does "declarative" mean
PDF
Functional Programming: An Introduction
PPTX
Exploit Development: EzServer Buffer Overflow oleh Tom Gregory
PDF
Implementing Software Machines in Go and C
PDF
2020 Droid Knights CustomLint 적용기
PDF
CyberLink LabelPrint 2.5 Exploitation Process
Post Exploitation Bliss: Loading Meterpreter on a Factory iPhone, Black Hat U...
Coroutines in Kotlin. UA Mobile 2017.
The Ring programming language version 1.5.1 book - Part 74 of 180
The Ring programming language version 1.7 book - Part 29 of 196
3. Объекты, классы и пакеты в Java
EcmaScript 6
The Ring programming language version 1.5.1 book - Part 24 of 180
Grand Central Dispatch in Objective-C
The Ring programming language version 1.2 book - Part 57 of 84
The Ring programming language version 1.5.3 book - Part 25 of 184
Lisp
The Ring programming language version 1.5.2 book - Part 25 of 181
User-Defined Table Generating Functions
การเขียนคำสั่งควบคุมแบบวนซ้ำ ppt
FRP: What does "declarative" mean
Functional Programming: An Introduction
Exploit Development: EzServer Buffer Overflow oleh Tom Gregory
Implementing Software Machines in Go and C
2020 Droid Knights CustomLint 적용기
CyberLink LabelPrint 2.5 Exploitation Process
Ad

Viewers also liked (20)

PPT
Binz presentatie
PPT
งานนำเสนอ1
PDF
satandsmt.stpetersburg
PPT
ข้อมูลและสารสนเทศMix
PDF
The City
PPTX
PPT
ระบบคอมพิวเตอร์ Mix
PPT
GRS GIS profile
PPT
ระบบคอมพิวเตอร์ Mix
PDF
Binz presentatie slideshare
PPT
เทคโนโลยีสารสนเทศ Mix
PDF
The Power of Vision
PDF
smtlectures.2
PDF
smtlecture.3
ODP
Informatheques
ODP
Epi mobile
PDF
smtlectures.1
PDF
Yak podolaty batkivski_strahy_pered_shkoloyu._porady_psyhologa
PDF
Shkidlyvi batkivski perekonannya
DOC
11 gsm bss network kpi (paging success rate) optimization manual
Binz presentatie
งานนำเสนอ1
satandsmt.stpetersburg
ข้อมูลและสารสนเทศMix
The City
ระบบคอมพิวเตอร์ Mix
GRS GIS profile
ระบบคอมพิวเตอร์ Mix
Binz presentatie slideshare
เทคโนโลยีสารสนเทศ Mix
The Power of Vision
smtlectures.2
smtlecture.3
Informatheques
Epi mobile
smtlectures.1
Yak podolaty batkivski_strahy_pered_shkoloyu._porady_psyhologa
Shkidlyvi batkivski perekonannya
11 gsm bss network kpi (paging success rate) optimization manual
Ad

Similar to smtlecture.9 (20)

PDF
7 strace examples to debug the execution of a program in linux
PPT
Shell Scripting
PDF
The Ring programming language version 1.9 book - Part 90 of 210
KEY
groovy & grails - lecture 2
PDF
Kernel Recipes 2016 - Why you need a test strategy for your kernel development
PDF
Data mining : rule mining algorithms
PPTX
Lecture 9_Classes.pptx
PDF
Crash course to learn python programming
PPTX
Time and Space Complexity Analysis.pptx
PDF
RHCSA Discoverability Discoverability .pdf
PPT
Lecture 2
PDF
The Ring programming language version 1.8 book - Part 86 of 202
PPT
Slides chapters 28-32
PDF
Learning to Sample
PDF
python-2021.pdf
PDF
The Ring programming language version 1.7 book - Part 30 of 196
PDF
Groovy Update, Groovy Ecosystem, and Gaelyk -- Devoxx 2010 -- Guillaume Laforge
PPT
Synthesis
PPTX
ODU ACM Python & Memento Presentation
PDF
The Ring programming language version 1.7 book - Part 85 of 196
7 strace examples to debug the execution of a program in linux
Shell Scripting
The Ring programming language version 1.9 book - Part 90 of 210
groovy & grails - lecture 2
Kernel Recipes 2016 - Why you need a test strategy for your kernel development
Data mining : rule mining algorithms
Lecture 9_Classes.pptx
Crash course to learn python programming
Time and Space Complexity Analysis.pptx
RHCSA Discoverability Discoverability .pdf
Lecture 2
The Ring programming language version 1.8 book - Part 86 of 202
Slides chapters 28-32
Learning to Sample
python-2021.pdf
The Ring programming language version 1.7 book - Part 30 of 196
Groovy Update, Groovy Ecosystem, and Gaelyk -- Devoxx 2010 -- Guillaume Laforge
Synthesis
ODU ACM Python & Memento Presentation
The Ring programming language version 1.7 book - Part 85 of 196

More from Roberto Bruttomesso (6)

PDF
smtlecture.10
PDF
smtlecture.8
PDF
smtlecture.7
PDF
smtlecture.6
PDF
smtlecture.5
PDF
smtlecture.4
smtlecture.10
smtlecture.8
smtlecture.7
smtlecture.6
smtlecture.5
smtlecture.4

Recently uploaded (20)

PDF
Hazard Identification & Risk Assessment .pdf
PPTX
Introduction to pro and eukaryotes and differences.pptx
PPTX
B.Sc. DS Unit 2 Software Engineering.pptx
PDF
International_Financial_Reporting_Standa.pdf
DOCX
Cambridge-Practice-Tests-for-IELTS-12.docx
PDF
1.3 FINAL REVISED K-10 PE and Health CG 2023 Grades 4-10 (1).pdf
PDF
احياء السادس العلمي - الفصل الثالث (التكاثر) منهج متميزين/كلية بغداد/موهوبين
PDF
Chinmaya Tiranga quiz Grand Finale.pdf
PDF
FOISHS ANNUAL IMPLEMENTATION PLAN 2025.pdf
PDF
My India Quiz Book_20210205121199924.pdf
PDF
BP 704 T. NOVEL DRUG DELIVERY SYSTEMS (UNIT 2).pdf
PPTX
History, Philosophy and sociology of education (1).pptx
PDF
David L Page_DCI Research Study Journey_how Methodology can inform one's prac...
PPTX
ELIAS-SEZIURE AND EPilepsy semmioan session.pptx
DOC
Soft-furnishing-By-Architect-A.F.M.Mohiuddin-Akhand.doc
PDF
FORM 1 BIOLOGY MIND MAPS and their schemes
PDF
Trump Administration's workforce development strategy
PDF
Complications of Minimal Access-Surgery.pdf
PDF
OBE - B.A.(HON'S) IN INTERIOR ARCHITECTURE -Ar.MOHIUDDIN.pdf
PDF
Τίμαιος είναι φιλοσοφικός διάλογος του Πλάτωνα
Hazard Identification & Risk Assessment .pdf
Introduction to pro and eukaryotes and differences.pptx
B.Sc. DS Unit 2 Software Engineering.pptx
International_Financial_Reporting_Standa.pdf
Cambridge-Practice-Tests-for-IELTS-12.docx
1.3 FINAL REVISED K-10 PE and Health CG 2023 Grades 4-10 (1).pdf
احياء السادس العلمي - الفصل الثالث (التكاثر) منهج متميزين/كلية بغداد/موهوبين
Chinmaya Tiranga quiz Grand Finale.pdf
FOISHS ANNUAL IMPLEMENTATION PLAN 2025.pdf
My India Quiz Book_20210205121199924.pdf
BP 704 T. NOVEL DRUG DELIVERY SYSTEMS (UNIT 2).pdf
History, Philosophy and sociology of education (1).pptx
David L Page_DCI Research Study Journey_how Methodology can inform one's prac...
ELIAS-SEZIURE AND EPilepsy semmioan session.pptx
Soft-furnishing-By-Architect-A.F.M.Mohiuddin-Akhand.doc
FORM 1 BIOLOGY MIND MAPS and their schemes
Trump Administration's workforce development strategy
Complications of Minimal Access-Surgery.pdf
OBE - B.A.(HON'S) IN INTERIOR ARCHITECTURE -Ar.MOHIUDDIN.pdf
Τίμαιος είναι φιλοσοφικός διάλογος του Πλάτωνα

smtlecture.9

  • 1. Satisfiability Modulo Theories Lecture 9 - Extending OpenSMT for fun and profit∗ (slides revision: Saturday 14th March, 2015, 11:47) Roberto Bruttomesso Seminario di Logica Matematica (Corso Prof. Silvio Ghilardi) 22 Dicembre 2011 R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 1 / 22
  • 2. Outline 1 A simple logic 2 Phase 0 - Compiling OpenSMT 3 Phase 1 - Setting up files and directories 4 Phase 2 - Connecting the T -solver 5 Phase 3 - Implementing the T -solver R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 2 / 22
  • 3. A simple logic For this tutorial we use a theory that we call “simple order” (SO) Atoms of this theory are of the form x ≤ y but ≤ it is just a symbol to intend “x is before y” A set of constraints is unsatisfiable iff there is a cycle x ≤ y, y ≤ z, . . . , w ≤ x A model is therefore is any “acyclic” set of constraints x ≤ y y ≤ z z ≤ x x y z unsat R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 3 / 22
  • 4. A simple logic For this tutorial we use a theory that we call “simple order” (SO) Atoms of this theory are of the form x ≤ y but ≤ it is just a symbol to intend “x is before y” A set of constraints is unsatisfiable iff there is a cycle x ≤ y, y ≤ z, . . . , w ≤ x A model is therefore is any “acyclic” set of constraints x ≤ y y ≤ z x ≤ z x y z sat R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 3 / 22
  • 5. Phase 0 - Compiling OpenSMT for the first time $ autoreconf --install [--force] $ mkdir debug $ cd debug debug $ ../configure --disable-optimization [--with-gmp=/opt/local] debug $ make [-j4] debug $ cd .. R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 4 / 22
  • 6. Phase 1 - Setting up files and directories 1. Create a new directory for SO-solver a. $ cd src/tsolvers b. src/tsolvers $ cp -r emptysolver sosolver R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 5 / 22
  • 7. Phase 1 - Setting up files and directories 1. Create a new directory for SO-solver a. $ cd src/tsolvers b. src/tsolvers $ cp -r emptysolver sosolver 2. Rename files a. src/tsolvers $ cd sosolver b. src/tsolvers/sosolver $ mv EmptySolver.h SOSolver.h c. src/tsolvers/sosolver $ mv EmptySolver.C SOSolver.C R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 5 / 22
  • 8. Phase 1 - Setting up files and directories 1. Create a new directory for SO-solver a. $ cd src/tsolvers b. src/tsolvers $ cp -r emptysolver sosolver 2. Rename files a. src/tsolvers $ cd sosolver b. src/tsolvers/sosolver $ mv EmptySolver.h SOSolver.h c. src/tsolvers/sosolver $ mv EmptySolver.C SOSolver.C 3. Adjust Makefile.am a. src/tsolvers/sosolver $ rm Makefile.in b. src/tsolvers/sosolver $ vim Makefile.am c. Find-replace “empty” with “so” and “Empty” with “SO” in the file (:%s/empty/so/g and :%s/Empty/SO/g with vim) R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 5 / 22
  • 9. Phase 1 - Setting up files and directories 4. Adjust source files a. src/tsolvers/sosolver $ vim SOSolver.h b. Find-replace “EMPTY” with “SO” (:%s/EMPTY/SO/g with vim) c. Find-replace “Empty” with “SO” (:%s/Empty/SO/g with vim) d. src/tsolvers/sosolver $ vim SOSolver.C e. Find-replace “Empty” with “SO” (:%s/Empty/SO/g with vim) R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 6 / 22
  • 10. Phase 1 - Setting up files and directories 4. Adjust source files a. src/tsolvers/sosolver $ vim SOSolver.h b. Find-replace “EMPTY” with “SO” (:%s/EMPTY/SO/g with vim) c. Find-replace “Empty” with “SO” (:%s/Empty/SO/g with vim) d. src/tsolvers/sosolver $ vim SOSolver.C e. Find-replace “Empty” with “SO” (:%s/Empty/SO/g with vim) 5. Adjust ../Makefile.am a. src/tsolvers/sosolver $ cd .. b. src/tsolvers $ vim Makefile.am c. Add sosolver in SUBDIR list d. Add sosolver/libsosolver.la R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 6 / 22
  • 11. Phase 1 - Setting up files and directories 4. Adjust source files a. src/tsolvers/sosolver $ vim SOSolver.h b. Find-replace “EMPTY” with “SO” (:%s/EMPTY/SO/g with vim) c. Find-replace “Empty” with “SO” (:%s/Empty/SO/g with vim) d. src/tsolvers/sosolver $ vim SOSolver.C e. Find-replace “Empty” with “SO” (:%s/Empty/SO/g with vim) 5. Adjust ../Makefile.am a. src/tsolvers/sosolver $ cd .. b. src/tsolvers $ vim Makefile.am c. Add sosolver in SUBDIR list d. Add sosolver/libsosolver.la 6. Adjust ../../configure.ac a. src/tsolvers $ cd ../.. b. $ vim configure.ac c. Add -I${top_srcdir}/src/tsolvers/sosolver d. Add src/tsolvers/sosolver/Makefile R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 6 / 22
  • 12. Phase 1 - Setting up files and directories 7. Compile again a. $ cd debug b. debug $ make -j4 c. debug $ cd .. R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 7 / 22
  • 13. Phase 2 - Connecting the T -solver 1. Create a new logic a. $ vim src/common/Global.h b. Add , QF_SO around line 196 c. Add else if ( l == QF_SO ) return "QF_SO"; around line 312 d. Add using opensmt::QF_SO; around line 346 e. $ vim src/api/OpenSMTContext.C f. Add else if ( strcmp( str, "QF_SO" ) == 0 ) l = QF_SO; around line 88 g. Compile again $ cd debug; make; cd .. (to see if any typo was introduced) R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 8 / 22
  • 14. Phase 2 - Connecting the T -solver 2. Allocate the solver a. $ vim src/egraph/EgraphSolver.C b. Add #include "SOSolver.h" around line 29 c. Add around line 853 else if ( config.logic == QF_SO ) { tsolvers.push_back( new SOSolver( tsolvers.size( ) , "Simple Order Solver" , config , *this , sort_store , explanation , deductions , suggestions ) ); #ifdef STATISTICS tsolvers_stats.push_back( new TSolverStats( ) ); #endif } 2. Compile again $ cd debug; make; cd .. (to see if any typo was introduced) R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 9 / 22
  • 15. Phase 3 - Implementing the solver Playing with the Enodes The Enode is the data structure that stores any term and formula There are three kinds of Enode Symbol + Term + List - R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 10 / 22
  • 16. Phase 3 - Implementing the solver Playing with the Enodes The Enode is the data structure that stores any term and formula There are three kinds of Enode Symbol + Term + List - E.g. the term x ≤ y is represented as If e is the Enode for x ≤ y, we retrieve the Enode for x with Enode * lhs = e->get1st( ) and the Enode for y with Enode * rhs = e->get2nd( ) ≤ x y - R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 10 / 22
  • 17. Phase 3 - Implementing the solver Playing with the Enodes The polarity of an Enode can be retrieved with lbool sign = e->getPolarity( ); and it could be l_True or l_False An Enode e can be simply printed with cerr << "printing enode: " << e << endl; R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 11 / 22
  • 18. Phase 3 - Implementing the solver A set of constraints is unsatisfiable iff there is a cycle x ≤ y, y ≤ z, . . . , w ≤ x A model is therefore is any “acyclic” set of constraints x ≤ y y ≤ z z ≤ x x y z unsat Therefore we need to 1 Represent the graph from the received constraints 2 Check if the graph contains a cycle R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 12 / 22
  • 19. Phase 3 - Implementing the solver Representing the graph We represent the graph with adjacency lists, i.e., every node (variable) is assigned to a list of outgoing edges We use STL to make the following data structure map< Enode *, vector< Enode * > > adj_list; that we declare as private attribute in SOSolver.h, so that it will be accessible everywhere in the class When we receive a new constraint with assertLit, we update adj_list with adj_list[ from ].push_back( e ); R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 13 / 22
  • 20. Phase 3 - Implementing the solver Checking for a cycle When check is called we have to see if there is a cycle in the current graph We use a simple depth-first search using the following high-level recursive function: Input: a node “from” Output: true iff a cycle containing “from” is found 1 function findCycle( Enode * from ) 2 if ( “from was seen before” ) return true 3 for each “from ≤ y” in adj list of from 4 res = findCycle( y ) 5 if ( res == true ) return true 6 return false R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 14 / 22
  • 21. Phase 3 - Implementing the solver Checking for a cycle In SOSolver.C ... bool SOSolver::findCycle( Enode * from ) { if ( seen.find( from ) != seen.end( ) ) return true; seen.insert( from ); vector< Enode * > & adj_list_from = adj_list[ from ]; for ( size_t i = 0 ; i < adj_list_from.size( ) ; i ++ ) { const bool cycle_found = findCycle( adj_list_from[ i ]->get2nd( ) ); if ( cycle_found ) return true; } seen.erase( from ); return false; } ... R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 15 / 22
  • 22. Phase 3 - Implementing the solver Checking for a cycle In SOSolver.C bool SOSolver::check( bool complete ) { for ( map< Enode *, vector< Enode * > >::iterator it = adj_list.begin( ) ; it != adj_list.end( ) ; it ++ ) { seen.clear( ); Enode * from = it->first; const bool cycle_found = findCycle( from ); if ( cycle_found ) return false; } return true; } R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 16 / 22
  • 23. Phase 3 - Implementing the solver Checking for a cycle In SOSolver.h private: bool findCycle ( Enode * ); map< Enode *, vector< Enode * > > adj_list; set< Enode * > seen; We can try to compile, and test it with files so example 1.smt2 and so example 2.smt2 R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 17 / 22
  • 24. Phase 3 - Implementing the solver Computing conflicts Conflicts can be computed by keeping track of the edges that form the last cycle detected We add a map< Enode *, Enode * > parent_edge map which we use to store the edge used to reach a node in the depth-serch traversal When during findCycle we discover an already visited node, we backward visit the parent edge relation to retrieve the cycle void SOSolver::computeExplanation( Enode * from ) { assert( explanation.empty( ) ); Enode * x = from; do { x = parent_edge[ x ]->get1st( ); explanation.push_back( parent_edge[ x ] ); } while( x != from ); } R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 18 / 22
  • 25. Phase 3 - Implementing the solver Computing conflicts Again in SOSolver.C void SOSolver::findCycle( Enode * from ) { if ( seen.find( from ) != seen.end( ) ) { computeExplanation( from ); return true; } ... } Again in SOSolver.h map< Enode *, Enode * > parent_edge; R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 19 / 22
  • 26. Phase 3 - Implementing the solver Incrementality - Backtrackability Last thing we need is to handle incrementality/backtrackability For simplicity, solving will not be incremental nor backtrackable in this lecture However we still have to keep adj_list updated with constraints received/dropped For this aim we introduce two more vectors in SOSolver.h vector< Enode * > used_constr; vector< size_t > backtrack_points; used_constr keeps track of the order of constraints received, while backtrack_points keeps track of the size of used_constr when a new backtrack point is requested R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 20 / 22
  • 27. Phase 3 - Implementing the solver Incrementality - Backtrackability void SOSolver::pushBacktrackPoint ( ) { backtrack_points.push_back( used_constr.size( ) ); } void SOSolver::popBacktrackPoint ( ) { assert( !backtrack_points.empty( ) ); const size_t new_size = backtrack_points.back( ); backtrack_points.pop_back( ); while ( new_size < used_constr.size( ) ) { Enode * e = used_constr.back( ); Enode * from = e->get1st( ); Enode * to = e->get2nd( ); assert( adj_list[ from ].back( ) == e ); adj_list[ from ].pop_back( ); used_constr.pop_back( ); } } R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 21 / 22
  • 28. Exercizes The current code for check has worst-case quadratic complexity (a lot of redundant work is done). Modify it to make it linear (hint: use another set< Enode * > to keep track of . . . ) R. Bruttomesso (SMT) OpenSMT 22 Dicembre 2011 22 / 22