This is an archive of an inactive wiki and cannot be modified.

RIF example UC9: BPEL Orchestration of Rule-Based Web Services

Kindly send comments on this page to GaryHallmark

Summary

This use case is about rules that score a credit report represented as an XML document.

The source rules are production rules (PR) with actions other than assert, suggesting that we invent a PR dialect that extends RIF Core in order to translate these rules to RIF. It turns out that most of the rules can be restated as PR with only assert actions, and these restated PR can be translated to RIF Core augmented with aggregation. That is the route we will take.

We will express the translated rules in a "human readable" RIF because their elaboration as XML probably does not help understand the key issues of mapping production rules to RIF at this point.

Background

Use case BPEL Orchestration of Rule-Based Web Services is about rules that score a credit report represented as an XML document. The sources are provided as Oracle Rule Language (RL), a production rule language with its roots in CLIPS but with a more modern Java-like syntax. (Note that business users do not program in RL directly.)

The use case is loosely based on a commercial credit application.

Source data and rules

The actual application has about 100 rules. Each rule interprets one or a few credit report attributes, and typically increments an overall credit score variable. We show just a fragment of the credit report document, and a redacted ruleset in RL containing the definition of the credit score variable, a variable indicating whether credit is approved, and two rules with priorities.

RL relies on the Java API for XML Binding (JAXB) to translate XML schema to Java classes, and to translate XML instance documents to Java objects.

First we show the "original" ruleset in RL (before transforming to assert actions).

JAXB processing of credit report schema

The schema of a simple credit report document such as the following

<credit-report>
  <name>Joe Slacker</name>
  <ssn>923764388</ssn>
  <income>45000</income>
  ...
</credit-report>

results in a Java class such as the following

class CreditReport {
    String name;
    String ssn;
    BigDecimal income;
}

Original production rules

The following RL ruleset then references the credit report

ruleset creditScoring {
  int score = 0;
  boolean approved = false;

  rule r1 {
    // If applicant's income is between 40000 and 50000 then add 40
    priority = 1;
    if (fact CreditReport cr && cr.income > 40000 && cr.income <= 50000)
    {
      score += 40;
    }
  }

  rule r2 {
    // approve if total score is over 300
    priority = 0; // must execute after the scoring rules
    if (true) {
      approved = score > 300;
    }
  }
}

Production rules using assert actions and aggregation

The above can be rewritten to use only assert actions and aggregation:

ruleset creditScoring2 {
  class ScoreIncrement {
    int value;
  }
  class Approved {}

  rule r1 {
    // If applicant's income is between 40000 and 50000 then add 40
    if (fact CreditReport cr && cr.income > 40000 && cr.income <= 50000)
    {
      assert(new ScoreIncrement(value: 40));
    }
  }

  rule r2 {
    // approve if total score is over 300
    if (aggregate (fact ScoreIncrement si) : sum(si.value) score && score > 300)
    {
      assert(new Approved());
    }
  }
}

Translation of PR with only assert actions into RIF Core

The following translation assumes the following

ScoreIncrement[value->40] :- 
  Exists ?income (
    And (
      CreditReport[income->?income] 
      &numeric-greater-than(?income 40000) 
      &numeric-greater-than(50000 ?income) ))

Approved[] :- 
  Exists ?increment ?score (
    And (
      ScoreIncrement[value->?increment]
      ?score = &SUM(?increment)
      &numeric-greater-then(?score 300) ))

Issues

A few issues with the above translation are worth disussion.

Naming

How do we attach the ruleset and rule names? There is no place in the ASN or concrete syntax at present.

I don't know what to do about namespace prefixes in the human-readable syntax. I omitted them.

Datatypes

Literals such as 300 and 40000 are not tagged as 300^^int or 40000^^BigDecimal. Is this required?

Builtins and ordering of conjuncts

Order matters. CreditReport[income->?income] must come before &numeric-greater-than(?income 40000) so that ?income is bound.

Aggregation

Adding &SUM is easy syntactically, but the semantics are non-monotonic. How do we extend Core semantics to support aggregation?

Translation of arbitrary PR

Neither r1 nor r2 from the original creditScoring ruleset has a head (neither rule asserts a fact into working memory). R2 doesn't even have a body. How can these actions be expressed?

A notion of priority is needed because r2 must execute after r1 in order to read the total score.

Changes

GaryHallmark rewrote most of this page on June 22, 2007 to rephrase as PR with assert actions and aggregation and to use the "latest" Core syntax (not all approved)