Sketch of an alternative approach to RIF
This is a proposal for an alternative approach to designing RIF, an approach that, I believe, makes it simpler by not assigning it the full-fledge semantics of a rule language, and, thus, allowing for a core that is common to a large extend of different kinds of rule languages and covers a broad base of practically useful cases (and that makes interoperability between different styles of rule languages possible in most of those cases).
I tried to be complete and rigorous enough for the idea to be clear, but this is a rough sketch nonetheless: many detailled need be discussed and hammered. I tried to be clear and unambiguous, but bear with my maybe heterodoxe use of the terminology
RIF expressions are atomic expressions or modified atomic expressions or quantification expressions or quantified test expressions or conjonctions of RIF expressions or disjunctions of RIF expressions.
Atomic expressions are made of a relation identifier and zero or more arguments, where each argument is the identifier of a constant, the name of a variable or the identifier of a function and zero or more arguments.
The parties in the interchange of a RIF document (that is, of rules serialized as a RIF document) are assumed to have agreed on the meaning of atomic expressions, that is, each party knows how to interpret them in their own rule language, and, given an evaluation context, how to decide whether or not it is satisfied (and they agree on that, too, of course).
Modified atomic expressions are made of one or more modifiers and the atomic expression they modify. Examples of modifiers are the various kinds of negation, modal operators etc.
Given that agreement on atomic expressions, RIF specifies how to interpret combinations and modifications (so that each party knows how to translate them to and from their own rule language and, given an evaluation context, how to decide whether or not they are satisfied; and so that all parties agree on that, too):
- conjunctions, resp. disjunctions, are translated by each party from/into expressions in their own rule language that are satisfied iff all their component expressions are satisfied, resp at least one of their component expressions is satisfied;
- quantified test expressions are translated by each party from/into expressions in their own rule language that are satisfied for at least one binding (existential test), resp. all bindings (universal test), of its free variable as specified by its associated quantification expression;
- quantification expressions associate a variable name to an expression that specifies the values that it can take, e.g. a type identifier and possibly a constraint; or maybe even an extensive set of values (so, the expression associated to the variable name in a quantification expression may end up being slightly different from other expressions - or could types be interchanged just another atomic expression?). Quantification expressions are translated by each party from/into expressions in their own rule language that will bind the variable name to one value that satisfies the expression (as translated from/into the same rule language), in the case of an exsitential quantification expression; resp. to all such values, in the case of an universal quantification expression;
- modified atomic expressions are translated by each party from/into expressions in their own rule language that are satisfied according to the semantics assigned to the modifiers and their combiantion (e.g. strong negation, negation as failure etc).
In BNF-like form:
- Conjunction ::= Expression Expression*
- Disjunction ::= Expression Expression*
AtomicExpression ::= RelationID Argument*
Argument ::= ConstantID | VariableName | FunctionID Argument*
Rules are made of three components:
- zero or more quantification expressions;
- zero or one antecedent expression;
- one consequent expression.
Quantification expressions come in two varieties: existantial and universal and are made of a variable name and an expression in the sense of the previous paragraph (possibly with some restrictions).
Antecedent expressions are expressions in the sense of the previous paragraph (possibly with some restrictions).
Consequent expressions are expressions in the sense of the previous paragraph (possibly with some restrictions).
The expression in a quantification expression is to be interpreted as a query (the associated variable is to be bound to the values returned by the query). An antecedent expression is to be interpreted as a condition. A consequent expression is to be interpreted as a prescription: the consequent expression is expected to be satisfied for all of the bindings produced by the initial quantification expression that satisfy the antecedent expression (subject to the agreed-on meaning).
What is to be done with that prescription is up to the up to the applications that use the rules. Take, for instance, a business rule like: "IF the structure is framed on the exterior, THEN the appraiser must provide calculations of measurements on the appraisal" (taken from a MISMO BREW use case; the rule regards property appraisal - the MI in MISMO stands for Mortgage Industry). Leaving aside the modal operator (must), the RIF (Rule Interchange Form) of the rule could be paraphrased as :
- Quantification expression: "For each ?property to be appraised" (where "to be appraised" is a query refereing to the appraisal order document (an XML document in the Use Case)
- Antecedent expression: "The structure of ?property is framed on the exterior"
- Consequent expression: "The appraisal of ?property provides calculations of measurements" (where both the antecedent expression and the consequent expression are about the appraisal report, an XML document in the use case).
Now, depending on the application using the rule, and the rule language it translates the RIF of the rule from/into, the rule could end up looking like:
in an application using a production rule kind of language for compliance checking : "FOR ?property Property(toBeAppraised() & Structure.isFramedOnTheExterior()) IF NOT(?property.Appraisal.providesCalculationsOfMeasurements()) THEN Execute(raiseAlarm(?property, "No calculation of measurements"))
in another application using a production rule kind of language for the preparation of the appraisal report: "FOR ?property Property(toBeAppraised() IF Structure.isFramedOnTheExterior()) THEN ?property.AppraisalReport.addSection(CalculationOfMeasurement)
Notice that, while in applications 1 and 3, the evaluation of the rule results in the fact that the required calculation is provided being true, this is not the case in application 2, although the rule is equally "satisfied" in all three cases, as far as the application is concerned (that is, in application 2, if the alarm is correctly raised, of course).
Notice that it seems that the translation from/to RIF may thus depend not only on the target/source rule language, but on the application as well.
Rulesets are made of two components:
- zero or more quantification expressions (maybe, see comment below);
- one or more rules.
The meaning of a ruleset is that all the rules have to be evaluated one at a time in some order until none needs or can be evaluated anymore (typically, because their consequent is satisfied or their antecedent is not; but it could also be otherwise, depending on the application: in application 2 above, each rule needs be evaluated only once)
(The possibility to have quantification expressions at the ruleset level is added to cater for the case where the valuation domains for some or all variables must be evaluated once and for all - and not be modified by the evaluation of the rules. Not sure if it is necessary or useful).
The semantics of a rule, resp. a ruleset is deliberately informal; it may need to be refined, but not necessarily (and, maybe, preferably not) to the point that it is, or can be translated into a formal semantics. Indeed, the point is _not_ that RIF translators actually translate the semantics of what would then be a RIF rule/ruleset from/into the semantics of the source/target rule language, but that the semantics of RIF should, instead, abstract from the semantics of rule languages in such a way that, for a useful - and preferably broad - class of rule languages/rules/rulesets/use cases, a rule/ruleset in a specific rule language will have, according to the semantics of that rule language, the same meaning that its "natural"/expected representation in RIF (that is, without unduly complex transformation of the rule being required for the sole purpose of preserving its meaning).
The rather vague "semantics" proposed above for rules and rulesets seems to be able, for instance, to preserve the meaning of a rule/ruleset across a large class of general logic programmes with a stable model semantics and a large class of rulesets with the usual operational semantics of production rule languages.
The underlying assumption is that the meaning of a rule is, for most practical purposes, the same, whatever the rule language in which it is written/translated, and that the complexity of theoretical devices used to specify the formal semantics for rule languages depends mostly on the wish/need to cover all the possible cases in an uniform way (another possibility being to restrict the syntax of the rule language in order to make cases that cannot be covered uniformly by the semantics be impossible to express with the language).
This proposed approach to RIF is based on the idea that RIF, RIF Core at least, should be designed to enable interchange between rule languages for a class of practically useful cases that is as broad as possible, but with no attempt towards any kind of completeness. As a consequence, RIF Core does need neither a strict semantics beyond what is described above, nor syntactic restrictions within the limit of constructs for which that basic semantics make sense.
Another assumption that is critical to the proposed approach is, indeed, that RIF document will not be produced and published, interchanged or retrieved arbitrarily, but that producers/publishers on the one hand, and retievers/consumers, on the other hand, will do that (produce, publish, retrieve, consum RIF documents) for a purpose, and that they will thus be able to decide whether RIF Core fits that purpose, or if a more specialised dialect is required. A side assumption is, of course, that there are no use cases for interchanging rules/rulesets requiring a more specific semantics between rule languages that do not share that semantics (and, thus, that the interchange can then happen in the appropriate dialect that they would, by definition share).
According to this proposal, extensions (possibly or even probably divergent: that is, mutually incompatible dialects) will, indeed, specify their semantics in greater details and formalism, and possibly add syntactic restriction as well as additional constructs, in order to cover the cases of special relevance to certain classes of RL, and where the basic semantics of RIF Core is insufficient to preserve the intended meaning of rule/rulesets.
RIF Core, extensions, phases
Such an approach provides for an extensible common core for RIF, where "core" means the part of RIF that does not depend on the style of the source/target rule language: that is, the part of RIF that is shared accross styles of rules. Notice that implementing the common core does not require necessarily a rule language to be able to process all the rules that can be represented in that core. It only requires that it is able to recognise all the constructs in that core, and to identify the rules/rulesets that it can process in a meaning preserving way: here, again, the assumption is that a ruleset that this implementation could not process would simply not be meant for its consumption; and, in the case where that assumption would be wrong, that is, where the ruleset would be specifically addressed to that application, being compliant would enable the implementation, first to comply with the expected default behaviour; and, second, to indicate unambiguously, if required, what part of the rule/ruleset it cannot process. Of course, another approach could be to define different compliance levels/profiles/whatever to RIF core will be needed, based on expressive power. There should be, however, a non-trivial level/profile/whatever that is shared by all RIF implementations: that basic profile/level/whatever could, for instance, restrict consequent expressions to atomic expressions, restrict the use of quantified test expressions in antecedent expressions, etc. RIF core is extended by adding new features that exist across classes of rule languages, such as modifiers (e.g. the basic core is not likely to include all the useful kinds of negation, if it includes any).
Non-core extensions, aka dialects, extend the core by adding features that are specific to a style of rules or a group of rule languages: such dialectal features could include, for instance, the specification of intended models (targeted to LP languages); built-ins to specify finer control of execution loop, e.g. relative to the ordering of the rules, or to notion such as recency (targeted to production rule languages); build-ins that are specific to families of languages, e.g. modal operators (maybe coming in different kinds, depending on whether they are targeted to business rules, modal LO languages etc), side-effect operators beyond assert, retract, modify (targeted to active rule languages), etc.
My understanding of phase one is that it is chartered to specify the framework for RIF (architecture, syntax, compliance etc) and a basic, but still useful, part of the core. That probably covers at least the basic level of compliance, but it may define more than one level/profile/whatever, if we decide that we need them (e.g. a basic level with no types, no functions and no negation, and a extended basic including types, functions and, e.g., NEG in the antecedent). My rule of the thumb for what belongs in phase 1 and what does not, is whether it is controversial or not, subject to time constraints and the part of RIF core defined in phase 1 being at least expressive enough to interchange Horn rules (aka the minimum usefulness criterion).
I may be wrong, but it seems to me that RIF Core, according to the design sketched above, is not a rule language, in the sense that it does not exclude the possibility to represent meaningless rules/rulesets (source/target rule languages and application are expected to bring that capability: hence my reluctance at having "people write rules in RIF directly"); but dialectal extensions could be rule languages by themselves, so that RIF could provide the basis for a SW rule language (I am not sure that dialects are in the scope of RIF, but that is debatable, at least for some of the basic dialectal extensions; they are certainly not phase 1 anyway, and probably not phase 2 either, however).
I am aware that this approach pushes much of the burden outside of RIF, and, in particular, on the translators. But I believe:
- that what is pushed outside of RIF is orthogonal to the purpose of RIF (and, thus, it should not be dealt with as part of RIF, by application of the principle of separation of concerns);
- that that approach is at least sufficient for a substantive core, covering a practically useful part of logic programming and of production rules (limited to the three standard assert/retract/modify and, thus, covering PRR);
- and that it makes design simpler, as it leaves many issues outside the scope.
And thus, that this is the approach RIF should adopt Well, at least, it should be seriosuly considered. I believe that adopting such an approach would satisfy both the spirit and the letter of the WG charter and of the requirements that this WG has identified, and that it would allow the WG to focus on the technical details of rule interchange (as opposed to spending time on the equally worthwhile, but orthgonal, task of designing rule languages).
Notice that the approach we adopt finally (that one, Harold at al.'s, Hassan CLP-based, yet another one, a synthesis, whatever) seems to have little impact on many of the technical issues that we will have to resolve, e.g. regarding:
how does RIF interchange identifiers, that is how does it refer to the agreement between the parties regarding the meaning of relation, function, constant identifiers (some might be builtins, some might be concretized as an XML Schema, an RDF vocabulary, an OWL ontology; or maybe it can even have no concrete representation)? Namespaces? derived questions: at what level need it be specified (RIF document, ruleset, rule, lower?)? What if a party does not know/understand the reference? NB: some are inbuilt => the reference is RIF itself;
how does RIF specify against which context are the rules to be evaluated (that is, against what fact base, working memory, data base, whatever, are queries and conditions to be evaluated, and what fact base, working memory, data base whatever is prescvribed to satisfy the conclusions, if any)? And derived questions... (aka the data source/dataset issue). Notice that that issue is related to the previous one, since, in the pure LP case, the agreement on the interpretation of identifier can be in the form of a mapping onto the identifiers in specific Herbrand universes/bases, that is, applicable fact bases/EDB:data sources; and that, when the identifiers are identical, the shared information about the interpretations that are acceptable seems to be the mere indication of the applicable datasets (but, of course, there is also the, possibly implicit, agreement that the identifiers are indeed the same, i.e. that they have the same interpretation...)
- how does RIF deal with extensions (preserving compatibility), compliance, meta-data (names, comments and beyond)