Search code examples
javadrools

Drools rule implementation


I have a rule that I do not know if it is possible to implement in drools.

The description: A, L, P are all facts/POJOs which are connected. I need to find out if each A can be assigned to a free P through L. And if not, how many A elements are left unassigned.

Fact model diagram

In the case above one A will be left unassigned.

I thought up an algorithm that is simple to describe:

  1. Find A with least edges

    • If A has no edges, increase result counter by 1, remove A
  2. Choose random L->P from that A and remove the A, L, P elements

  3. Repeat until there are no A left

I'm having a hard time describing that in drools. I'm no expert in drools rules. In JAVA, you'd have to do a lot of manipulations with collections, including sorting, which drools does not seem to support. Is it possible to do this somehow in drools?


Solution

  • Here is a set of rules that implements the algorithm. It will not be very efficient on large numbers of As and Ps. A pure Java solution shouldn't be all that difficult either. Note that a complete sort isn't necessary after removing one A from the set and clearing away all dangling L and P objects.

    rule findMin
    when
        $mina: A( $edges: edges )
        not A( edges.size() < $edges.size() )
    then
        System.out.println( "retract " + $mina );
        retract( $mina );
    end
    
    rule countFail extends findMin
    when
        eval( $edges.size() == 0 )
    then
        Main.counter++;
        System.out.println( "fail to match " + $mina );
    end
    
    rule matchLP extends findMin
    when
        $l: L( this memberOf $edges, $p: p )
    then
        retract( $p );
        retract( $l );
        System.out.println( "retract " + $p + " and " + $l );
    end
    
    rule cleanup
    salience 10
    when
        $l: L( $p: p )
        not P( this == $p )
        $a: A( edges contains $l )
    then
        retract( $l );
        modify( $a ){
            remove( $l );
        }
        System.out.println( "cleanup " + $l + ", " + $a );
    end