Ava
Ava

Reputation: 512

Remove/Add constraints - optaplanner

Is it possible to make some rules be completely ignored? I have a set of rules, but I want the user to be able to add certain inputs, like they want rule 1, rule 2, rule 3, rule 5, but maybe not rule 4. So I want the program to recognise this, and not at all enter rule 4 while checking for constraint violation

How could I go about this?

Upvotes: 0

Views: 209

Answers (2)

ricardo.scholz
ricardo.scholz

Reputation: 128

I've got a similar problem, except that I wanted users to control each rule weight [0 to 10] instead of a binary control [active - inactive]. I'm not sure about this being a performance optimized answer (worked for me in reasonable time, but of course that depends on your corpus size).

The approach we used was creating a Singleton which holds each rule weight set by the user in volatile memory, using a HashMap<Integer, Integer> for faster random access (key = rule number, value = rule weight), as the inference engine may call it several times.

Then, in our rule files we checked if a given rule was active in when clause, and updated score in then clause according to the actual rule weight:

import my.rules.singleton.package.MyRulesWeightSingleton;

rule "1"
    when
        eval(MyRulesWeightSingleton.isRuleActive(1))
        //other conditions here.
    then
        scoreHolder.addHardConstraintMatch(kcontext, MyRulesWeightSingleton.getRuleWeight(1));
end

The Singleton would look like this:

import java.util.HashMap;

public class MyRulesWeightSingleton {

    private static MyRulesWeightSingleton instance;
    private HashMap<Integer, Integer> weights;

    private MyRulesWeightSingleton() {
        this.weights = new HashMap<Integer, Integer>();
    }

    public static MyRulesWeightSingleton getInstance() {
        if (instance == null) {
            instance = new MyRulesWeightSingleton();
        }
        return instance;
    }

    public boolean isRuleActive(int ruleId) {
        Integer weight = weights.get(ruleId);
        return (weight != null && weight > 0);
    }

    public int getRuleWeight(int ruleId) {
        Integer weight = weights.get(ruleId);
        if (weight != null) {
            return weight;
        }
        return 0;
    }

    //Allows you to put and remove weights information
    //before running planner.
    public HashMap<Integer, Integer> getWeights() {
        return this.weights;
    }
}

PS: Our actual problem here was a bit more complicated than this, so I simplified our approach for didatical reasons. ;)

Upvotes: 0

laune
laune

Reputation: 31290

A simple solution would be the creation of

class Guard {
    String rulename; ... }

and the addition of patterns to your rule

rule rule_1
when
    Guard( rulename == "rule_1" )
    ...

Then you need to insert the Guard facts for the rules that should be blocked.

Upvotes: 1

Related Questions