RuleAPI:Natural Language

From FlexRule Wiki
(Redirected from RuleAPI:NL)
Jump to: navigation, search

Natural Language

Natural Language (NL) is a language to model business rules close to your spoken language. The intends to remove all the noise that an XML models has, and emphases on the actual business rules using business glossary, terms and logic that are reusable across other types of logic.

As the results rule are much more simpler to understand with less nose related to structure and/or types of the rule logic.

Example

@name test a person identity

input person    
output valid

when Person has identity
    (
    Person has name or
    Person has family
    ) and
    Email of person match "\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"
    /* Birth city must be available */
    and
    (
     Name of City of BirthPlace of person is not null and
     Name of City of BirthPlace of person is not empty
    ) or
    Age of person lt 18
then
   set valid to true
end

when Person has name
        Name of person is not null and
        Name of person is not empty
end 

when Person has family
        Family of person is not null and
        Family of person is not empty
end

Structure

Body

The body of rule, contains

  1. the name of the rule
  2. context
  3. set of logic
@name "name of rule document"
/* enable attribute is not mandatory, if it’s not set the default value will be added automatically. Default value is true. */
@enable {true | false} 

{context}

{logic 1}
{logic 2}
...
{logic n}

Logic

A logic is a when-then-otherwise-end block. then and otherwise are optional.

/* There might be one or more when condition available in the rule document */
when {name of logic}
    {Body of condition}
then
    {body of actions}  
otherwise
    {body of actions}  
end

Please note a logic can have no name. In this case remove {name of logic} from after when.

When {body of condition} is left empty, the actions on then automatically will be executed. If the {body of condition} is provided, then will be executed when {body of condition} are met otherwise the otherwise will be executed.

Parameterised Logic

In defining logic with parameters, { and } are used that enclose the parameter name

/*A logic with parameter named amount*/
when Add bonus of {amount} to total amount
end

/*A logic with NO parameters*/
when Print total
end
Logic

In calling a logic, just use its name. If the logic is parameterised then ( and ) are used to pass values

when 
    Add bonus of (12.3) to total amount   and
    Print total
end

Context

Adding {context} to rules has the following format:

/* List of input parameters */
 given | input variable1, variable2, …
 /* List of output parameteres */
 output variable1, variable2, …

Body of condition

{Body of condition} has the following format:

{compare expression-1} {or|and|nor|xor|xnor}
{compare expression-2} {or|and|nor|xor|xnor}
…
{compare expression-n} 
/* Or may contains groups or nested groups. Group starts with ( and ends with ) */
(
    {Body of condition-1} {or|and|nor|xor|xnor}
    {Body of condition-2} {or|and|nor|xor|xnor}
…
    {Body of condition-n} 
) {or|and|nor|xor|xnor}
{Body of condition}

Compare expression

{compare expression} has the following format:

case 1: {left hand expression} {operator} {right hand expression}
or 
case 2: name of logic
or
case 3: Any expression
case 1

{Right hand expression} can be any expression or {Value}.

{operator} can be

  1. Comparison operators
  2. Or any of: is, is not, match, not match

{left hand expression} can be a {term} or can be any expression or {Value}.

case 2

When multiple logic is defined in a document, the can have a name and call each other by name. In these cases, the parameter can be called by parentheses.

When multiple actions are expected as part of the consequence, then they should be separated or connect by either of the following:

  • and
  •  ; (semicolon)
  • set

Value

Value can be primitive, constant values or complex expressions. e.g. value [3; 45] is a range expression value.

Expression
{value} can be any Expression
Of Operator
{left or right hand expression} may have:
/* Flat property access */
{Property name} of {variable}
/* Or nested property access */
{Property name} of {Property name} of {Property name} of … {variable}

Samples

Logic with names:

Sample-when-name.PNG

Logic with no name:

Sample-when-no-name.PNG

Where r1, r2, r3, r4, and r5 are some other logic that are used in this logic.

Iterations

If you need to iterate on a list (i.e. array, or collection of objects) you can use for.

for variableName in listName
(
  /* do your tasks */
) 

When there is a condition to break the iteration, you include until to the for.

for variableName in listName until (expression)
(
  /* do your tasks */
) 

The loop executes while the evaluated expression is false.

Comments

Comments can be added to the rule document using /* and */.

Sample

Nl-sample-comments.PNG

Parameters

