Search code examples
serviceclouddroolsoptaplanner

Drools rule for processes belonging to services (inverse optaplanner tutorial assignment)


I would like to implement a simple (?) rule in drools connected with the cloudbalancing example in optaplanner: Instead of having processes of a particular service on different computers ("2.1.8: Beyond this tutorial"), there should be a cost involved for a first process of any given service on any given computer:

rule "changeCost"

    when

       $computer: CloudComputer($changecost : getchangeCost())
       $process: CloudProcess($service: service, computer== $computer)
       $NumberOfProcessesOfSameServiceInComputer: Number (intValue == 0) from accumulate ( $a:
        CloudProcess (
            computer== $computer,
            service== $service),
        count($a)
       )

    then

    scoreHolder.addSoftConstraintMatch(kcontext, - $changecost);

end

Of course I have added an item (?) "service" in the class CloudProcess and the item changecost in the class CloudComputer with the getters/setters. The code compiles great, but other than getting really slow, the assignment takes place as usual (i.e., as if there were no services). What is the matter?

Thanks in advance for your help.


Solution

  • I can well imagine that this rule slows everything down. See what you are doing:

    rule "changeCost"

    when
       $computer: CloudComputer($changecost : getchangeCost())
    

    Match any CloudComputer instance - OK.

       $process: CloudProcess($service: service, computer== $computer)
    

    Match any (!) CloudProcess instance with some service on that CloudComputer

       $NumberOf: Number (intValue == 0)
                 from accumulate ( $a: CloudProcess (
            computer== $computer,
            service== $service),
        count($a)
    

    Count the likes of that CloudProcess (computer, service).

    So, once you have established one CloudProcess instance with some service, its likes are counted, but the same thing happens for any other CloudProcess instance of the same kind, and it happens for all kinds of services...

    Moreover, the rule will just cause fact evaluations, but it will never fire. The second pattern establishes that there is (at least) one CloudProcess with some service for the CloudComputer established by the first pattern. The accumulate counts its likes, but then the constraint says that the counted number must be zero - clearly an impossibility after matching the second pattern.

    If you need to establish that there is exactly one CloudProcess of a kind, you can use

    when
      $computer: CloudComputer($changecost : getchangeCost())
      $cp: CloudProcess($service: service, computer== $computer)
      not CloudProcess( computer== $computer, service== $service, this != $cp)
    then