Programming declaratively in C++ using the Logic paradigm

24
Programming declaratively in C++ using the Logic paradigm Roshan Naik Hewlett Packard Co. [email protected] 16 th April 2008 Northwest C++ Users Group Redmond, WA

description

Programming declaratively in C++ using the Logic paradigm. Roshan Naik Hewlett Packard Co. [email protected] 16 th April 2008 Northwest C++ Users Group Redmond, WA . Agenda. Introduction to Logic Programming (LP) concepts. - PowerPoint PPT Presentation

Transcript of Programming declaratively in C++ using the Logic paradigm

Page 1: Programming declaratively in C++ using the Logic paradigm

Programming declaratively in C++ using the Logic paradigm

Roshan NaikHewlett Packard Co.

[email protected]

16th April 2008Northwest C++ Users Group

Redmond, WA

Page 2: Programming declaratively in C++ using the Logic paradigm

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.

Page 3: Programming declaratively in C++ using the Logic paradigm

Underlying Theme• LP as a general purpose programming.• Demonstrate Multiparadigm Programming by

mixing LP with the Imperative, Object-oriented, Functional and Generic paradigms.

Page 4: Programming declaratively in C++ using the Logic paradigm

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.

Page 5: Programming declaratively in C++ using the Logic paradigm

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 ?

Page 6: Programming declaratively in C++ using the Logic paradigm

“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.

PeopleFrankSamMaryDenise

GendersMaleFemale

GenderOf(Frank, Male)(Sam, Male)(Mary, Female)(Denise, Female)

Page 7: Programming declaratively in C++ using the Logic paradigm

“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.

Page 8: Programming declaratively in C++ using the Logic paradigm

Functions vs. Relations• As functions

// check if (p,g)bool checkGender(string p, string g) { ...}// get gender of pstring genderOf(string p) { ...}// get all people having gender glist<string> havingGender(string g) { ...}// list all (p,g)list<pair<string,string> > getItems() { ...}

GenderOf(Frank, Male)

(Sam, Male)

(Mary, Female)

(Denise, Female)

Page 9: Programming declaratively in C++ using the Logic paradigm

Functions vs. Relations

• As a relation// declarative reading : p’s gender is grelation gender(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)

Page 10: Programming declaratively in C++ using the Logic paradigm

Demo

Page 11: Programming declaratively in C++ using the Logic paradigm

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 copy of 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;

Page 12: Programming declaratively in C++ using the Logic paradigm

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-referencesli3=5;cout << *li1; // prints 5

• Assignmentlref<int> li4 = 4;li4=li1; // copy value from li1 to li4li1=9;cout << *li1 << ", " << *li4; // prints 9, 1

Page 13: Programming declaratively in C++ using the Logic paradigm

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!

Page 14: Programming declaratively in C++ using the Logic paradigm

The magic type : relation• Represents any function object that produces a bool and

takes no arguments.struct FuncObj { bool operator() (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()>

Page 15: Programming declaratively in C++ using the Logic paradigm

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() )

yield return true; //‘yield’ borrowed from C#while( rhs() )

yield return true;return false;

Page 16: Programming declaratively in C++ using the Logic paradigm

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 rhswhile( lhs() ) {

while( rhs() ) yield return true; //‘yield’ borrowed from C#rhs = tmp; //reset rhs

}return false;

Page 17: Programming declaratively in C++ using the Logic paradigm

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;

yield return true;}while(!lhsSucceded && rhs())

yield return true;return false;

Page 18: Programming declaratively in C++ using the Logic paradigm

Examples

• Demo

Page 19: Programming declaratively in C++ using the Logic paradigm

Directed Acyclic Graphs// Edges in the graphrelation edge(lref<int> n1, lref<int> n2) { return eq(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 pathrelation path(lref<int> start, lref<int> end) { lref<int> nodeX; return edge(start, end) || edge(start, nodeX) && recurse(path,nodeX,end);}

1

3

4

5

2

Page 20: Programming declaratively in C++ using the Logic paradigm

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;}

Page 21: Programming declaratively in C++ using the Logic paradigm

Examples

• Demo

Page 22: Programming declaratively in C++ using the Logic paradigm

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

Page 23: Programming declaratively in C++ using the Logic paradigm

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.

Page 24: Programming declaratively in C++ using the Logic paradigm

Q / A