I have structure as below
Parameter -> Condition -> Rule
Let say i need to create a Business rule, Customer Age > 18
I have two parameters, Customer Age (P1) and 18(P2), where P1 is Field Parameter (Ognl) and P2 is constant Parameter with value 18.
So my Condition now is , Customer Age > 18 and so as my Rule.
Problem Statement : Avoid user from creating duplicate parameter/condition and rules.
Solution : Constant Parameters, Field Parameters etc i can check in DB and compare if already present.
Now condition for me,
Customer Age > 18 and 18 < Customer Age is same in business terms.
The above cases can be more complex.
(a + b) * (c + d) is same as (b + a) * (d + c)
I need to validate the above expressions.
First Approach - Load all expression from DB (Can be 10000's) and compare using Stack/Tree Structure, which will really kill my objective.
Second Approach - I was thinking of building power full, let say hashcode generator or we can say one int value against every expression (considering operators/brackets also). this value should be generated in such a way that it validates above expression.
Means a + b and b + a should generate same int value, and a - b and b - a should generate different.
Maybe a simplified version of your first approach: What about filtering only the relevant expressions by looking for similar content as you are about to insert into the database?
If you know that you are about to insert Customer Age you can find all expressions containing this parameter and build the stack/tree based on this reduced set of expressions.
I think that you cannot avoid writing a parser of expressions, building an AST of the expressions and code rewrite rules to detect expressions equivalence.
It may not be as time consuming as you think.
For the parsing and AST building part, you can start from exp4j:
http://www.objecthunter.net/exp4j/
For the rewrite rules, you can have a look at: Strategies for simplifying math expressions
For a 100% safe solution you should analyze the expressions with a computer algebra system to see whether there are mathemiatically equal. But that's not so easy.
A pragmatic approach that can be to test whether two expressions are similar:
Check whether they have the same variables
Compare their outputs for a number of different inputs, see if the outputs are equal
You can store the variable list and outputs for a predefined set of inputs as a "hash" for the expression. This hash does not give a guarentee that two expresions are equal, but you could present expressions with the same hash to the user asking if this new rule is equal to one of these similar ones.
Related
I want to sort something like this:
Given an ArrayList of objects with name Strings, I am trying to write the compareTo function such that Special T is always first, Special R is always second, Special C is always third, and then everything else is just alphabetical:
Special T
Special R
Special C
Aaron
Alan
Bob
Dave
Ron
Tom
Is there a standard way of writing this kind of compare function without needing to iterate over all possible combinations between the special cases and then invoking return getName().compareTo(otherObject).getName()); if it's a non-special case?
I would put the special cases in a HashMap<String, Integer> with the name as key and position as value. The advantages are:
search is in O(1) order of magnitude
The HashMap may be populated from an external source
I have to give the user the option to enter in a text field a mathematical formula and then save it in the DB as a String. That is easy enough, but I also need to retrieve it and use it to do calculations.
For example, assume I allow someone to specify the formula of employee salary calculation which I must save in String format in the DB.
GROSS_PAY = BASIC_SALARY - NO_PAY + TOTAL_OT + ALLOWANCE_TOTAL
Assume that terms such as GROSS_PAY, BASIC_SALARY are known to us and we can make out what they evaluate to. The real issue is we can't predict which combinations of such terms (e.g. GROSS_PAY etc.) and other mathematical operators the user may choose to enter (not just the +, -, ×, / but also the radical sigh - indicating roots - and powers etc. etc.). So how do we interpret this formula in string format once where have retrieved it from DB, so we can do calculations based on the composition of the formula.
Building an expression evaluator is actually fairly easy.
See my SO answer on how to write a parser. With a BNF for the range of expression operators and operands you exactly want, you can follow this process to build a parser for exactly those expressions, directly in Java.
The answer links to a second answer that discusses how to evaluate the expression as you parse it.
So, you read the string from the database, collect the set of possible variables that can occur in the expression, and then parse/evaluate the string. If you don't know the variables in advance (seems like you must), you can parse the expression twice, the first time just to get the variable names.
as of Evaluating a math expression given in string form there is a JavaScript Engine in Java which can execute a String functionality with operators.
Hope this helps.
You could build a string representation of a class that effectively wraps your expression and compile it using the system JavaCompiler — it requires a file system. You can evaluate strings directly using javaScript or groovy. In each case, you need to figure out a way to bind variables. One approach would be to use regex to find and replace known variable names with a call to a binding function:
getValue("BASIC_SALARY") - getValue("NO_PAY") + getValue("TOTAL_OT") + getValue("ALLOWANCE_TOTAL")
or
getBASIC_SALARY() - getNO_PAY() + getTOTAL_OT() + getALLOWANCE_TOTAL()
This approach, however, exposes you to all kinds of injection type security bugs; so, it would not be appropriate if security was required. The approach is also weak when it comes to error diagnostics. How will you tell the user why their expression is broken?
An alternative is to use something like ANTLR to generate a parser in java. It's not too hard and there are a lot of examples. This approach will provide both security (users can't inject malicious code because it won't parse) and diagnostics.
I'm working on implementing probablistic matching for person record searching. As part of this, I plan to have blocking performed before any scoring is done. Currently, there are a lot of good options for transforming strings so that they can be stored and then searched for, with similar strings matching each other (things like soundex, metaphone, etc).
However, I've struggled to find something similar for purely numeric values. For example, it would be nice to be able to block on a social security number and not have numbers that are off or have transposed digits be removed from the results. 123456789 should have blocking results for 123456780 or 213456789.
Now, there are certainly ways to simply compare two numerical values to determine how similar they are, but what could I do when there are million of numbers in the database? It's obviously impractical to compare them all (and that would certainly invalidate the point of blocking).
What would be nice would be something where those three SSNs above could somehow be transformed into some other value that would be stored. Purely for example, imagine those three numbers ended up as AAABBCCC after this magical transformation. However, something like 987654321 would be ZZZYYYYXX and 123547698 would be AAABCCBC or something like that.
So, my question is, is there a good transformation for numeric values like there exists for alphabetical values? Or, is there some other approach that might make sense (besides some highly complex or low performing SQL or logic)?
The first thing to realize is that social security numbers are basically strings of digits. You really want to treat them like you would strings rather than numbers.
The second thing to realize is that your blocking function maps from a record to a list of strings that identify comparison worthy sets of items.
Here is some Python code to get you started. (I know you asked for Java, but I think the Python is clear and you aren't paying me enough to write it in Java :P ). The basic idea is to take your input record, simulate roughing it up in multiple ways (to get your blocking keys), and then group on by any match on those blocking keys.
import itertools
def transpositions(s):
for pos in range(len(s) - 1):
yield s[:pos] + s[pos + 1] + s[pos] + s[pos + 2:]
def substitutions(s):
for pos in range(len(s)):
yield s[:pos] + '*' + s[pos+1:]
def all_blocks(s):
return itertools.chain([s], transpositions(s), substitutions(s))
def are_blocked_candidates(s1, s2):
return bool(set(all_blocks(s1)) & set(all_blocks(s2)))
assert not are_blocked_candidates('1234', '5555')
assert are_blocked_candidates('1234', '1239')
assert are_blocked_candidates('1234', '2134')
assert not are_blocked_candidates('1234', '1255')
For a programming project in Calculus we were instructed to code a program that models the Simpson's 1/3 and 3/8 rule.
We are supposed to take in a polynomial(i.e. 5x^2+7x+10) but I am struggling conceptualizing this. I have began by using scanner but is there a better way to correctly read the polynomial?
Any examples or reference materials will be greatly appreciated.
I'd suggest that you start with a Function interface that takes in a number of input values and returns an output value:
public interface Function {
double evaluate(double x);
}
Write a polynomial implementation:
public class Poly {
public static double evaluate(double x, double [] coeffs) {
double value = 0.0;
if (coeffs != null) {
// Use Horner's method to evaluate.
for (int i = coeffs.length-1; i >= 0; --i) {
value = coeffs[i] + (x*value);
}
}
return value;
}
}
Pass that to your integrator and let it do its thing.
A simple way (to get you started) is to use an array.
In your example: 5x^2 + 7x + 10 would be:
{10,7,5}
I.e. at index 0 is the factor 10 for x^0 at index 1 is 7 for x^1 at index 2 is 10 for x^2.
Of course this not the best approach. To figure out way figure out how you would represent x^20
In java it would be easiest to pre-format your input and just ask for constants--as in, "Please enter the X^2 term" (and then the X term, and then the constant).
If that's not acceptable, you are going to be quite vulnerable to input style differences. You can separate the terms by String.split[ting] on + and -, that will leave you something like:
[5x^2], [7x], [10]
You could then search for strings containing "x^2" and "x" to differentiate your terms
Remove spaces and .toLowerCase() first to counter user variances, of course.
When you split your string you will need to identify the - cases so you can negate those constants.
You could do two splits, one on + the other on -. You could also use StringTokenizer with the option to keep the "Tokens" which might be more straight-forward but StringTokenizer makes some people a little uncomfortable, so go with whatever works for you.
Note that this will succeed even if the user types "5x^2 + 10 + 7 x", which can be handy.
I believe parsing is my problem. I am somewhat new to java so this is troubling me.
You should use a parser generator.
A parser generator is a tool that reads a grammar specification and converts it to a Java program that can recognize matches to the grammar. In addition to the parser generator itself, JavaCC provides other standard capabilities related to parser generation such as tree building (via a tool called JJTree included with JavaCC), actions, debugging, etc.
JavaCC's FAQ answers How do I parse arithmetic expressions?
See the examples that come with JavaCC.
See any text on compiling.
See Parsing Epressions by Recursive Descent and a tutorial by Theodore Norvell.
Also, see JavaCC - Parse math expressions into a class structure
This is a question more about best practices/design patterns than regexps.
In short I have 3 values: from, to and the value I want to change. From has to match one of several patterns:
XX.X
>XX.X
>=XX.X
<XX.X
<=XX.X
XX.X-XX.X
Whereas To has to be a decimal number. Depending on what value is given in From I have to check whether a value I want to change satisfies the From condition. For example the user inputs "From: >100.00 To: 150.00" means that every value greater than 100.00 should be changed.
The regexp itself isn't a problem. The thing is if I match the whole From against one regexp and it passes I still need to check which option was inputted - this will generate at least 5 IFs in my code and every time I want to add another option I will need to add another IF - not cool. Same thing if I were to create 5 Patterns.
Now I have a HashMap which holds a pattern as the key and a ValueMatcher as the value. When a user inputs a From value then I match it in a loop against every key in that map and if it matches then I use the corresponding ValueMatcher to actually check if the value that I want to change satisfies the "From" value.
This aproach on the other hand requires me to have a HashMap with all the possibilities, a ValueMatcher interface and 5 implementations each with only 1 short "matches" methode. I think it sure is better than the IFs, but still looks like an exaggerated solution.
Is there any other way to do it? Or is this how I actually should do it? I really regret that we can't hold methods in a HashMap/pass them as arguments because then I'd only have 1 class with all the matching methodes and store them in a HashMap.
How about a chain of responsibility.
Each ValueMatcher object exactly one From/To rule and a reference to the next ValueMatcher in the chain. Each ValueMatcher has a method which examines a candidate and either transaforms it or passes it on to the next in the chain.
This way adding a new rule is a trivial extension and the controlling code just passes the candidate to the first member of the chain.
a ValueMatcher interface and 5 implementations each with only 1 short "matches" methode. I think it sure is better than the IFs, but still looks like an exaggerated solution.
Well, for something as simple as evaluating a number against an operator and a limit value, couldn't you just write one slightly more generic ValueMatcher which has a limit value and an operator as its parameters? It would then be pretty easy to add 5 instances of this ValueMatcher with a few combinations of >, >=, etc.
EDIT: Removed non Java stuff... sorry about that.