We are doing POC on business rules using CodeEffects rule engine. Trying to write evaluation rules using rule editor. Here question is how to use + operator between custom functions to evaluate specific rule. For example, I would like to write rule like below
check if(somefunc(somevar1)+somefunc(somevar2)+somefun(somevar3) is greater than [1]
Please help how to write such rule in editor.
You need to use the calculation option (the "Add calculation..." menu item) as the value of your condition. Keep in mind that in Code Effects each condition must begin with either a field or an in-rule method. Because of that, your rule needs to be changed as follows:
Check if Somefunc(Somevar1) is greater than
{ Somefunc(Somevar2) + Somefunc(Somevar3) - [1] }
Notice that the result of the evaluation is still the same, I just moved some rule elements around.
Related
Is it possible to create a filtering system in FastAPI like:
?something[lte]=120&something2[in]=12,34
or
?something=lte:120&something2=in:12,34
And how to make OpenAPI documentation for it?
Imagine if there are many such endpoints and even more fields? I do not want to describe a set of fields with the same type of Depends classes with a certain logic parse (I don't know how to dynamically pass type annotating for it).
It is also not possible to subclass fastapi.Query and add extra logic to it.
Also there was an idea in the implementation of the f key as a query parameter:
?f=<field_name>:<operator>:<value>&f=<field_name N>:<operator>:<value>
But in this case, the documentation is not complete and you have to fill it in description (it will also be the same for all endpoints). As a result, it will not be clear which fields can be filtered and which operators are used for them.
I would like to annotate the first token of a text and use that annotation in following rules. I have tried different patterns:
Token.begin == 0 (doesn't work, although there definitely is a token that begins at 0)
Token{STARTSWITH(DocumentMetaData)}; (also doesn't work)
The only pattern that works is:
Document{->MARKFIRST(First)};
But if I try to use that annotation e.g. in the following way:
First{->MARK(FirstAgain)};
it doesn't work again. This makes absolutely no sense to me. There seems to be a really weird behaviour with annotations that start at 0.
This trivial task can be a bit tricky indeed, mainly because of the visibility settings. I do not know why your rules in the question do not work without having a look at the text that should be processed.
As for UIMA Ruta 2.7.0, I prefer a rule like:
# Token{->First};
Here some additional thoughts about the rules in the question:
Token.begin == 0;
Normally, there is not token with begin at 0 since the document starts with some whitespaces or line breaks. If there is actually a token that starts at offset 0 and the rule does not match, then something invisible is covering the begin of the end of the token. This depends of course of the filtering settings, but in case that you did not change them, it could be a bom.
Token{STARTSWITH(DocumentMetaData)};
Here, either the problem above applies, or the begin offset is not identical. If the DocumentMetaData covers the complete document, then I would bet on the leading whitespaces. Another reason could be that the internal indexing is broken, e.g., the tokens or the DocumentMetaData are created by an external analysis engine which was called with EXEC and no reindexing was configured in the action. This situation could also occur with unfortunate optimizations using the config params.
Document{->MARKFIRST(First)};
First{->MARK(FirstAgain)};
MARKFIRST creates an annotation using the offset of the first RutaBasic in the matched context IIRC. If the document starts with something invisible, e.g., a line break, then the second rule cannot match.
As a general advice in situations like this when some obvious simple rules do not work correctly as expected, I recommend adding some additional rules and using the debugging config with the explanation view. As rule like Token; can directly highlight if the visibility setting are problematic for the given tokens.
DISCLAIMER: I am a developer of UIMA Ruta
This might be a trivial question, but I'm new to Ruta so bear with me please.
My testdata consists of numbers in the following format:
0.1mm 0,11mm 1.1mm 1,1mm 1mm
I use the following rule to annotate the first four examples:
((NUM(COMMA|PERIOD)NUM) W{REGEXP("mm")}) {-> nummm};
Document{->MARK(nummm)};
Now I want to annotate "1mm", for example, too, but I'm kind of stuck right now, because I have no idea how to do this. I tried negating Conditions, like AFTER (as in "if NUM mm not after comma or period"), but it either didn't work or the syntax was wrong. Any help would be appreciated!
EDIT: I should add that I want to annotate "1mm", but not the 1mm part after a comma or period, as of right now i basically annotate everything twice.
There are really a lot of ways to specify this in UIMA Ruta.
Here's the first thing that came to my mind:
(NUM{-PARTOF(nummm)} (PM{PARTOF({COMMA,PERIOD})} NUM)? W{REGEXP("mm")}){-> nummm};
This is probably not the "best" rule but should do what you want. There are three main changes:
I made the middle part of the rule optional so that it also matches on a single NUM.
I added the negated PARTOF of at the first rule element thus the matching will fail if the starting point is already covered by a nummm annotation. The - is a shortcut for the NOT condition.
I replaced the expensive disjunctive composed rule element with a simple one just because it is not really necessary here.
This rule works because the actions of a rule match are already executed before the next rule match is considered.
DISCLAIMER: I am a developer of UIMA Ruta.
My rules in a drl file will return 1 or more String values back to the calling program.
Right now the way I do that is via global variables as below
global java.util.List<String> statuses;
The calling program will pass it an empty ArrayList() and within my rules, I'll add the String values into the List. Finally, my calling program will retrieve the statuses list that might contain zero or many String items in the list as below
session.getGlobal("statuses")
But in the drools user guide, it said that it's not recommended that rules should change values of the global variables.
Are global variables the best way to return values back to the calling program? If not, what's the best way please? I have to deal with concurrency in my web application as well so I'm looking for the best way to return values back to the calling program for concurrency as well.
Thanks
There is nothing wrong with changing the value of a global variable in the code within the consequence ("right hand side") of a rule. What you describe is one of standard use cases for globals.
What the author of the Drools user guide (please add the exact reference!) meant is that changes of a global that is used in the condition ("left hand side") of a rule are not considered in the (re-)evaluation of these conditions. Therefore, this is to be avoided.
As for concurrency: Use a properly synchronized List object as a global.
I am testing a rather complex system, which behaves according to some business rules (written as semi-formal text).
The goal is to create test cases, which cover as many states of the system as possible. I want to automate this task in the following way:
1) Formalize the business rules in Drools
2) Then use some mechanism to create a list of all possible situations (which need to be tested)
For example, I have following business rule package with two rules (this is only an example, real business rules are much more complex):
global List outErrorCodes;
global Boolean condition1;
global Boolean condition2;
global Boolean condition3;
rule "01"
when
eval( condition3 == false);
then
outErrorCodes.add("ERROR_CODE1");
end
rule "02"
when
eval((condition1 == true) && (condition2 == true));
then
outErrorCodes.add("ERROR_CODE2");
end
condition1, condition2 and condition3 are inputs.
outErrorCode is the output.
That is, condition1, condition2 and condition3 describe a certain situation, and outErrorCode describes the expected behaviour of the system in that particular situation.
I want to create a mechanism, which automatically creates a list of all possible tuples (condition1, condition2, condition3, outErrorCodes), based on the logic in the rules. Each tuple represents a state of the system.
These tuples will then be used as a basis for creating actual test cases.
Is it possible with Drools? If so - how?
Many thanks in advance
Dmitri
We had success in taking the ruleset, deploying it as a service using drools-server, and then writing a script to make web service calls exercising each possible value of each input variable. Within about an hour we were able to make 5000+ calls to our rule base and see output for each case.
The downside (and I don't think you will get around this with any solution) is that you are testing business logic. When you think about it, you can generate all the test data you want, but you can't generate test input and an expected result without running the business logic (which you are testing). Just saying that if you get into auto generating input to business logic, you can't actually know the expected results without violating the integrity of the test.