Parameters can be defined in standard way using Declaration section or inside the Dsl section.

Or alternatively they can be defied as part of the NL with the following keywords:

  1. input: defines input parameters.
  2. give: defines input parameters.
  3. output: defines output parameters.

Format:

[input|give|output] list of parameters, separated by comma

Example:

Nl-give-sample.PNG

Local Parameters

Local [Parameter]s can be added in two different levels:

  1. Root scope
  2. Logic scope

In the bellow example 'g' is defined as a local parameters in the logic scope.

when split {names} into groups
then
    /* defining a local parameter in a Logic scope. */
    local g;
    g = split(names,',');

    /* rest of your logic */
 end

Operators

In the body of logic, all the operators that are described in Expression section are accepted. On top of that, there are some specific operators in NL as follow:

  1. is: To check equality
  2. is not: To check inequality
  3. match: To check Regex pattern is matched
  4. match not: To check Regex pattern is not matched
  5. of: access to field and property on a parameter
  6. set/to: set a value to parameter or its underlying structure. An alias to Val.

Match

Format

[value|parameter|Term] [match | not match] pattern

Example

Email of person match ""\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*""

where Email is a property on person parameter.

Evaluation

Boolean expressions can be chained in the body of logic.

Format

exp = [boolean value | term [is|is not] value | boolean expression] 
condition = exp [and|or|nor|xor] | exp... 

Samples

Sample 1

A rule lik this:

R4: If all of the following are true, then the car’s potential theft rating is *low*.
	* car model is *not* on HTPA list
	* car’s price is between $20,000 and $45,000,


can be modelled as bellow:

N-sample-when-name2.PNG

Sample 2

In this example, we need to produce the result bellow(right) from a source(left):

Cars-data-question.png

We have two questions to answer:

  1. Cars in both groups (commonCars)
  2. Unique cars in each group (allUniqueCars)


input cars
/* 
commonCars: cars in both groups
allUniqueCars: unique cars in each groups
*/ 
output commonCars, allUniqueCars 

local g1,g2,ab,ba,groups  

when main 
then
	split into groups; 
	/* Intersect of two groups */
	commonCars = g1 
		     |select(x, x.Make, x.Model) 
		     |intersect (
			g2 |select(x, x.Make, x.Model)
	             );
				
	/* difference of first group from second one */
	ab = g1
	     |select (x, x.Make, x.Model) 
	     |except (
		g2 |select (x, x.Make, x.Model)
	     );
	
	/* difference of second group from first one*/
	ba = g2
	     |select (x, x.Make, x.Model) 
	     |except (
		 g1 |select (x, x.Make, x.Model)
	     );

	/* union the differences */
	allUniqueCars = ab |union (ba);
end
 
when split into groups
then
        /* As you see here, it allows you to split the logic
        and then you call it later by its name */ 
	groups = cars |groupBy (x, x.Group);
	g1 = groups[0];
	g2 = groups[1];
 end

Sample 3: Auto premium

Calculation of auto premium of a car in Natural Language:Add bonus of (12.3) to total amount

input car

when main
@processAll false

	test for Compact or
	test for Sedan or
	test for Luxury
end

when test for Compact
	(car.Style != 'Compact') or ((car.Model == 'abcd') and (car.ModelYear == 1999)) or
	car.ModelYear == 2002
then
	increase premium by (250) amount
end


when test for Sedan
	car.Style=='Sedan'
then
	increase premium by (400) amount
end


when test for Luxury
	car.Style=='Luxury'
then
	increase premium by (500) amount
end


when increase premium by {n} amount
then
	car.AutoPremium += n;
end

Notification

In NL document, $context can be used to write notifications.

Format: $context.WriteInfo(groupName, message)
        $context.WriteWarning(groupName, message)
        $context.WriteError(groupName, message)
  • groupName: to categorize a set of notices in notification collection. null when it is not needed.
  • message: any text, expression or value for the notice
Example: $context.WriteError(null, '$Assets is imputed.');

Inference

Inference capability allows rules dependencies to each other within on ruleset be resolved at runtime. Which means order of rules definition becomes irrelevant to the order of rules execution. Ro use inference command run on can be used:

run goal on {r1, r2, r3...}
  • goal (optional): name of the parameter that is the goal to be answered
  • r1,r2...: name of the rules i.e. when names

Example

when main
    run on {test for Compact, test for Sedan, test for Luxury}
end