240 likes | 338 Views
Programming declaratively in C++ using the Logic paradigm. Roshan Naik Hewlett Packard Co. roshan@mpprogramming.com 16 th April 2008 Northwest C++ Users Group Redmond, WA . Agenda. Introduction to Logic Programming (LP) concepts.
E N D
Programming declaratively in C++ using the Logic paradigm Roshan Naik Hewlett Packard Co. roshan@mpprogramming.com 16th April 2008 Northwest C++ Users Group Redmond, WA
Agenda • Introduction to Logic Programming (LP) concepts. • Introduction to facilities available for LP in C++. Will use the open source library : Castor (www.mpprogramming.com). • Live examples. From trivial to simple to more complex ones.
Underlying Theme • LP as a general purpose programming. • Demonstrate Multiparadigm Programming by mixing LP with the Imperative, Object-oriented, Functional and Generic paradigms.
Logic Paradigm (LP) • Computational model: Predicate calculus (Turing complete). • Declarative : Focuses on what to compute not how. • Holy Grail of programming: “The user states the problem, the computer solves it”. LP is one approach in Computer Science. • Basic mechanics of LP • Programmer provides sufficient information to the computer. • By using relations • Computer employs a general purpose problem solving technique. • By using backtracking and unification.
Declarative vs. Imperative • Why are most programming languages imperative ? • What is a key weakness of declarative programming ? • What is a key weakness of imperative programming ?
“relation” • A set is a collection of (unique) objects. • A simple way of thinking about relations is as an association/mapping between elements in two or more sets. People Frank Sam Mary Denise Genders Male Female GenderOf (Frank, Male) (Sam, Male) (Mary, Female) (Denise, Female)
“relation” • A relation is essentially a set. • Thinking of relations as mappings between sets really helps when designing relations in LP. • A relation is to the logic paradigm what a function is to the imperative paradigm.
Functions vs. Relations GenderOf (Frank, Male) (Sam, Male) (Mary, Female) (Denise, Female) • As functions // check if (p,g) bool checkGender(string p, string g) { ... } // get gender of p string genderOf(string p) { ... } // get all people having gender g list<string> havingGender(string g) { ... } // list all (p,g) list<pair<string,string> > getItems() { ... }
Functions vs. Relations • As a relation // declarative reading : p’s gender is g relationgender(lref<string> p, lref<string> g){ return eq(p,”Frank”) && eq(g,”male”) || eq(p,”Sam”) && eq(g,”male”) || eq(p,”Mary”) && eq(g,”female”) || eq(p,”Denise”)&& eq(g,”female”); } • Specification is declarative. • One relation subsumes functionality of all four functions. GenderOf (Frank, Male) (Sam, Male) (Mary, Female) (Denise, Female)
lref<T> : logic reference • Unlike C++ references, it does not have to be initialized. Use method defined() to check. • Operator * used to access underlying value. cout << *lx; • Internally stores a copyof the value assigned to it. lref<int> li=2; • Copy constructing an lref binds it with source lref. i.e. both refer to the same underlying object. lref<int> lj (li); • Assigning one lref to another simply copies the underlying value over. lref<int> lk; lk=lj;
lref<T> : Logic reference • Initialization lref<int> li1=1, li2;// li2.defined()==false li2=10; // li2.defined()==true • Copy construction lref<int> li3=li1; // co-references li3=5; cout << *li1; // prints 5 • Assignment lref<int> li4 = 4; li4=li1; // copy value from li1 to li4 li1=9; cout << *li1 << ", " << *li4; // prints 9, 1
eq : The unification relation • Attempts to make both arguments equal. • Semantically a combination of == and = if (both args are initialized) return 1stArg == 2ndArg; else uninitializedArg= value of the other; return true; • At least one of the two arguments must be initialized!
The magic type : relation • Represents any function object that produces a bool and takes no arguments. struct FuncObj { booloperator() (void) {...} }; FuncObj f; relation r = f; r();// execute FuncObj::operator() • Type erasure at work • Explicit conversion or assignment operators not needed to assign FuncObj to relation. • FuncObj does not have to inherit from any type or be templated. • Key to smooth integration of paradigms and simple syntax. • Fairly similar to boost::function<bool()>
Disjunction: Operator || relation operator || (relation lhs, relation rhs) Example:foo(…) || bar(…) • In plain English: • Generate all solutions from lhs (one per invocation), then generate all solutions from rhs (one per invocation). • Coroutine style pseudo code (C# like syntax). while( lhs() ) yieldreturntrue; //‘yield’ borrowed from C# while( rhs() ) yieldreturntrue; return false;
Conjunction: Operator && • In plain English: • Produce all solutions (one per invocation) in the 2nd relation for each solution in the 1st relation. • Coroutine style pseudo code (C# like syntax). relation tmp = rhs; //make copy of rhs while( lhs() ) { while( rhs() ) yieldreturntrue; //‘yield’ borrowed from C# rhs = tmp; //reset rhs } returnfalse;
Exclusive Disjunction: Operator ^ • In plain English: • Generate solutions from 2nd relation (one per invocation), only if 1st relation did not produce any. • Coroutine style pseudo code (C# like syntax). bool lhsSucceded = false; while( lhs() ) { lhsSucceded = true; yieldreturntrue; } while(!lhsSucceded && rhs()) yieldreturntrue; returnfalse;
Examples • Demo
1 2 5 3 4 Directed Acyclic Graphs // Edges in the graph relation edge(lref<int> n1, lref<int> n2) { returneq(n1,1) && eq(n2,2) ||eq(n1,2) && eq(n2,3) ||eq(n1,3) && eq(n2,4) ||eq(n1,5) && eq(n2,4) ||eq(n1,5) && eq(n2,2) ; } // Definition of path relation path(lref<int> start, lref<int> end) { lref<int> nodeX; return edge(start, end) || edge(start, nodeX) && recurse(path,nodeX,end); }
Disjunctions : Dynamic relations • Think of it as a dynamic list of clauses separated by || operator. • Disjunctions is itself a relation. relation edge(lref<int> n1, lref<int> n2) { Disjunctions result; result.push_back(eq(n1,1) && eq(n2,2) ); result.push_back(eq(n1,2) && eq(n2,3) ); ... return result; }
Examples • Demo
Castor • About: • Pure header library (i.e. nothing to link). • Download from www.mpprogramming.com • Open source. (MIT License). • Sourceforge project name: castor-logic • Compilers supported: • aCC, A.06.15 (Mar 28 2007) • Borland C++ Builder 2007 • GCC, v4.1.0 (and above) • Microsoft Visual C++ 2005 and 2008
More information • Introduction to Logic Programming with C++ • www.mpprogramming.com/resources/CastorTutorial.pdf • Castor reference manual • www.mpprogramming.com/resources/CastorReference.pdf • Blending the Logic Programming Paradigm into C++ (on design & implementation of Castor) • www.mpprogramming.com/resources/CastorDesign.pdf • RSS feed on mpprogramming.com for updates.