Search code examples
javaalgorithmdesign-patternsstrategy-pattern

Split a conditional expression programmatically


I am looking for a known way (if any) to split a long conditional expression into independent statements.

For example, I have this long expression:

*IF ( 
   ( *VALUE K01_PROCESS_COUNTS.Process_Name *EQ 'python' 
     *OR *VALUE K02_PROCESS_COUNTS.Process_Name *EQ 'java' ) 
   *AND 
   ( *VALUE K01_PROCESS_COUNTS.Process_Count *LT 1 
    *OR *VALUE K02_PROCESS_COUNTS.Process_Count *LT 2 )
 )

I want to get all the possible combinations for this statement to be true. Manually I can iterate a first time and get this:

*IF (
   ( *VALUE K01_PROCESS_COUNTS.Process_Name *EQ 'python' ) 
   *AND ( *VALUE K01_PROCESS_COUNTS.Process_Count *LT 1 
     *OR *VALUE K02_PROCESS_COUNTS.Process_Count *LT 2) )
*IF ( 
  ( *VALUE K02_PROCESS_COUNTS.Process_Name *EQ 'java' ) 
  *AND ( *VALUE K01_PROCESS_COUNTS.Process_Count *LT 1 
    *OR *VALUE K02_PROCESS_COUNTS.Process_Count *LT 2) )

And a second time I will have the full set of combinations:

*IF ( ( *VALUE K01_PROCESS_COUNTS.Process_Name *EQ 'python' ) 
   *AND ( *VALUE K01_PROCESS_COUNTS.Process_Count *LT 1 ) )
*IF ( ( *VALUE K01_PROCESS_COUNTS.Process_Name *EQ 'python' ) 
   *AND ( *VALUE K02_PROCESS_COUNTS.Process_Count *LT 2 ) )
*IF ( ( *VALUE K02_PROCESS_COUNTS.Process_Name *EQ 'java' ) 
   *AND ( *VALUE K01_PROCESS_COUNTS.Process_Count *LT 1 ) )
*IF ( ( *VALUE K02_PROCESS_COUNTS.Process_Name *EQ 'java' ) 
   *AND ( *VALUE K02_PROCESS_COUNTS.Process_Count *LT 2 ) )

I was thinking on doing this from scratch but I was wondering, is there any algorithm available for this type of operations? I have been searching for a while but I am unable to find it. I am working in Java, but any other language will work too.

Thanks!


Solution

  • We need to parse the statements and then apply a fairly simple recursive algorithm to expand the terms.

    to expand L *AND R:
        for l in expand(L):
            for r in expand(R):
                yield l *AND r
    
    to expand L *OR R:
        for l in expand(L):
            yield l
        for r in expand(R):
            yield r
    

    See https://github.com/eisenstatdavid/misc/blob/master/2017-02-10/dnf.go for a complete implementation in Go. The implementation also parses *NOT and simplifies expressions involving it using De Morgan's laws.