Prova 3.0 User Guide - May 2010

  • Upload
    vermuz

  • View
    214

  • Download
    0

Embed Size (px)

Citation preview

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    1/94

    ProvaRuleLanguageVersion3.0

    UsersGuide

    Prova is an economic and efficient open source rule

    language for creating distributed collaborating agents.

    Running in Java runtime, it combines Prolog style logic

    inference with extensions for Java scripting, concurrent

    and scalable reactive messaging, workflows and event

    processingsuitableforEnterpriseServiceBusdeployment.

    AlexKozlenkov

    May2010

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    2/94

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    3/94

    1. General language features .............................................................. 1

    1.1. Basiclanguageelements.................................................................................................1

    1.1.1. Simple(atomic)terms.................................................................................................2

    1.1.2. Variables......................................................................................................................2

    1.1.3.Constants

    ....................................................................................................................

    2

    1.1.4. Compoundterms(lists)...............................................................................................3

    1.1.5. Facts............................................................................................................................3

    1.1.6. Rules............................................................................................................................3

    1.2. RunningProvascriptsfromcommandline.....................................................................3

    1.3. RunningProvafromJava................................................................................................4

    1.3.1. PassingJavaobjectstotheinitializationrulebase......................................................5

    1.3.2. PassingJavaobjectstotheaddedrulebasefragment................................................7

    1.3.3.Submitting

    goals

    and

    obtaining

    solutions

    ...................................................................

    7

    1.3.4. Sendingmessagestotherunningrulebase................................................................8

    1.3.5. ProvaServiceasimplerwaytoembedProvaagents...............................................8

    1.3.6. RunningProvainsideanOSGicontainer..................................................................11

    1.3.7. ProvaagentcontractandESBadaptor.....................................................................12

    1.4. CallingJavafromProvarulebases.................................................................................13

    1.4.1. UsingJavatypesandclassesforProvavariables......................................................13

    1.4.2. CreatingJavaobjectsbycallingtheirconstructors...................................................15

    1.4.3.Passing

    Prova

    lists

    as

    arguments

    to

    constructors

    .....................................................

    15

    1.4.4. Invokingstaticmethods............................................................................................15

    1.4.5. Accessingpublicstaticandinstancefields...............................................................15

    1.4.6. UsingspecialbuiltinsthattakeadvantageofcommonJavaclasses.......................15

    1.5. Expressions....................................................................................................................15

    1.6. Globalconstants............................................................................................................16

    1.7. Provamapsfordefiningslottedterms.........................................................................16

    1.8. Metadataannotations..................................................................................................17

    1.9.

    Guardsin

    Prova

    .............................................................................................................

    18

    1.10. Workflowsandbusinessprocesses..............................................................................19

    1.10.1. Simplegateways...................................................................................................19

    1.10.2. Eventdrivengateways(edBPM)...........................................................................21

    1.10.3. Predicategateways...............................................................................................23

    1.11. Functionalprogrammingextensions............................................................................25

    1.11.1. Representingfunctions.........................................................................................25

    1.11.2. Functionalcomposition.........................................................................................26

    1.11.3.

    Lambdafunctions

    ..................................................................................................

    26

    1.11.4. Simplefunctionalcomposition.............................................................................27

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    4/94

    2

    1.11.5. Monadicfunctionalcomposition..........................................................................28

    1.12. Builtinsreference..........................................................................................................28

    2. Reactive messaging ..................................................................... 47

    2.1. Designprinciples...........................................................................................................47

    2.2.

    Sendingmessages

    .........................................................................................................

    47

    2.2.1. Positionbasedarguments........................................................................................47

    2.2.2. SynchronizedmessagesendingwithsendMsgSync.................................................50

    2.3. Usingreactionrulesforreceivingmessages.................................................................51

    2.3.1. Globalreactionrules.................................................................................................51

    2.3.2. Inlinereactionrules..................................................................................................52

    2.3.3. Controllingthemessagereactionmultiplicity..........................................................52

    2.3.4. Explicitterminationofinlinereactions.....................................................................53

    2.4.

    Guardsin

    message

    processing

    ......................................................................................

    54

    2.5. Concurrentreactivemessaging....................................................................................54

    2.6. Annotationsformessagereceiving...............................................................................58

    2.7. ReactivemessagingforJavaSwing...............................................................................59

    3. Event processing ......................................................................... 60

    3.1. Eventprocessingusingreactiongroups.......................................................................60

    3.1.1. Whiteboxorworkfloweventprocessing.................................................................61

    3.2. Structureofreactiongroups.........................................................................................61

    3.3.

    Annotationsfor

    reaction

    groups

    ...................................................................................

    63

    3.4. Lifecycleofreactiongroupinstances............................................................................74

    3.5. ContextvariableswithequalityandWHEREconstraintsinANDgroups.....................77

    3.6. Dynamiceventchannels...............................................................................................80

    3.7. EPTSLanguageWorkingGroup.....................................................................................82

    3.7.1. Flowerdeliveryexample...........................................................................................82

    3.8. Glossary.........................................................................................................................89

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    5/94

    Pro

    1.Ge1.1.

    Alth

    Reader

    givena

    The

    simples

    new sy

    refactor

    increme

    languag

    quality

    The

    Att

    arulelangu

    nerallaBasiclanoughthero

    willneed to

    ditionalse

    syntactic si

    yntaxiseasi

    ntactic refin

    ing.The ide

    ntally,with

    es that fost

    xecutables

    followingdi

    hetoplevel,

    age3.0

    guagefuageelem

    otsofProva

    keepano

    anticsand

    mplicityof

    iertocompr

    ements ea

    alhere is t

    minimalcha

    erquick ex

    stems.

    agramcapt

    Provaoffer

    aturesents

    lieinlogic

    enminda

    andomuch

    he languag

    ehendand

    ily availabl

    atofadev

    ngestothe

    erimentatio

    resthemai

    threebasic

    UsersG

    rogrammin

    daccept th

    morethan

    isentirely

    ostimport

    via linear

    eloper thin

    existingcod

    n and yet,

    nlanguagee

    syntacticst

    uide

    g(LP),thesi

    at syntactic

    inatypicalP

    intentional

    antly,easier

    code chan

    ingabouta

    e.Thelangu

    in the best

    lements.

    ructuresfor

    milaritycan

    structures

    rologlikela

    andmotiva

    toscaleup

    es as opp

    new functi

    ageisthus

    examples, li

    puttingtog

    bedeceptiv

    amiliar fro

    nguage.

    tedby the i

    andbackdo

    sed to co

    nalityand

    arcloserto

    ike Ruby, yi

    theraruleb

    ay2010

    e,sothe

    LP,are

    dea that

    wn,with

    plicated

    adding it

    scripting

    ld high

    ase:

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    6/94

    Provarulelanguage3.0 UsersGuide May2010

    2

    rules,

    facts(ruleswithnobody),

    goals(ruleswithnohead).

    Thesearebuiltattheelementallevelfrom

    atomicterms,

    compoundterms

    (lists).

    Letustalkabouttheminabottomupfashion.

    1.1.1.Simple(atomic)termsProva includes two types of simple terms: constants and variables. Internally, they are Java

    interfacesProvaConstantandProvaVariable,respectively.

    1.1.2.VariablesProvavariablesareessentiallyhollowpointersthatareyettobegivensomevalueassignment.

    Oncethevalue isassigned,thevariablebecomesaconstantterm,that isadatawrapperarounda

    Javaobject.Onceaconstantisassigned,inatypicallogicandfunctionalprogrammingway,itcannot

    beassigned

    some

    other

    data.

    However,

    ifafailure

    (inability

    to

    prove

    anew

    sub

    goal)

    is

    detected

    during the goal evaluation, backtracking may result in alterantive branching, and therefore,

    alternativeassignmentstovariables.Assignmentofvaluestovariablesultimately isthemainpoint

    ofrunningaProvarulebase,i.e.,providinganswerstoquestions(goals)thatarebeingasked.

    AsopposedtotypicalPrologsystems,variablescanbetyped(seethediscussion inCallingJava

    from Prova rulebases). Previous versions of Prova also allowed variables tobe typedusingOWL

    ontologies.ThisfeatureisnotavailableinProva3.0butwillreturninthenextversion.

    Syntactically,ascommon inProlog,variablesarerepresentedbytokensstartingwithacapital

    letter, in the case of typed variables, prefixed by fully qualified package and class name of the

    corresponding Java class. It is also possible to use anonymous variables that begin with the

    underscorecharacter.SomeexamplesofProvavariablesfollow.

    APayloadInteger.Icom.betfair.prova.domain.Market.M_

    1.1.3.ConstantsConstantsmayincludenumericdatausingtheJavasyntax,stringsinsingleordoublequotes,as

    well as fullyqualified staticor instance fields in Javaobjects. Singleword strings thatbeginwith

    lowercaseletterareforallpurposesthesameassuchstringsinquotes.12300L

    3.0e

    9

    test'test'"test"

    It is important to understand that during the execution of a Prova rulebase, variables get

    assigned values essentially becoming constants. In this case, however, these variables are

    syntacticallyrepresentedasvariables,yetforallpurposes,behavelikeconstants.Forexample,going

    slightlybeyond the scopeof thissubsection, thisassignmentsets thevariable toaconstant,and

    subsequentreassignmentofthesamevariablefails.I=2,I='cannotassign'

    Specialglobalconstantshavenamesstartingwith'$'asbelow.

    $Count.addAndGet(Delta)

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    7/94

    Provarulelanguage3.0 UsersGuide May2010

    3

    1.1.4.Compoundterms(lists)Compoundtermsare inProvarepresentedasgenericProva lists.This lendsitselfwelltoagent

    programmingasanyinformationcanbeeasilydistributedwithagentssendingeachotherProvalists.

    Critically, and uniquely different from typical LP languages, Prova keeps lists in arrays instead of

    recursivelists.

    Listsare

    represented

    in

    astandard

    Prolog

    way

    as

    [Head|Rest]

    Here Head is one or more (commaseparated) elements that are the list's starting (prefix)

    elements. The Rest is the list tail, thatmost often isjust a variable thatwillmatch against the

    remainderofthelist.Theverticalbaristhenthesameastheconsoperatorinfunctionallanguages.

    Listsareaninvaluabletoolforpatternmatching,sothatwecansay,wewantthoseelementstobe

    thereinthelistandunification,whichisthecoreoperationinProva,willmatchthelistsandassign

    valuestofreevariablesasappropriate.

    1.1.5.FactsAProva fact is essentially a relation tuple (a record)with its elementsbeing any term, be it

    constant,variable,

    or

    a(possibly

    recursive)

    list.

    This

    is

    different

    from

    standard

    Prolog,

    where

    facts

    normallycannothavevariables.Moreover, factscanhaveembedded Javaobjects,orevenglobal

    constants.Factshavethefollowingformat.predicate(arg1,...,argn).

    Itisoftenthecasethattherearemorethanonefactforagivenpredicatesymbol.alert_destination(no_bids,store2).alert_destination(no_bids,store_manager2).

    1.1.6.RulesProvarulestypicallyareHornrulesthatare firstorderdisjunctionsof literalswithexactlyone

    positiveliteral.Inlogics,suchHornrulesareknownasdefiniteclauses.Thewordtypicallyhighlights

    the

    fact

    that

    in

    Prova,

    global

    reaction

    rules

    look

    exactly

    like

    Prova

    rules

    (with

    head

    literal

    for

    predicate symbol rcvMsg) but their semantics aremore aligned with reactive rules rather than

    derivationrules.

    RulesarewritteninthestandardProloglikeway.Where':'ispronouncedasIF.head_literal(args_h): body_literal1(args_1), ..., body_literaln(args_n).

    1.2. RunningProvascriptsfromcommandlineThenewProvamain()ishostedbytheProvaCommunicatorImplclass.Currently,itrequiresthe

    followingcommandlinearguments:

    1. agentname,2. password(unusedfornow),3. startingrulebase(withpossiblyincludedgoalsthatareimmediatelyrunsynchronously).

    Optionally,thetimeoutfortheagentcouldbespecifiedafterthatwitht.

    Specifying theoption t 1 allows the agent to run indefinitely, accepting goals asmessages and

    respondingbyotheractions.Ifthetimeoutparameterisnotprovided,theengineexecutesallgoals

    in the starting rulebaseand then ifno internalmessageswere sent (as is the casewitha typical

    rulebase thathasnomessage sendingor receiving), it exits to the command shell.Otherwise, it

    looksforonesecondlongperiodofinactivitywhennomessagesaredetectedandthenexitstothe

    commandshell.

    ThebinaryProvadistributionallowsrunningthenewProvainterpreterfromcommandlineusing

    prova3.bat[t]arg0arg1...argN

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    8/94

    Provarulelanguage3.0 UsersGuide May2010

    4

    The list of commandline arguments is passed to the starting rulebase as global constants:

    $0,$1..,$N.

    Hereisanexampleoftheargumentspassedtotherunner:agentpasswordtest001_args.provaanticoagulant

    The

    following

    rulebase

    test001_args.prova

    then

    prints

    one

    solution

    Parent=molecular_function.

    is_a("anticoagulant","molecular_function").

    %Rules(howtoderivenewknowledge)parent(X,Y):%XisparentofYIFYisa(kindof)X is_a(Y,X).parent(X,Y):%XisparentofYIFXhasaY has_a(X,Y).

    %Goal(whattodo/whattoderive)%WhoisParentof"anticoagulant"?:solve(parent(Parent,$0)).

    1.3. RunningProvafromJavaProva iswritten in Java but clearly, there needs to be away for a generic Java program to

    somehow 'initialise'aProvaagentandinteractwith it.TheProvaagentthatservesthispurpose is

    ProvaCommunicatorImpl, an implementation of the interface ProvaCommunicator. In the test

    directory for the new Prova, test.ws.prova.test2,not alltests are created equal. Some work on

    primitiveconstructs,explicitlycreatingvariablesorrules fromscratch.Wedonotwanttodo that

    here so let's create a ProvaCommunicator instance and give it a spin. When you create a

    ProvaCommunicator,there isonemainquestionyouneedtoanswer,whatrulebasetheagentwill

    initially run? Let's look at the test capture_enum() in test.ws.prova.test2.ProvaBuiltins1.java

    reproducedbelow:staticfinalStringkAgent="prova";

    staticfinalStringkPort=null;

    @Testpublicvoidcapture_enum(){ finalStringrulebase="rules/reloaded/test017.prova"; finalint[]numSolutions=newint[]{2}; ProvaCommunicatorprova=new

    ProvaCommunicatorImpl(kAgent,kPort,rulebase,ProvaCommunicatorImpl.SYNC); Listsolutions=prova.getInitializationSolutions(); org.junit.Assert.assertEquals(solutions.size(),1); org.junit.Assert.assertEquals(solutions.get(0).length,numSolutions[0]);

    org.junit.Assert.assertTrue(solutions.get(0)[0].getNv("Groups")

    instanceof

    ProvaList);

    }

    This is the simplestway to callProva from Java.We createaProvaCommunicatorImpl,passing it

    (apart from theuniqueagentnameandport,discussedelsewhere), the rulebase tobe consulted

    and indicating that theagentwillbe run ina synchronousmode.At the timeofwriting, this last

    parameter is in fact, ignored. If the initial rulebase has any goals, they are run right in the

    ProvaCommunicatorImpl constructor, making their results available when the client calls

    ProvaCommunicator.getInititalizationSolutions().ThismethodreturnsaList,which

    isalistofsolutionarrays,oneeachforeachgoalinsidetheinitialisationrulebase.Sointhecurrent

    example,wehaveonegoalandtwosolutionsforthatgoal.EachProvaSolutioncontainsname/value

    pairscorrespondingtovariables'binding.Thecorrespondingrulebaseisshownbelow.:solve(test017(Groups)).

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    9/94

    Provarulelanguage3.0 UsersGuide May2010

    5

    test017(Groups): Text="Adoodleisadoddle", %nondeterministicallyenumerateregularexpressiongroups capture_enum([Text,"(d?)(dl)"],Groups).

    1.3.1.PassingJavaobjectstotheinitializationrulebase

    JavaobjectscanbepassedtotheProvaengineinavarietyofways.Inparticular,youcanembed

    Java objects directly into the initialization rulebase, i.e., the rulebase consulted when the

    ProvaCommunicator is constructed, creating a Prova engine instance. The following code from

    ProvaBuiltins1Test.javademonstrates. @Test publicvoidread_enum(){ finalStringrulebase="rules/reloaded/read_enum.prova"; finalint[]numSolutions=newint[]{5};

    Mapglobals=newHashMap(); globals.put("$File",rulebase);

    ProvaCommunicator

    prova

    =new

    ProvaCommunicatorImpl(kAgent,kPort,rulebase,ProvaCommunicatorImpl.SYNC,globals); Listsolutions=prova.getInitializationSolutions();

    org.junit.Assert.assertEquals(1,solutions.size()); org.junit.Assert.assertEquals(numSolutions[0],solutions.get(0).length); }

    Thiscodepassesamapglobalswithnamedconstants (inthisexample,$File)totheconsulted

    rulebaseread_enum.provashownbelow.:solve(test_read_enum_1(Line)).

    test_read_enum_1(Line):

    fopen($File,Reader),

    read_enum(Reader,Line).

    Therulebaseopensthefilegiventhesuppliedfilename.AnyJavaobjectscanbepassedtothe

    rulebaseinthisway.Forexample,youcandirectlyembedarbitraryJavaobjectsintoProvafactslike

    this.customer(1234,$c1).

    Dealingwithexceptions

    Ifexceptionsoccurduringthe initialization,theenginewrapsthem inaRuntimeExceptionwith

    theappropriateunderlyingexceptionreportedasitscause.Thefollowingtestshowsafailuredueto

    non

    existence

    of

    the

    consulted

    rulebase.

    @Testpublicvoidinitialization_from_nowhere(){ finalStringrulebase="rules/reloaded/NOSUCHFILE.prova";

    try{ comm=newProvaCommunicatorImpl(kAgent,kPort,rulebase,ProvaCommunicatorImpl.SYNC); }catch(Exceptione){ finalStringlocalizedMessage=e.getCause().getLocalizedMessage(); org.junit.Assert.assertEquals( "Cannotreadfromrules/reloaded/NOSUCHFILE.prova", localizedMessage);

    }

    }

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    10/94

    Provarulelanguage3.0 UsersGuide May2010

    6

    Ifthereareparsingerrors,thewrappedexceptionisaProvaParsingException.Thisexceptionhas

    twofieldsthatprovidefurther information:srcanderrors, i.e,thefileoriginoftherulebaseanda

    collectionofactualparsingerrors.Thiscollectionmaps linesandoffsets in format line:offset toa

    textualdescriptionoftheencounteredparsingerrorasreportedbytheparser.Thefollowingcode

    fragmentillustrates.

    @Testpublicvoidinitialization_with_parsing_errors(){ finalStringrulebase="rules/reloaded/parsing_errors.prova";

    try{ comm=newProvaCommunicatorImpl(kAgent,kPort,rulebase,ProvaCommunicatorImpl.SYNC); }catch(Exceptione){ org.junit.Assert.assertTrue(e.getCause()instanceofProvaParsingException); org.junit.Assert.assertEquals( "rules/reloaded/parsing_errors.prova", ((ProvaParsingException)e.getCause()).getSource()); org.junit.Assert.assertEquals(5,((ProvaParsingException)e.getCause()).errors().size());

    }

    }

    Finally, if an exception occurs inside the rulebase, for example, caused by a failedmethod

    invocation, the exception is also wrapped in a RuntimeException. The following rulebase

    processing_errors.provathrowsaNoSuchMethodException.

    :solve(p(X)).

    p(X): A=java.util.HashSet(), A.nomethod().Thetestbelowshowshowtodetectthisexception.

    @Testpublicvoidinitialization_with_rulebase_errors(){ finalStringrulebase="rules/reloaded/processing_errors.prova";

    try{ comm=newProvaCommunicatorImpl(kAgent,kPort,rulebase,ProvaCommunicatorImpl.SYNC); }catch(Exceptione){ finalStringlocalizedMessage=e.getCause().getLocalizedMessage(); org.junit.Assert.assertEquals( "Nosuchaccessiblemethod:nomethod()onobject:java.util.HashSet", localizedMessage); }}

    Modifyingtherulesinarunningengine

    When a Prova engine instance is active, i.e, the ProvaCommunicator object is successfully

    constructed,thelattercanbeusedforaddingandremovingadditionalfactsorrulestotherunning

    rulebase.Ifthenewconsultedcodecontainsgoals,thesegoalswillthenbeexecuted.TheexamplebelowshowstheuseoftheProvaCommunicator.consultSyncmethodtoaddanew

    fragmenttotherunningrulebase.

    StringinputRules="dissemination(Person,public_reports):clearance(Person,low).";BufferedReaderinRules=newBufferedReader(newStringReader(inputRules));

    try{

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    11/94

    Provarulelanguage3.0 UsersGuide May2010

    7

    comm.consultSync(inRules,"disseminationrules",newObject[]{});}catch(Exceptione){ //TODO:processexceptions}

    Themethodtakesthreeparameters:

    1. eitheraStringorBufferedReaderwitharulebasefragmentinProva;2. aStringwiththelogicalnamegiventotherulebasefragment;3. anarrayofJavaobjectstoreplaceanyplaceholdersembeddedinthefragment.

    Thecallmayraiseexceptionsthattheuserisrequiredtoprocess.

    Removingorreplacingthecode

    The name of the rulebase fragment can be used later for removing the previously added

    fragment.

    //Removeallclausesconsultedforthiskeycomm.unconsultSync("disseminationrules");

    Thefragmentcanbetheneasilyupdatedbyconsultingitagainwithanewversioninaseparate

    step.

    1.3.2.PassingJavaobjectstotheaddedrulebasefragmentThesourcecodesubmittedtoconsultSynccancontainplaceholders inthesyntax_0,...,_nthat

    thecallwillreplacewiththeJavaobjectssuppliedinthethirdparameterintherulebase.

    Stringinput="robot(_0).";BufferedReaderin=newBufferedReader(newStringReader(input));

    try{ comm.consultSync(inRules,"robotrules",newObject[]{newRobot("Dave")});}catch(Exceptione){

    //

    TODO:

    process

    exceptions

    }

    Thisisactuallymorepowerfulthanwhatyoucandofromarulebaseconsultedfromanexternal

    file during initialization because to embed a Java object in a factwould have required explicitly

    constructingaJavaobjectandaddingafactdynamicallyusingassert.

    Robot=com.independentrobots.Robot(),assert(robot(Robot))

    1.3.3.SubmittinggoalsandobtainingsolutionsIfthefragmentrulebasecontainsclausesformetapredicatesevalorsolve,theyareexecutedas

    newgoals.

    The

    solutions

    resulting

    from

    the

    solve

    goals

    (eval

    do

    not

    produce

    any

    solutions)

    are

    returnedinaListinthesamewayitworksforinitializationsolutions.

    Stringinput=":solve(dissemination(Person,public_reports)).";BufferedReaderin=newBufferedReader(newStringReader(input));

    try{ ListresultSets=comm.consultSync(in,Integer.toString(key++),newObject[]{}); for(ProvaSolution[]resultSet:resultSets){ org.junit.Assert.assertEquals(numSolutions[i++],resultSet.length); }}catch(Exceptione){

    //

    TODO:

    Process

    exceptions

    }

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    12/94

    Provarulelanguage3.0 UsersGuide May2010

    8

    1.3.4.SendingmessagestotherunningrulebaseTherearetwowaystosendamessagetotherunningProvarulebasefromJava.The lowlevel

    ProvaCommunicator.addMsgmethodcanbeusedforsendingamessageconstructedfromaProva

    termexplicitlybuiltfromthebasicbuildingprimitives,suchasconstantsorlists.Theexamplebelow

    demonstrates.

    //Send

    ahundred

    messages

    to

    the

    consulted

    Prova

    rulebase.

    //Processingisdoneconcurrentlyonthreadsbelongingtotheasyncpool.for(inti=0;i

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    13/94

    Provarulelanguage3.0 UsersGuide May2010

    9

    *NotethatthisrunsinplainJavanoOSGicontainerisactuallyrequired.**TherunnerimplementsEPServiceforProvaenginestobeabletosendmessagestotherunner,*notjustbetweenthemselves.**@authorAlexKozlenkov

    */

    publicclassProvaSimpleServiceimplementsEPService{ staticfinalStringkAgent="prova"; staticfinalStringkPort=null; finalStringsender_rulebase="rules/service/message_passing/sender.prova"; finalStringreceiver_rulebase="rules/service/message_passing/receiver.prova"; privateProvaServiceservice;

    publicProvaSimpleService(){ service=newProvaServiceImpl(); service.init(); }

    private

    void

    run()

    {

    //CreatetwoProvaagentsintheirownengines Stringsender=service.instance("sender",""); Stringreceiver=service.instance("receiver","");

    //Consultonerulebaseintoeach service.consult(receiver,receiver_rulebase,"receiver1"); //Makesuretheconsumerhasaccesstoaglobalobjectforcounting AtomicIntegercount=newAtomicInteger(); service.setGlobalConstant(receiver,"$Count",count); service.consult(sender,sender_rulebase,"sender1");

    //

    Send

    a

    message

    directly

    from

    this

    runner

    Mappayload=newHashMap(); payload.put("a",2); //Thisrunnernamesitselfas"runner"agentinthiscall(seethethirdargument). //ThisEPServiceimplementationispassedinthelastargument. //TheservicewillthenregisteranEPServicecallbacksothatagentswillbeableto //sendmessagestothisrunnersettingthedestinationto"runner". service.send("xid","receiver","runner","inform",payload,this);

    try{ synchronized(this){ wait(2000); //Verifythatthecounthadbeenincremented

    assert(count.get()==2);

    } }catch(Exceptione){ } System.out.println("Confirmedthatthemessageshavebeenreceived");

    //Bringbothenginesdown:ifwehadnotdonethat,bothagentswouldhavecontinuedindefinitely

    service.destroy(); }

    /** *ThisisacallbackthatiscalledwhenaProvaengine(seereceiver.prova)sendsamessagetothis

    runner */

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    14/94

    Provarulelanguage3.0 UsersGuide May2010

    10

    @Override publicvoidsend(Stringxid,Stringdest,Stringagent,Stringverb, Objectpayload,EPServicecallback){ System.out.println("Received"+verb+"from"+agent+":"+payload); }

    public

    static

    void

    main(

    String[]

    args

    )

    {

    newProvaSimpleService().run(); }}Thisrunnercodeusestworulebasesbelow.Thisisa"receiver"agentinrules/service/receiver.prova.:eval(receiver()).

    receiver(): rcvMult(XID,Protocol,From,inform,{a>I}), println(["Received",{a>I}]), $Count.incrementAndGet(),

    %ThisonlymakessenseifrunfromProvaSimpleService.java

    sendMsg(XID,osgi,runner,inform,{a

    >I}).

    Thisisa"sender"agentinrules/service/sender.prova.:eval(sender()).

    sender(): sendMsg(XID,osgi,receiver,inform,{a>1}).

    When the runner code is initialized in the ProvaSimpleService constructor, it creates and

    initializesaProvaServiceinstance.ItthencreatestwoProvaagentsusingtheProvaService.instance()

    methodand thenusesthemethodconsulttoadd theProvarulebases to thoseagents.When the

    rulebasesareconsulted,theyruntheirevalgoalswiththesendersendingandthereceiverreceiving

    amessage. For the agents to be "visible" to each other, theymust communicate via the "osgi"

    protocol(thesecondargumentinsendMsgandrcvMsg).

    Using a global object count is only needed in this slightly contrived example:we use it for

    incrementingthecountofexpectedmessages(see$Count.incrementAndGet()inreceiver.prova)and

    checkingthiscountfromtheJavacode.

    Theexample alsodemonstrates thatwe canboth sendmessages to the selected agents and

    receivemessagesbackfromtheJavacode.Forthistowork,thekeyistopassachosennameofthe

    containing"agent"tothe_ProvaService.send()_method:

    service.send("xid","receiver","runner","inform",payload,this);

    ProvaService registers the name "runner" against the callback object passed as the last

    parameter.Note that the ProvaSimpleService implements the EPService interface, allowing it the

    ProvaagentstocallbackontheEPService.send()methodwhentheneedtosendmessagesbackto

    thecontainingagent.ObservethesendMsgwithdestination"runner"inreceiver.prova.

    sendMsg(XID,osgi,runner,inform,{a>I}).Also,observetheuseofJavaMapforpassingmessagepayloadsbetweenallparties, including

    the embedding agent. This improvesperformance and yet allows for considerable flexibility (see

    Provamapsandmessagingusingslottedterms).

    Thisisatypicaloutputfromrunningthisprogram.ProvaService7faee1dea6e1421dac2e97709ba47196created==========Servicemessagingtest:receiver====================Servicemessagingtest:sender==========Received{a=1}Received{a=2}Receivedinformfromreceiver:{a=1}

    Received

    inform

    from

    receiver

    :{a=2}

    ConfirmedthatthemessageshavebeenreceivedProvaService7faee1dea6e1421dac2e97709ba47196destroyed

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    15/94

    Provarulelanguage3.0 UsersGuide May2010

    11

    To summarize, we are able to exchange messages between all parties: the Java code

    representinganembeddingagentandtheembeddedProvaagents.Themessagescanflow inany

    directionbetweenallpartieswithonlylogicalagentnamesrequiredasdestination.

    1.3.6.RunningProvainsideanOSGicontainerProva

    3.0

    is

    packaged

    as

    an

    OSGi

    bundle

    that

    can

    expose

    aProva

    service

    and

    necessary

    domain

    classes accessible from other bundles in an OSGi container. We use METAINF/MANIFEST.MF

    reproducedbelowfordeclaringthebundledependenciesanddeclaringpackagesandservicesuseful

    forotherbundles.ManifestVersion:1.0BundleVersion:3.0.0BundleName:ProvacompactBundleManifestVersion:2BundleDescription:ProvaruleenginecompactBundleSymbolicName:ws.prova.compactBundleRequiredExecutionEnvironment:J2SE1.5ImportPackage:org.osgi.framework;version="1.3.0",

    org.apache.commons.collections;version="3.2.1",

    org.apache.commons.beanutils;version="1.8.0",org.apache.log4j;version="1.2.15"RequireBundle:com.springsource.org.antlr.runtime;bundleversion="3.1.3"ExportPackage:ws.prova.service;version="3.0.0",ws.prova.api2;version="3.0.0",ws.prova.exchange;version="3.0.0",ws.prova.exchange.impl;version="3.0.0"BundleClassPath:.,target/classes/,rulesBundleActivationPolicy:lazy

    Aswecansee,thenumberofdependenciesthatProvareliesonisverysmall.WealsouseSpring

    DMcontext

    configurations

    in

    META

    INF/spring

    to

    make

    ProvaService

    available

    to

    other

    bundles

    as

    a

    service.WhenanOSGitargetplatformstarts,itexposestheProvaServiceasanOSGiservicewithout

    ushavingtohaveanydependencyorcouplingintheprojectitselfonOSGiorSpring.

    Youcandownloadtheplatformfrom:http://www.prova.ws/downloads/platform.zip.Unzipitto

    adirectoryandfromEclipsegotoWindow/Preferences/Plugindevelopment/Targetplatformand

    createandchooseanew targetplatformusing thedirectoryyouexpanded theplatformbundles

    into.

    Check out the Prova Eclpse project from

    https://mandarax.svn.sourceforge.net/svnroot/mandarax/prova3/provacompact/trunk and run

    mvncleaninstall DskipTestsfromcommandline.RefreshtheprojectinEclipse.

    YoucanruntheProvabundleinanOSGicontainerbyfirstcreatinganewrunconfigurationby

    goingto

    Run/Run

    configurations.../OSGi

    Framework

    including

    the

    Prova

    bundle

    from

    the

    Prova

    projectinadditiontoallthebundlesincludedinthe importedplatform.Runningthisconfiguration

    willoutputsomethinglikethistotheconsole:osgi>0[StartLevelEventDispatcher]INFO

    org.springframework.osgi.extender.internal.activator.ContextLoaderListenerStarting[org.springframework.osgi.extender]bundlev.[1.2.1]

    90[StartLevelEventDispatcher]INFOorg.springframework.osgi.extender.internal.support.ExtenderConfigurationNocustomextenderconfigurationdetected;usingdefaults...

    99[StartLevelEventDispatcher]INFOorg.springframework.scheduling.timer.TimerTaskExecutorInitializingTimer

    185[StartLevelEventDispatcher]INFO

    org.springframework.osgi.extender.support.DefaultOsgiApplicationContextCreatorDiscovered

    configurations{osgibundle:/METAINF/spring/*.xml}inbundle[Provacompact(ws.prova.compact)]

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    16/94

    Provarulelanguage3.0 UsersGuide May2010

    12

    357[SpringOsgiExtenderThread1]INFOorg.springframework.osgi.context.support.OsgiBundleXmlApplicationContextRefreshingOsgiBundleXmlApplicationContext(bundle=ws.prova.compact,config=osgibundle:/METAINF/spring/*.xml):startupdate[ThuApr2913:54:59BST2010];rootofcontexthierarchy

    358[SpringOsgiExtenderThread1]INFOorg.springframework.osgi.context.support.OsgiBundleXmlApplicationContextApplicationContextservice

    alreadyunpublished

    426[SpringOsgiExtenderThread1]INFOorg.springframework.beans.factory.xml.XmlBeanDefinitionReaderLoadingXMLbeandefinitionsfromURL[bundleentry://59.fwk1384828782/METAINF/spring/modulecontext.xml]

    755[SpringOsgiExtenderThread1]INFOorg.springframework.beans.factory.xml.XmlBeanDefinitionReaderLoadingXMLbeandefinitionsfromURL[bundleentry://59.fwk1384828782/METAINF/spring/moduleosgicontext.xml]

    907[SpringOsgiExtenderThread1]INFOorg.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutorNooutstandingOSGiservicedependencies,completinginitializationforOsgiBundleXmlApplicationContext(bundle=ws.prova.compact,config=osgibundle:/METAINF/spring/*.xml)

    911[SpringOsgiExtenderThread2]INFOorg.springframework.beans.factory.support.DefaultListableBeanFactoryPreinstantiatingsingletonsinorg.springframework.beans.factory.support.DefaultListableBeanFactory@57c8b24d:

    defining

    beans

    [provaService,org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean#0];rootoffactoryhierarchy

    ProvaService090128f4d886400aa63185088bdd08e0created996[SpringOsgiExtenderThread2]INFO

    org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBeanPublishingserviceunderclasses[{ws.prova.service.ProvaService}]

    999[SpringOsgiExtenderThread2]INFOorg.springframework.osgi.context.support.OsgiBundleXmlApplicationContextPublishingapplicationcontextasOSGiservicewithproperties{org.springframework.context.service.name=ws.prova.compact,BundleSymbolicName=ws.prova.compact,BundleVersion=3.0.0}

    1006[SpringOsgiExtenderThread2]INFO

    org.springframework.osgi.extender.internal.activator.ContextLoaderListener

    Application

    context

    successfullyrefreshed(OsgiBundleXmlApplicationContext(bundle=ws.prova.compact,config=osgibundle:/METAINF/spring/*.xml))

    ThisconfirmsthattheProvabundlestartedsuccessfully.

    1.3.7.ProvaagentcontractandESBadaptorThewaytostartaProvaenginefromJavadescribedinthepreviousSectiondoesnotfollowany

    particularpattern. Inparticular, there isnoway for theProva rulebase to takeanactive roleand

    communicatewiththeembedding Javacode,apart frompassingacallbackobjectto therulebase

    andthelatterinvokingthecallbackwhentherulebaseneedstosenddata.

    Prova3.0 includes the following simpleProvaAgent interface that imposes a contracton the

    adaptorJavaobjectthatembedsaProvaengineinstance.Inaseparatemuleprovaagentsproject,

    weuse

    aMule

    2.1

    Enterprise

    Service

    Bus

    implementation

    of

    this

    contract.

    This

    allows

    Prova

    agents

    tobeprovisionedbytheMuleESBconfigurationandcommunicatewitheachotherviaavariatyof

    transportssupportedbyMule.IfanotherESB(orequivalent)implementationisrequired,allthatis

    requiredisimplementingtheProvaAgentinterfacedescribedbelow.

    publicinterfaceProvaAgent{ publicvoidsend(Stringdest,ProvaListterms)throwsException; publicStringgetAgentName();}

    We recommendconsulting theProva3AgentImpl.javacode foran implementationsuitable for

    MuleESBasitprovidesasimpleexampleoftherequiredfunctionality.AsdescribedintheSending

    messages(in

    particular,

    see

    the

    discussion

    on

    Protocol),

    the

    agent

    rulebase

    sending

    messages

    using

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    17/94

    Provarulelanguage3.0 UsersGuide May2010

    13

    the"esb"protocolwillautomaticallyhitthemethodProvaAgent.send,whichthenwillpublishthem

    intotheESBlayertotheindicateddestination.

    @Overridepublicvoidsend(Stringdest,ProvaListterms)throwsException{ MuleClientclient=newMuleClient();

    client.dispatch(dest,terms,null);}

    Conversely,allmessagesreceivedbytheagentwill indicatethereceivedprotocolas"esb"but

    typicallywilloverride thatwith the "async"protocol to allow for the same conversationid tobe

    mappedtothesameagentthread.

    publicObjectonCall(MuleEventContextcontext)throwsException{MuleMessageinbound=context.getMessage();ProvaListterms=null;if(inbound.getPayload()instanceofObjectMessage){ terms=(ProvaList)((ObjectMessage)inbound.getPayload()).getObject();}else{

    terms

    =(ProvaList)

    context.getMessage().getPayload();

    }

    //AddthemessageasagoaltotheasynchronousProvaCommunicatorqueueif(!"".equals(targetProtocol)){ terms.getFixed()[1]=newProvaConstantImpl(targetProtocol);} comm.addMsg(terms);

    //Wearedone,everythingisasynchronous context.setStopFurtherProcessing(true);

    return

    null;

    }

    1.4. CallingJavafromProvarulebasesProvaagentsrun inJavaso it isnaturalthatProvarulebasescanalsocallhomeandworkwith

    Javadataandobjects.Thisintegrationincludes:

    UsingJavatypesandclassesforProvavariables; CreatingJavaobjectsbycallingtheirconstructors; PassingProvalistsasargumentstoJavaconstructors; Invokingstaticmethods,includingobjectcreationbyusingfactorymethods; Accessingpublicstaticandinstancefields;

    Using

    special

    built

    ins

    that

    take

    advantage

    of

    common

    Java

    classes;

    AddingnewProvabuiltinsinJava.1.4.1.UsingJavatypesandclassesforProvavariables

    AccordingtosomePrologexpertsandimplementers,theansenceofvariablestypinginPrologis

    oneof the reasonsof its relative failure tobecome completelymainstream. Prova takes amore

    practicalapproachbyallowing Javatypesexplicitlyandclearlyannotatingvariablesusingasimple

    syntaxasinthefollowingexamplera001.prova::solve(a(3)).:solve(a(Number.X)).:solve(a(Integer.I)).:solve(a(Short.I)).

    a(Integer.I).

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    18/94

    Provarulelanguage3.0 UsersGuide May2010

    14

    a(Double.I).

    %==================%Thisprints:%yes%X=java.lang.Integer.

    %X=java.lang.Double.

    %I=java.lang.Integer.%no

    Unificationthatincludesvariabletypesfollowsthefollowingsubsumptionrules.

    1. Ifthequery(goal)is'asking'foranarrowertype,itwillnotmatchawidertypeinthetargetliteral.

    2. Awiderquerywillmatchamorespecializedtargetliteral.Observe how uninstantiated variables also benefit from this with the second goal

    solve(a(Number.X))matchinganyapplicablerulesthataremorespecialized.

    Notethatclassesinthejava.langpackagedonotrequiretobefullqualified.Fullyqualifiedclass

    names can also be used in typed variables. The following code shows how the builtins retract,

    retractall,

    and

    insert

    take

    into

    account

    typed

    variables.

    :solve(ra002_1(X,Y)).:solve(ra002_2(X,Y)).:solve(ra002_3(X,Y)).

    f(ws.prova.examples.IBMPortfolio.N,Integer.M).f(ws.prova.examples.Portfolio.N,M).f(ws.prova.examples.IBMPortfolio.N,Integer.M).f(2,3).

    ra002_1(X,Y): println([""]), %Thefirstfactnotmoregeneralthanthisisremovedbyretractbelow

    retract(f(ws.prova.examples.Portfolio.N,M)),

    f(X,Y).ra002_2(X,Y): println([""]), %Factsmoregeneralthanthisarenotremovedbyretractallbelow retractall(f(ws.prova.examples.IBMPortfolio.N,Integer.M)), f(X,Y).ra002_3(X,Y): println([""]), insert(f(ws.prova.examples.Portfolio.N,Integer.M)), %DoesnotaddanythingasitsubsumesafactalreadyintheKB insert(f(ws.prova.examples.Portfolio.N,M)), f(X,Y).

    %==================%Thisprints:%%X=ws.prova.examples.Portfolio.,Y=%X=ws.prova.examples.IBMPortfolio.,Y=java.lang.Integer.%X=2,Y=3%%X=ws.prova.examples.Portfolio.,Y=%X=2,Y=3%%X=2,Y=3

    %

    X=ws.prova.examples.Portfolio.,

    Y=java.lang.Integer.

    %X=ws.prova.examples.Portfolio.,Y=

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    19/94

    Provarulelanguage3.0 UsersGuide May2010

    15

    1.4.2.CreatingJavaobjectsbycallingtheirconstructorsProvaallows Javaconstructorstobe invokedusing the familiat Javasyntax,onlydropping the

    newkeyword.Hereareafewexamples.L=java.util.ArrayList()DF=java.text.SimpleDateFormat("dd/MM/yyyykk:mm:ss.mmm")

    Calendar=java.util.GregorianCalendar()

    1.4.3.PassingProvalistsasargumentstoconstructorsWhenaProvalistispassedasanargumenttoaJavaconstructor,wefollowtheagreementthat

    the toplevel elements in the supplied list are unwrapped if necessary from the Prova constant

    representation to naked Java objects and the list itself is then shipped to the method (or

    constructor)asJava listcontainingtheseobjects.InthecaseofordinaryJavamethodcalls,Prova

    listsarepassedtothelistunchanged.Thisfragmentfromtest004.provaillustrates.List=java.util.ArrayList([1,"2"])

    1.4.4.InvokingstaticmethodsHereisatypicalexampleofastaticmethodinvocation,inthisinstance,thisisafactorymethod.Model=com.hp.hpl.jena.rdf.model.ModelFactory.createDefaultModel()

    1.4.5.AccessingpublicstaticandinstancefieldsPublicstaticfieldscanbeaccessedusingthefamiliarJavasyntax.Thisexampleusesafewpublic

    enumerationsaswellasthestandardoutstreamasaparameterinamethod.Child1=Model.createResource(),Child1.addProperty(com.hp.hpl.jena.vocabulary.VCARD.Given,GivenName),Child1.addProperty(com.hp.hpl.jena.vocabulary.VCARD.Family,FamilyName),JohnSmith.addProperty(com.hp.hpl.jena.vocabulary.VCARD.N,Child1),Model.write(System.out),

    1.4.6.UsingspecialbuiltinsthattakeadvantageofcommonJavaclassesAt the moment, there are two builtin predicates that use Java datamatching appropriate

    interfaces.

    TheelementbuiltincannondeterministicallyextractelementsfrominstantiatedJavaiterators.Iter=Model.listStatements(),element(Stmt,Iter),

    The findall builtin accumulates the resultset of a goal in a JavaArrayList. For example, the

    followingruleaccumulatesallthesolutionsofthegoal [X|Xs] inthenew listL,which isthensent

    backtothecallerasawholeinonereplymessage.%Reactionruletoageneralqueryref_accrcvMsg(XID,Protocol,From,queryref_acc,[ID,[X|Xs]]):

    findall([X|Xs],[X|Xs],L), sendMsg(XID,Protocol,From,reply,[ID,L]).

    1.5. ExpressionsProva 3.0 can handle arithmetic expressions on the righthand side of binary operators. The

    grammarisshownbelow.

    expr :aterm((PLUS|MINUS)expr)?;

    aterm :(MINUS?variable|number|MINUS?predicate_java_call|OPENexprCLOSE)((MULT|DIV|REM)aterm)?;

    predicate_java_call : static_java_call|instance_java_call

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    20/94

    Provarulelanguage3.0 UsersGuide May2010

    16

    ;

    It iscurrently impossibletouseexpressions inargumentsofJavacalls.It isalsonotallowedto

    useJavaconstructorsinexpressionsunlessinisolation.Herearesomeexamples.

    expr001(N,M): N=M+1*2.expr001(N,M): N(M+1)*2.

    expr002(N,M): N=java.lang.Math.min(1,M)+1.expr002(N,M): L=java.util.ArrayList(), L.add(2), N=L.get(0)+L.size().

    1.6. GlobalconstantsGlobal constants is a new functionality in Prova. Look at the following example

    globals001.prova.:solve(globals(N)).

    globals(N): data($A,N).globals(N): $A=b, data($A,N).

    data(a,1).

    data(b,2).

    Anyconstantwithnamestartingwiththe$signisaglobalconstant.Theseconstantsarepartof

    the_ProvaKnowledgebaseImpl_instanceandcanbeinstantiatedpriortoparsinganewrulebaseor

    modified (or added) during the execution of the code. This is accomplished by using the syntax

    $Var=.

    ThecodeaboveisrunfromthenewtestProvaGlobalsTest.globals001()thatinitiallysets$Ato

    'a'soitreturnstwosolutions:1and2.

    The intendeduseof global constants $NNN is forpassing commandline argumentsto Prova

    scripts.Thisfunctionalitywillbeaddedoncethemain()runnerisaddedtothenewProvacode.

    1.7.

    ProvamapsfordefiningslottedtermsSlotted terms isahighlyvaluable featureof languages likeFLogic,standards (RIForRuleML),

    andproducts(likeOOjDREW).Theyalsomake interoperabilitywithforwardchainingrulesystems

    likeJBossRulesfareasier.

    Prova 3.0 includes an implementation of slotted terms using theW3C RIF arrow expression

    syntax as in the following examplemap2.prova.Note that Prova also allows to use colon ':' in

    key:valueinsteadofkey>value.Thekeysarecurrentlylimitedtostrings.:solve(own(X)).

    buy({buyer>'Bill',seller>'Amazon',item>'AvatarBluray'}).

    keep({keeper>'Bill',item>'AvatarBluray'}).

    own({owner>Person,item>Object}):

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    21/94

    Provarulelanguage3.0 UsersGuide May2010

    17

    buy({buyer>Person,seller>Merchant,item>Object}), keep({keeper>Person,item>Object}).

    ThisshowsthatProvamapscanbeusedassoleargumentsofpredicates,essentiallyreplacing

    positionbasedsyntaxwithonebasedonnamedarguments.Theexampleprints:X={item=AvatarBluray,owner=Bill}

    Thetestmap2()inProvaBuiltins1Test.javaisbasedonthisexample.

    Slottedtermsareespeciallyusefulinreactivemessaging,seethediscussiononslottedtermsinreactivemessaging.

    1.8. MetadataannotationsTheoldProvaversionhadaninterestingbutsomewhatpatchyapproachtoruntimeprocessing

    oftherulemetadata.Prova3.0isaimingtoimproveonthis.Thefirstquestioniswhattoannotate

    with metadata? It is clear that all Prova clauses (rules and facts) should be allowed to carry

    metadata.As you'll seebelow,body literals can also be annotated so thatwheneverunification

    occurs,itusesmetadatamatchingifmetadataispresentonthebodyliteral.

    The

    examples

    below

    are

    taken

    from

    a

    new

    test

    rules/reloaded/label.prova.

    This

    is

    the

    way

    metadataisaddedtorules:@label(rule1)r1(X):q(X).@label(rule2)r2(X):q(X).@label(rule3)r2(X):q(X).

    Metadataisasetofannotationseachofwhichisapairdefinedas:@key(value[,value]*).Both

    keys and values are arbitrary strings definedby theiroccurrence in an annotation.All rules in a

    rulebaseconsultedfromafileautomaticallyhaveaspecialannotation@src(FILENAME).Apartfrom

    that,allotherruleannotationsaredefinedbytheuser.Therecouldbemorethanoneuserdefined

    annotationassociatedwithasinglerule.Thereisnorequirementforannotationstobeonthesame

    lineastherulehead.

    Now therewouldn'tbeany realuse for this ifwe couldn't somehow take thismetadata into

    accountwhen

    the

    rulebase

    is

    executed.

    To

    achieve

    that,

    the

    body

    literals

    in

    arule

    can

    be

    optionally

    annotatedaswell.Hereisanexamplethatreturns3solutions(1,2,3):p1(X): @label(rule1) r1(X).q(1).q(2).q(3).

    :solve(p1(X2)).

    The annotationson literals (asopposed to rules) are a setof constraintson the target rules

    duringunification.Foreach literalannotation, theremustbeat leastonematchbetweenavalue

    listedfor

    that

    annotation

    and

    avalue

    listed

    for

    the

    same

    key

    in

    the

    target

    rule.

    This

    is

    amore

    complexexamplethatalsohasthreesolutions(1,2,3):%succeedssincescopeisEITHER"rule2"OR"rule1"p2a(X): @label(rule2,rule1) r1(X).:solve(p2a(X4)).

    Imagine now thatwe do not knowwhat are the target annotation values andwould like to

    discoverandpossiblytracetheannotationsfortargetrulesmatchinga literal.Howabouttryingto

    useavariable insteadofaconstantvalue ina literalannotation?Thefollowingreturns6solutions

    whereLabel6takesvalues'rule2'and'rule3'3timeseach.p4(X,Y):

    @label(Y)

    r2(X).

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    22/94

    Provarulelanguage3.0 UsersGuide May2010

    18

    :solve(p4(X6,Label6)).

    Observethatifamatchisfound,executioncontinuesforr2(X)asthoughthe@labelannotation

    wasnotpresent.

    Now since we have variables in literal annotations, we can also preassign values to these

    variablesdynamically.The following code sets theannotationvalueat runtime to 'rule2' so that

    only

    3

    solutions

    for

    X7

    are

    returned

    (1,2,3).

    %dynamicallysetthemetadatavalueexpectedfrommatchingrules:solve(p4(X7,rule2)).

    Finally,we can also find the rulebaseof the target clause in aunification. The final example

    shows howwe can constrain one annotation (@label)while enquiring on the value of another

    (@src). In thisway, anymatch canbe traced from the source rulebaseof the target clause.This

    returns3solutionswithSrc9settothefilenameoftherulebaseineachsolution.%getmodulelabelp6(X,Y): @src(Y)@label(rule3) r2(X).:solve(p6(X9,Src9)).

    1.9. GuardsinProvaProva 3.0 implements a new inference extension called literal guards. Let's start with an

    example. Imaginethatduringunification,thetargetrulematchesthesource literalbutwedonot

    wanttoproceedwithfurtherevaluationunlessaguardconditionevaluatestotrue.Theguardsare

    specified inasyntax that issimilar to theoneused inErlang (usingbrackets insteadof thewhen

    keyword) but the semantics are more appropriate for a rule language like Prova. See

    rules/reloaded/guard.provaandProvaMetadataTest.java.

    @author(dev1)r1(X):q(X).@author(dev22)r2(X):q(X).@author(dev32)r2(X):s(X).

    q(2).s(2).

    trusted(dev1).trusted(dev22).%Authordev22istrustedbutdev32isnot,soonesolutionisfound:X1=2p1(X): @author(A) r2(X)[trusted(A)].:solve(p1(X1)).

    Thisexampleusesmetadataannotationsonrulesforpredicatesr1/1andr2/1andontheliteral

    r2(X)in

    the

    body

    of

    the

    rule

    for

    p1(X)

    (see

    Metadata

    annotations).

    Since

    variable

    A

    in

    @author(A)

    is

    initiallyfree,itgetsinstantiatedfromthematchingtargetrule(s).OnceAisinstantiatedtothetarget

    rule's @author annotation's value ('dev22', for the first r2 rule), the body of the target rule is

    dynamicallynondestructivelymodifiedtoincludealltheliteralsintheguardtrusted(A)beforethe

    bodystart,afterwhichtheprocessingcontinues.Sincetrusted(dev22) istruebuttrusted(dev32)is

    not,onlythefirstruleforpredicater2isusedandsoonesolutionX1=2isreturnedbysolve(p1(X1)).

    Guards can include arbitrary listsofProva literals including Java calls,arithmeticexpressions,

    relations,andevenCUT.ThenextexampleshowshowCUTcanbeusedintheliteralguard.

    a(X):qq(X).a(X):s(X).

    s(2).

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    23/94

    Provarulelanguage3.0 UsersGuide May2010

    19

    %Thisexampleshowshowguardscanbeusedtoimplementa"dynamicCUT".%TheCUTintheguardisdynamicallysplicedintothestartofthetargetrulebody.%Asqq(X)hasnosolutions,theCUTpreventsfurtherbacktrackingtothesecondrulefora(X):s(X),%thatwouldhaveyieldedasolutionbutdoesnotduetothatdynamicCUT.p2(X): a(X)[!].

    :solve(p2(X2)).

    IftheCUTwasincludedaspartofthep2(X)ruleaftera(X)likeinthefollowingversion,thea(X)

    ruleincludingqq(X)wouldhavefailedbutthesecondrulewouldhaveprovidedonesolution:2.p2(X): a(X),!.

    Provaguardsplayevenamoreimportantroleinmessageandeventprocessingastheyallowthe

    receivedmessagestobeexaminedbeforetheyareirrevocablyaccepted,seethedetailsinGuardsin

    messageprocessing.

    1.10. WorkflowsandbusinessprocessesProvaoffersafairlyuniquecombinationofprocessingtechniques,includingworkflows,reactive

    messaging,event

    processing

    and

    elements

    of

    functional

    programming.

    The

    idea

    is

    to

    give

    the

    users

    agreatfreedomforbuildingdistributedagentsusingaholisticapproachthatdoesnotforcethemtoa

    particularmethodology.

    The following syntactic and semantic instruments in Prova 3.0 capture the basics and offer

    uniqueadvancedfeaturesforimplementingworkflowsandbusinessprocesses.

    inherentnondeterminismfordefiningprocessdivergences; Reactivemessaging; Concurrencysupport,includingpartitionedandnonpartitionedthreadpools; builtinpredicatespawnforrunningtasks; processjoin predicatejoin reactiongroupscombiningeventprocessingwithworkflows(seeeventdrivengatewaysandEventprocessingusingreactiongroups); supportfordynamiceventchannels; guardsThis Section discusses the Prova support for workflows, in particular, both simple and

    sophisticatedlogicbasedpredicategateways.

    1.10.1. SimplegatewaysProva includes a very simple mechanism (inspired by Joincalculus) for creating diverging

    branches (parallel gateway) and processjoin points (inclusive gateways). Consider the following

    simpleworkflowpresentedintheBPMNnotation.

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    24/94

    Pro

    The

    implem

    :ev

    pro

    p

    s

    in

    in

    commun

    fo

    fork

    s

    r

    fo

    fork

    s

    r

    jo

    fork

    s

    r

    jo

    fork

    s

    r

    arulelangu

    following c

    ntthiswor

    al(process_jo

    ess_join():

    intln(["====

    Thismessag

    ndMsg(XID,s

    Theresulto

    Createajoi

    it_join(XID,jo

    Createajoi

    it_join(XID,jo

    Thiswillcre

    NotethatP

    icate

    withother

    rk_a_b(XID).

    a_b(XID):

    Taska

    ndMsg(XID,s

    vMsg(XID,sel

    rk_c_d(XID).

    a_b(XID):

    Taskb

    ndMsg(XID,svMsg(XID,sel

    Tellthejoin

    in(Me,XID,joi

    c_d(XID):

    Taskc

    ndMsg(XID,s

    vMsg(XID,sel

    Tellthejoin

    in(Me,XID,joi

    c_d(XID):

    Taskd

    ndMsg(XID,svMsg(XID,sel

    age3.0

    ode fromp

    flow.

    in()).

    ======proc

    esignalsthe

    elf,0,start,[]),

    theaboveis

    predicatejo

    in_1,[c(_),b(_

    predicatejo

    in_2,[c(_),d(_

    atetwopara

    ovadoesnot

    agentsasyn

    elf,0,reply,a(

    ,Me,reply,a(

    elf,0,reply,b(,Me,reply,b(

    join_1thata

    n_1,b(1)).

    elf,0,reply,c(1

    ,Me,reply,c(

    join_1thata

    n_1,c(1)).

    elf,0,reply,d(,Me,reply,d(

    rocess_join.

    ss_join=====

    startofthec

    thatwenow

    in_1withthe

    ]),

    in_1withthe

    ]),

    llelprocessin

    runthemin

    hronouslyef

    ),corr_a),

    ),corr_a),

    ),corr_b),),corr_b),

    newpattern

    ),corr_c),

    ),corr_c),

    newpattern

    ),corr_d),

    ),corr_d),

    UsersG

    rova uses

    ====="]),

    nversation.

    havethecon

    listofrequir

    listofrequir

    streams.

    eparatethr

    ectivelyallo

    isready

    isready

    uide

    the builtin

    Theenginein

    versationid

    edinputpatt

    edinputpatt

    adsbutthey

    ingforpara

    predicates

    itializesthec

    IDinitialise

    ernsinthela

    ernsinthela

    areindepend

    llelprocessin

    init_join an

    onversation

    .

    stargument.

    stargument.

    entandcan

    g.

    ay2010

    20

    join to

    idXID.

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    25/94

    Provarulelanguage3.0 UsersGuide May2010

    21

    join(Me,XID,join_2,d(2)).

    %Thefollowingrulewillbeinvokedbyjoinoncealltheinputsareassembled.join_1(Me,XID,Inputs): join(Me,XID,join_2,c(2)), println(["Joined",join_1,"forXID=",XID,"withinputs:",Inputs]).

    %Thefollowingrulewillbeinvokedbyjoinoncealltheinputsareassembled.join_2(Me,XID,Inputs): println(["Joined",join_2,"forXID=",XID,"withinputs:",Inputs]).

    %Atestingharnesscatchallreactionforprintingallmessages.rcvMsg(XID,Protocol,From,Performative,[X|Xs],Extra): println([Performative,[X|Xs],Extra]).Thiscodeprints:

    ==========process_join==========replyforconversationidprova:1:[a,1],corr_areplyforconversationidprova:1:[b,1],corr_bJoined

    join_1

    for

    XID=prova:1

    with

    inputs:

    [[b,1],

    [c,1]]

    replyforconversationidprova:1:[c,1],corr_cJoinedjoin_2forXID=prova:1withinputs:[[c,2],[d,2]]replyforconversationidprova:1:[d,1],corr_d

    In the example, all tasks aremodeled as messages sent to self, i.e., the engine itself, and

    acceptingthesamemessageinthebodyofthesamerule.Thiscouldbereplacedbyeitherinbody

    taskexecution,spawningacomputationusingspawnorsendingarequestmessagetoanagentand

    acceptinga replywith the results.Remember that rcvMsgdoesnotblock the current threadbut

    waitsforamessageasynchronously,whilekeepingallthecurrentdatainthetransparentlycreated

    closure.Parallelbranchingisimplementedbysimplycreatingapredicatewithmultipleclausesand

    processingtherelevanttasksasynchronously.

    Nowback

    to

    the

    init_join

    and

    join

    predicates.

    The

    former

    initializes

    ajoin

    (an

    inclusive

    gateway)

    by passing it (1) the conversationid onwhich thejoinwill be processed, (2) the exit predicate

    invokedwhen thejoinconditionsareverifiedand (3)a listofjoin terms representing tokens that

    needtobecomeavailablefortheexitpredicateofthejointofire.Itisentirelypossibletospecifyjoin

    termscontainingarbitraryfreevariables,includinganonymousvariable'_'.

    When processing reaches a point in the workflow where the join condition can be

    communicatedtotheengine,thecodeusesthejoinpredicatethatacceptsthenameoftheagent,

    theconversationid,thenameofthejoin,andtheconcretejointermthatcorrespondstoanewly

    availablejointoken.Whentheenginedetectsthatalljointermsareavailable,itprocessestheexit

    goal for the predicate corresponding to thejoin name specified at initialization (see clauses for

    join_1andjoin_2).

    1.10.2. Eventdrivengateways(edBPM)Prova supports ebPBMstyle of agent programming and, in fact, offersmuchmorewith the

    conceptofreactiongroups.Onecouldarguethataneventdrivengatewayisasimplifiedversionofa

    reactiongroup.Considerthefollowingvariationontheexampleintheprevioussection.

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    26/94

    Pro

    Wh

    dependi

    detecteThe

    implem

    fork

    r

    s

    r

    fo

    fork

    r s

    r

    jo

    fork

    r

    An

    behavio

    event a

    happen

    fromth

    areact

    Howeve

    annotat

    run_ba

    only ex

    situatio

    The

    this spe

    workflo

    impose

    timeout

    fork

    arulelangu

    t changed

    ingonwhet

    d,the

    other

    following

    ntedusing

    a_b(XID):

    group(g)

    vMsg(XID,Pr

    ndMsg(XID,s

    vMsg(XID,sel

    rk_c_d(XID).

    a_b(XID):

    group(g)

    vMsg(XID,PrndMsg(XID,s

    vMsg(XID,sel

    Tellthejoin

    in(Me,XID,joi

    a_b(XID):

    or(g)

    vMsg(XID,Pr

    Rreaction

    rsuchthat

    rrives, due

    tobethe

    egrouptha

    allynotint

    r, there are

    iondeclares

    rrives,theg

    ension of t

    n.

    beautyoft

    cification, t

    ,eventpat

    a10secon

    channel.

    a_b(XID):

    age3.0

    here is the

    ertheeve

    alternativeodifiedfirst

    areactiong

    otocol,From,

    elf,0,reply,a(

    ,Me,reply,a(

    otocol,From,elf,0,reply,b(

    ,Me,reply,b(

    join_1thata

    n_1,b(1)).

    otocol,From,

    groupgives

    hegroupc

    o the sema

    lternativer

    isusedfor

    restedinc

    subbranc

    themtobe

    roupasaw

    he workflo

    isapproac

    ranslating t

    tern,ormo

    dstimeout

    exclusive

    trun_aorr

    ranchis

    im

    halfofthe

    oup.

    ommand,run

    ),corr_a),

    ),corr_a),

    ommand,run),corr_b),),corr_b),

    newpattern

    r,_).

    thetwom

    llectivelyw

    ntics of OR,

    eaction,dis

    definingthe

    mmonacti

    es followin

    partofthe

    holedisapp

    . Note tha

    isthelinea

    o the ease

    egeneralre

    onthegrou

    UsersG

    hoice that

    un_barrive

    ediatelydi

    aboveexa

    _a),

    _b),

    isready

    ssagehand

    aitsforeith

    , the group

    ppears.Th

    semantics

    nlogicsot

    g either of

    reactiongr

    arsbutthe

    we use a

    rityofexte

    of authori

    activebeha

    p,addsa

    uide

    the enviro

    first.More

    sabledso

    th

    pleshows

    lers foreve

    erofthet

    asa whole

    @orannot

    ofthegrou

    isreaction

    the reactio

    upwitha l

    closureoft

    Prova OR r

    sibleseman

    g and mai

    ior.Forexa

    notannota

    ment imp

    ver,assoo

    atonly

    one

    owtheeve

    tsrun_aa

    oeventsto

    is terminat

    atedreactio

    asawhole

    isnotfollo

    s annotate

    gicalname

    hefiredbra

    action gro

    ticvariants

    tainability

    mple,thef

    iononthe

    ses on the

    aseithero

    branchcan

    ntdriveng

    drun_ba

    arrive.Wh

    ed so that

    nistheexit

    .Inthisinst

    edbyanyt

    with @gr

    g.Soonce

    nchcontinu

    p to model

    hatcanbe

    of the desi

    llowingmo

    run_bchan

    ay2010

    22

    process

    fthemis

    roceed.teway is

    ollective

    neither

    hatever

    channel

    ance,we

    ingelse.

    up (this

    run_aor

    sasthe

    an XOR

    addedto

    n, be it

    ification

    elanda

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    27/94

    Provarulelanguage3.0 UsersGuide May2010

    23

    @group(g) rcvMsg(XID,Protocol,From,command,run_a), sendMsg(XID,self,0,reply,a(1),corr_a), rcvMsg(XID,self,Me,reply,a(1),corr_a), fork_c_d(XID).fork_a_b(XID):

    @group(g)

    @not

    rcvMsg(XID,Protocol,From,command,run_b).fork_a_b(XID): @or(g)@timeout(10000) rcvMsg(XID,Protocol,From,or,_).fork_a_b(XID): @or(g) rcvMsg(XID,Protocol,From,timeout,_), sendMsg(XID,self,0,reply,b(1),corr_b), rcvMsg(XID,self,Me,reply,b(1),corr_b), %Tellthejoinjoin_1thatanewpatternisready join(Me,XID,join_1,b(1)).

    Ifrun_aarrivesbeforethetimeout,itremainstheonlybranchasinthepreviouscase.Ifneither

    run_anor_run_barrivebeforethetimeout,thetimeoutchannelproceedswiththebranchwithtaskb. Prova 3.0 includes a large collection of annotations for reaction groups that really helpwith

    designingverysophisticatedworkflows.

    1.10.3. PredicategatewaysIt iseasytoseewhysimplejoinsmaybequitelimiting.Imagineyouneedtoanalyzewhatjoin

    tokensareavailabletothejoinandmakeadecisionusinglogicalreasoning.Furthermore,ifthefinal

    joinconditionsarenotyetachieved,itwouldbegreatifwecouldreinitializethejoin,ifsomeother

    conditionsareverified.Thereareknownworkflowpatterns(forexample,StructuredDiscriminator)

    catalogedbyvanderAalstthatbenefitfromsuchfeatures.

    Thefollowingexamplepredicate_join_concurrent.provausestheenhancedversionofthesame

    workflowframeworkcomplementedbybuiltinpredicatesinit_predicate_joinandpredicate_join.

    :eval(predicate_join_concurrent()).

    predicate_join_concurrent(): println(["==========predicate_join_concurrent=========="]),

    for([0,2],I), sendMsg(XID,async,0,request,a()), rcvMsg(XID,async,Me,reply,a()),

    %Initialisethepredicatejoin:

    %

    XID

    is

    conversation

    id;

    %join_1istheexitpredicatethatmustbeuniqueforeachjoin; %join_predicate_1isthejoinconditions; %i1..i3aretherequiredtokens. init_predicate_join(XID,join_1,[i1(),i2(),i3()],join_predicate), println([XID]), %Thiswillcreatethreeparallelprocessingstreams. loop_a_body("Worker",XID).

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %Threebranchesexecutingthreeparallelactivities%%representingadivergenceintheprocess%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %%%%

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    28/94

    Provarulelanguage3.0 UsersGuide May2010

    24

    loop_a_body(Partner,XID): switch_thread(a), println(["Branch1complete"]), predicate_join(XID,join_1,i1(),[Partner]).loop_a_body(Partner,XID):

    switch_thread(b),

    println(["Branch2complete"]), predicate_join(XID,join_1,i2(),[Partner]).loop_a_body(Partner,XID): switch_thread(c), println(["Branch3complete"]), predicate_join(XID,join_1,i3(),[Partner]).

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %RulesrepresentingtheexitbranchesoftheJOIN%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %%

    %ThefollowingrulewillbeinvokedbyjoinonceONEinputforjoin_1hasarrived.%Thisisgovernedbythefirstjoin_predicaterule.join_1(s(0),XID,Count,Inputs,[Partner]): println(["JoinedforXID=",XID,"atstate's(0)'withinputs:",Inputs]), %Reporttothetestcaserunnerthatthisstepiscomplete sendMsg(XID,self,0,job_completed,[]).%Thefollowingrulewillbeinvokedbyjoinonceallinputsforjoin_1havearrived%Thisisgovernedbythesecondjoin_predicaterule.join_1(reset,XID,Count,Inputs,[Partner]): println(["JoinedforXID=",XID,"atstate'reset'withinputs:",Inputs]), sendMsg(XID,self,0,body_a_complete,[]),

    %

    Report

    to

    the

    test

    case

    runner

    that

    this

    step

    is

    complete

    sendMsg(XID,self,0,job_completed,[]).

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %Rulesestablishingwhenthepredicatejoinreachesappropriatestates%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %%%%%%%%%%%%%%%%%%%%%%%

    %Therulefordeterminingajoincondition.Notethatthestatemusthaveformat"s(Number)".join_predicate(XID,join_1,s(0),Msg,Waiting,Count,Complete,Params): 1=Complete.size().%Therulefordeterminingaresetcondition.Whenthisconditionisreached,theJOINisreset.

    %However,

    we

    also

    offer

    achance

    to

    define

    an

    optional

    JOIN

    exit

    branch

    when

    the

    reset

    is

    reached

    %(seerule2forthejoin_1predicate).join_predicate(XID,join_1,reset,Msg,Waiting,Count,Complete,Params): 0=Waiting.size().

    switch_thread(A): sendMsgSync(XID,task,0,switch,[A]), rcvMsg(XID,task,From,switch,[A]).

    %%%%%%%%%%%%%%%%%%ANOOPworker%%%%%%%%%%%%%%%%%%

    rcvMsg(XID,Protocol,From,request,[X|Xs]):

    println([rcvMsg(XID,Protocol,From,request,[X|Xs])]),

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    29/94

    Provarulelanguage3.0 UsersGuide May2010

    25

    sendMsg(XID,Protocol,0,reply,[X|Xs]).

    %Atestingharnesscatchallreactionforprintingallmessages.rcvMsg(XID,Protocol,From,Performative,[X|Xs]): println([Performative,[X|Xs]]).

    %A

    testing

    harness

    catch

    all

    reaction

    for

    printing

    all

    messages.

    rcvMsg(XID,Protocol,From,Performative,[X|Xs],Extra): println([Performative,[X|Xs],Extra]).

    1.11.FunctionalprogrammingextensionsFunctionalprogrammingisallaboutbeingabletocomposefunctionality.Thisabilityisrelatedto

    the glorious category theory that emphasizes maps (arrows) over objects. Being slightly

    controversial,Iwouldclaimthatfunctionalprogramming languagesshouldprimarilystriveforthat

    simplicitytocompose, i.e., linearlyaugmentthings,ratherthangettingboggeddown indifficultto

    readsyntaxanddetailedrefinement.

    TheProvaextensionforfunctionalprogrammingattemptstodoawaywiththeproliferationof

    syntacticalconstructs

    and

    distill

    that

    easy

    composability.

    What

    has

    been

    done

    so

    far

    is

    by

    no

    means

    completebutitoffersanumberofimmediatelyusefulfeaturessuchas

    single andmultivalued functions, the latterofferingdirect support fornondeterminismandbacktracking;

    functionalcompositionwiththeextendedderivebuiltin; partialevaluation; lambdafunctions; monadicfunctions; monadicbindusingacompositionofmapandjoin; maybe,list,state,andtreemonadsaspartoftheprovidedlibrarywitheasyextensibility.In order to utilize the functional extensions in Prova, you need to consult the utility library

    functional.provafrom

    your

    rulebase.

    %Thisassumestheindicatedpathlocationforthelibrary

    : eval(consult('rules/reloaded/functional.prova')).

    From the source code Prova distribution, you can also run the tests in

    ProvaFunctionalProgrammingTest.javatofindoutwhatisavailable.

    1.11.1. RepresentingfunctionsProva allows the user to define functions using facts and rules obeying a number of simple

    conventions.

    1. Functionsaredefinedviarulesforarity2predicateswhosepredicatesymbolthenbecomesthe

    function

    symbol.

    2. Thefirstargumentistheinputandthesecondargumentistheoutputofthefunction.3. If the input (output) isa simple term, thiscorresponds toaone input (output)parameter

    function.

    4. Otherwise, the input (output) is a Prova list, corresponding to multiple input (output)parameters.

    5. Theonlyexceptionstorules4and5areProvalistsbeginningwithstringsmaybe,list,stateortree,inwhichcasethosearetreatedasasingleinputoroutputparameter.

    Considersomeexamples.

    double(X,XM): XM=2*X.

    add([A,B],Z):

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    30/94

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    31/94

    Provarulelanguage3.0 UsersGuide May2010

    27

    visibleandcanbeusedinallsubsequentfunctionsintheenclosingpipelinewhichisagreatwayto

    passthedatadownstream.

    %Twoequivalentforms,withoutandwithlambda%BothinstantiateL2=4derive([[add(1)],3,L2])derive([[lambda(A,add(1,A))],3,L2])

    %Anexampleofpassingdatadownstream%Thisinstantiates:V3=9,V2=4,V1=2,C1=13derive( [[lambda(V1,double(V1)),lambda(V2,double(3)),lambda(V3,add(V2,V3))],2,C1])

    1.11.4. SimplefunctionalcompositionInthecaseofsimplecomposition,thefunctionalpipelineiscomposedoffunctionsoperatingon

    the totality of the values being passed between them. To appreciate the power of functional

    composition,

    we

    would

    like

    to

    pass

    between

    functions

    compound

    data

    as

    opposed

    to

    single

    values.

    Considerthefollowingfunction.

    duplicate(X,[X,X]).

    WhatevertheXvalue,the functioncreatesatwoelement listwithtwo identicalcopiesofthe

    samevalue(orstructure,ifXisalsoalist).Followingisanexampleofitsuse.

    %ReturnsXX=6derive( [[duplicate,add],3,XX])

    Whathappenshere?First,thesimplevalue3istransformed intothe list[3,3].Thenthesetwo

    numbers(3

    and

    3)

    get

    shipped

    as

    the

    first

    two

    parameters

    to

    the

    function

    add,

    returning

    the

    result.

    The apparent inflexibility of always attaching the computation results to the end of the next

    function'sargumentsisnicelyresolvedbyusinglambdafunctions.

    %Giventhisdefinitionsecond_degree([A,B,C,X],R): R=A*X*X+B*X+C.

    %Splice3asbothAandB%Thisinstantiates:Z=3,XX=7derive( [[lambda(Z,second_degree(Z,Z,1,1))],3,XX]

    )Nowfinallyiftheinputisalist,thelambdafunctionneedstoacceptmorethanonevariableby

    declaringitsinputasalist.

    %Thisinstantiates:A=3,B=3,L11=7derive( [[duplicate,lambda([A,B],second_degree(A,B,1,1))],3,L11])%Thisalsoworksthesamewayderive( [[lambda([A,B],second_degree(A,B,1,1))],[3,3],L11])

    Now

    we

    are

    completely

    ready

    for

    FizzBuzz,

    functional

    Prova

    style.

    We

    are

    going

    to

    show

    three

    waystodothesamethingandlaterdothesameagainusingtheListmonad.Notethatforisamulti

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    32/94

    Provarulelanguage3.0 UsersGuide May2010

    28

    valued function thatnondeterministically returnsall integersbetween1and100 (itsdefinition is

    verysimpleandispartoftheutilitylibraryfunctional.prova).prtlnisafunctionthatechoesbackits

    inputwhileprintingitfollowedbynewline.

    :solve(

    derive(

    [[for(1,100),fizzbuzz(3,5),prtln],[],X] )).:solve( derive( [[for(1,100),lambda(I,fizzbuzz(3,5,I)),prtln],[],X] )).:solve( derive( [[for,lambda(I,fizzbuzz(3,5,I)),prtln],[1,100],X] )

    ).

    %fizzbuzz:(M1,M2,I)>Rfizzbuzz([M1,M2,I],R): C1=ImodM1, C2=ImodM2, fizzbuzz(C1,C2,I,R).

    fizzbuzz(0,0,_,fizzbuzz):!.fizzbuzz(0,_,_,fizz):!.fizzbuzz(_,0,_,buzz):!.fizzbuzz(_,_,I,I).

    1.11.5. MonadicfunctionalcompositionInthecaseofmonadiccomposition,thefunctionalpipelinepassesaroundmonadicdataandis

    composedoffunctionsoperatingondata insomeform"contained" inthemonadicdata.Monadic

    composition in Prova is done by patternmatching the data passed between functions in the

    functionalpipeline.

    Toclarify,thisapproach isnotdirectlycomparabletotheoneused infunctionalprogramming

    languages.Thelatterisbasedonstrongtypingenforcedatcompiletime.Provaisobviouslyquitea

    bitmoredynamicsotheapproachusedhereisdatadriven.Inthefollowingdiscussion,weassume

    minimal understanding of what monads are about (see, for example, this compact post:

    http://www.haskell.org/haskellwiki/Monads_as_containers).

    The core idea is thatmonadic functionsproduce Prova termsmatchingpredefinedpatterns

    knownto

    the

    functional

    framework.

    1.12.BuiltinsreferenceThisSectionprovidesacompletereferenceforthebuiltinprimitivesintheProvalanguage.

    assert/1(i)

    ThisbuiltinpredicatetakesaProvalistastheonlyargumentandaddsittotherulebaserunby

    the engine as a fact (a rulewithout abody) for thepredicate symbol corresponding to the first

    element in the supplied list. Remember that in Prova, a standard Prologlike compound term

    f(t1,...,tN)is

    asyntactic

    equivalent

    of

    alist

    [f,t1,...,tN],

    so

    we

    see

    that

    the

    predicate

    symbol

    correspondstothefunctorfofthecompoundterm.NotethatProvafactscancontainfreevariables.

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    33/94

    Provarulelanguage3.0 UsersGuide May2010

    29

    TL2=javax.swing.JLabel("Results"), TL2.setAlignmentX(java.awt.Component.CENTER_ALIGNMENT), assert(label2(TL2)),

    Theasserted factscanbequeried in the samewayas the regular facts thatwerepartof the

    rulebaseatthetimetheProvaenginestarted.

    label2(TL2), unescape("\ntest_spawn2finished.",Text),

    Theassertedfactscanremovedusingretract/1orretractall/1builtinpredicates.

    Comp=Event.getComponent(), %Rememberwherethepopupoccurred retractall(selected_component(_)), assert(selected_component(Comp)),

    asserta/1(i)

    Thisbuiltin

    predicate

    takes

    aProva

    list

    as

    the

    only

    argument

    and

    adds

    it

    in

    front

    of

    any

    other

    factsforthesamepredicatetotherulebaserunbytheengineasafact(arulewithoutabody)for

    the predicate symbol corresponding to the first element in the supplied list. Remember that in

    Prova,astandardProloglikecompoundtermf(t1,...,tN)isasyntacticequivalentofalist[f,t1,...,tN],

    soweseethatthepredicatesymbolcorrespondstothefunctorfofthecompoundterm.Notethat

    Provafactscancontainfreevariables.

    Thefollowingexampledemonstrates.

    :solve(test008(X,Y)).

    test008(X,Y): assert(symmetric(f)),

    %

    The

    fact

    below

    will

    be

    added

    higher

    than

    the

    one

    above

    asserta(symmetric(g)), symmetric(X), println(["RuleA1:symmetric",X],""), symmetric(Y), println(["RuleA2:symmetric",Y],"").test008(X,Y): assert(dual(h,a)), assert(dual(h,_)), asserta(dual(h,f)), retractall(dual(_,a)), dual(X,Y),

    println(["Rule

    B:

    dual",X,Y],"

    ").

    Theexampleprints:

    RuleA1:symmetricgRuleA2:symmetricgX=g,Y=gRuleA2:symmetricfX=g,Y=fRuleA1:symmetricfRuleA2:symmetricgX=f,Y=gRuleA2:symmetricfX=f,Y=f

    RuleB:

    dual

    hfX=h,Y=f

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    34/94

    Provarulelanguage3.0 UsersGuide May2010

    30

    RuleB:dualhX=h,Y=

    attach/3(i,i,io)

    This predicate appends the Prova list in the second argument to the Prova list in the first

    argument,returning

    the

    result

    in

    the

    third.

    Since

    Prova

    lists

    are

    held

    in

    arrays,

    the

    code

    can

    concatenateverylargelists.

    Inthefirstargument,

    thelistcanonlyhaveatailthatisalistnotafreeProvavariable, thetaillistisallowedtohaveatailbutthistailisignoredandnotcopiedtotheresultList.Inthesecondargument,

    thelistcanonlyhaveatailandthetailisattachedtotheendoftheresultlist.Herearesomeexamples.

    :solve(attach([1|L],[2,3],X)).

    :solve(attach([1|[1,L]],[2,3],X)).

    :solve(attach([1|[1|L]],[2,3],X)).

    :solve(attach([1|[1|L]],[2,3|Z],X)).

    Thisprints:

    noL=L,X=[1,1,L,2,3]L=L,X=[1,1,2,3]L=L,Z=Z,X=[1,1,2,3|Z]

    Here isaclassicexampleof towerofHanoipuzzle inProva,alsomakinguseofProva tabling

    usingthecachebuiltinpredicate.

    :solve(move(4,left,mid,right,Plan)).

    move(0,_,_,_,[]):!.move(N,A,B,C,Plan): NM1=N1, cache(move(NM1,A,C,B,PlanL)), cache(move(NM1,B,A,C,PlanR)), attach(PlanL,[[A,C]|PlanR],Plan).

    bound/1(i)

    Thispredicate fails if the suppliedargument isa freeProvavariableoraProva listcontaining

    Provavariables.Otherwise,itsucceeds.

    Thefollowingfragmentshowshowtotestiftheargumentsuppliedtotheclauseisbound.

    access_data(Type,ID,Data,CacheData): %Attempttoretrievebounddata bound(ID), Data=CacheData.get(ID), %Success,Data(whateverobjectitis)isreturned !.

    byte_stream/2([i,i],o)

    Thispredicate

    encodes

    either

    an

    input

    string

    or

    aJava

    ByteArrayOutputStream

    using

    asupplied

    charsetname(see IANACharsets)andreturnsaJavaByteArrayInputStreamwrappingtheresulting

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    35/94

    Provarulelanguage3.0 UsersGuide May2010

    31

    bytearray.ThepredicateisstructuredasaProvafunction(seeFunctionalprogrammingextensions).

    In the first argument, it accepts a Prova listwith two input parameters: (1) an input stringor a

    ByteArrayOutputStream and (2) a charset name. The second argument is the produced

    ByteArrayInputStream.

    ThefollowingexamplecompressesaJavaString,storestodisk,andretrievesitback.

    :solve(test_byte_stream(toto)).

    test_byte_stream(Result): println(["==========byte_stream=========="]), byte_stream(["toto","UTF8"],BAIS), File=java.io.File.createTempFile("prefix","suffix"), FO=java.io.FileOutputStream(File), ZFO=java.util.zip.GZIPOutputStream(FO), copy_stream(BAIS,ZFO), println(["Compressedfilecreated."]),

    FI=java.io.FileInputStream(File), ZFI=java.util.zip.GZIPInputStream(FI),

    BAOS=java.io.ByteArrayOutputStream(),

    copy_stream(ZFI,BAOS), byte_stream([BAOS,"UTF8"],Result), println(["Theoriginalstringreadfromthecompressedfile:",Result]).

    ThefollowingtestfromProvaBuiltins1Test.javashowshowthisisrunfromJava.@Testpublicvoidbyte_stream_and_copy_stream(){ finalStringrulebase="rules/reloaded/byte_stream.prova"; finalint[]numSolutions=newint[]{1};

    ProvaCommunicatorprova=newProvaCommunicatorImpl(kAgent,kPort,rulebase,ProvaCommunicatorImpl.SYNC);

    List

    solutions

    =

    prova.getInitializationSolutions();

    org.junit.Assert.assertEquals(1,solutions.size()); org.junit.Assert.assertEquals(numSolutions[0],solutions.get(0).length);}

    cache/2(i)

    This builtin predicate provides support for tabling in Prova. It enables the literal in its only

    argumentforcaching.ThecurrentimplementationinProva3.0keepsthecachedanswersetforthe

    literalindefinitely.

    The following example runs the Hanoi Tower puzzle for 20 disks, which would have been

    prohibitivelylongifthecachepredicatewasnotused.NaiveimplementationsinHaskellorScalaalso

    sufferunlesstablingisexplicitlyadded.:solve(move(20,left,mid,right,Plan)).

    move(0,_,_,_,[]):!.move(N,A,B,C,Plan): NM1=N1, cache(move(NM1,A,C,B,PlanL)), cache(move(NM1,B,A,C,PlanR)), attach(PlanL,[[A,C]|PlanR],Plan).

    Tablingalsohelpstoavoidinfiniteloopingincodeastheexamplebelowshows.:solve(reach(X)).

    edge(a,b).

    edge(c,d).edge(d,c).

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    36/94

    Provarulelanguage3.0 UsersGuide May2010

    32

    reach(a).reach(A): edge(A,B), cache(reach(B)).

    ThisreturnsonlyonesolutionX=a.

    capture_enum/2([i,i],io)ND

    This nondeterministic predicate enumerates regular expression groups. It is structured as a

    multivalued Prova function (see Functional programming extensions). In the first argument, it

    acceptsaProvalistwithtwoinputparameters:aninputstringandaregularexpression.Itproduces

    independentsolutions,oneeach foreachpossibleanswer in thesecondargument.Thiscreatesa

    choicepointwithasmanynondeterministicbranchesastherearetokensintheinputstream.

    Thefollowingexampleshowshowthisworks.

    :solve(test017(Groups)).

    test017(Groups):

    Text="Adoodleisadoddle", %nondeterministicallyenumerateregularexpressiongroups capture_enum([Text,"(d?)(dl)"],Groups).

    Thisreturns:

    Groups=[,dl]Groups=[d,dl]

    clone/2(i,io)

    Thisbuiltinpredicateimplementsa"unidirectionalunification".Itcreatesfreshvariablesforthe

    first

    term

    and

    then

    unifies

    it

    with

    the

    second

    supplied

    term

    so

    that

    the

    result

    is

    available

    in

    the

    secondargumentwhilethefirstargumentisleftunmodified.Forexample,:solve(test_clone(must_match,add)).

    test_clone(B,FunX): clone(lambda(A,[add,A,4]),lambda(1,[FunX|ArgXs])), %Atthispoint,Aisstillafreevariable,butFunXisboundtoastring'add' println([FunX,ArgXs,B],""), println(lambda(A,[add,A,4]),""), %must_matchunifieswithaconstantAsuccessfully %NotwecannotuseAastheheadvariable,otherwiseclonecannotmatchmust_matchwith1 B=A.

    Thecodeaboveprintsthefollowing.

    add[1,4]

    must_match

    lambda[add,,4]yes

    Oneuseofthisbuiltinistomaplambdaexpressionsoverlists(andothermonads).Thecopyof

    thelambdafunctionneedstobefreshonapplicationtoeach listelement,soclone/2achievesthis

    byunifying theprovided lambdaexpression in the firstargumentwithastandard template in the

    secondargument,appliestheresultinthesecondargumenttothecurrentelementusingthebuiltin

    derive/3 and continuesprocessing the remainderof the listwith theoriginalunmodified lambda

    expression.map([lambda(A,[Fun|Args]),list(X|As)],[B|Bs]): !, clone(lambda(A,[Fun|Args]),lambda(X,[FunX|ArgXs])),

    derive([FunX,ArgXs,B]), map([lambda(A,[Fun|Args]),As],Bs).

  • 7/31/2019 Prova 3.0 User Guide - May 2010

    37/94

    Provarulelanguage3.0 UsersGuide May2010

    33

    concat/2(i,io)

    ThisbuiltinpredicatetakesaProvalistanditeratesoverthelistelements,byconvertingthemto

    Javastrings,concatenating them,andunifyingthe resultwith thesecondargument. Ifthesecond

    argumentisnotafreevariable,theunificationbetweentheconcatenationresultandthisargument

    mayfailwhichthenfailsthebuiltin.

    %Nosolutionsherer(AB): concat([a,b],AB), concat([a,c],AC), concat([a,c],AB), %Thislineis(correctly)unreachableinProva3.0 println(["1:",AB,"=",AC]).

    copy/2(i,i)

    ThispredicatetakesthecharacterstreamfromaJavaReaderandwritesitusingaJavaWriter.IO

    exceptions

    are

    wrapped

    in

    a

    RuntimeException.

    The following code uses a StringWriter to capture the stream in a buffer. A mobile agent

    functionalityisimplementedbysendingarulebasefragmenttoanotheragentthatthenconsultsthe

    rulebasedynamicallyandrunsagoal.

    upload_mobile_code(XID,Remote,File): fopen(File,Reader), Writer=java.io.StringWriter(), copy(Reader,Writer), SB=Writer.getBuffer(), sendMsg(XID,esb,Remote,upload,consult(SB))....

    rcvMsg(XID,Esb,From,upload,consult(SB))

    :

    iam(Me), consult(SB), %Theclauseforworker/2isdefinedinthecodethattheManageruploadstothisworker worker(XID,From).

    copy_stream/2(i,o)

    This predicate copies a Java ByteArrayInputStream to a Java ByteArrayOutputStream. The

    predicate isstructuredasaProvafunction(seeFunctionalprogrammingextensions),withthefirst

    argumentasinputandthesecondargumentasoutput.

    ThefollowingexamplecompressesaJavaString,storestodisk,andretrievesitback.:solve(test_byte_stream(toto)).

    test_byte_stream(Result): println(["==========byte_stream=========="]), byte_stream(["toto","UTF8"],BAIS), File=java.io.File.createTempFile("prefix","suffix"), FO=java.io.FileOutputStream(File), ZFO=java.util.zip.GZIPOutputStream(FO), copy_stream(BAIS,ZFO), println(["Compres