Rikkola opened a new issue, #7045:
URL: https://github.com/apache/incubator-kie/issues/7045

   Explanations that hopefully help understanding the code changes.
   
   First of all. Bilinear is off by default. The default setting can be changed 
with `drools.bilinear.enabled=true`. I have also built the entire code base 
with bilinear enabled and it passes.
   
   The goal is to share a part of the network. 
   `rule1 has A() B() C() D()` 
   and 
   `rule2 has C() D() // We can share C() D()`
   
   We can only share if there are no references between from the shared part to 
the rest of the rule. 
   ```
   rule1 A(x:x) B() C(x == x) D()
   rule2 C(x == x) D() // This does not work.
   ```
   
   # Network structure
   ## Without bilinear join
   ```
   📊 ObjectTypeNodes found: 5
   ┌─────────────────────────────────────────────────────────────┐
   │ 🏭 OTN: A (id=3)
   │   └─ ⬅️ LeftInputAdapterNode (id=4)
   │     └─ 🔗 JoinNode (id=7) 🔗 [no constraints]
   │       └─ 🔗 JoinNode (id=10) 🔗 [no constraints]
   │         └─ 🔗 JoinNode (id=13) 🔗 [no constraints]
   │           └─ 🏁 RuleTerminalNode (id=14) 🏁 [Rule1]
   │
   │ 🏭 OTN: B (id=5)
   │   └─ ➡️ JoinRightAdapterNode (id=6)
   │     ├─ ➡️  Adapts to: JoinNode (id=7)
   │
   │ 🏭 OTN: C (id=8)
   │   ├─ ➡️ JoinRightAdapterNode (id=9)
   │   │ ├─ ➡️  Adapts to: JoinNode (id=10)
   │   └─ ⬅️ LeftInputAdapterNode (id=15)
   │     └─ 🔗 JoinNode (id=17) 🔗 [no constraints]
   │       └─ 🏁 RuleTerminalNode (id=18) 🏁 [Rule2]
   │
   │ 🏭 OTN: D (id=11)
   │   ├─ ➡️ JoinRightAdapterNode (id=12)
   │   │ ├─ ➡️  Adapts to: JoinNode (id=13)
   │   └─ ➡️ JoinRightAdapterNode (id=16)
   │     ├─ ➡️  Adapts to: JoinNode (id=17)
   │
   │ 🏭 OTN: InitialFactImpl (id=2)
   │
   └─────────────────────────────────────────────────────────────┘
   ```
   ## With bilinear join
   ```
   📊 ObjectTypeNodes found: 5
   ┌─────────────────────────────────────────────────────────────┐
   │ 🏭 OTN: A (id=9)
   │   └─ ⬅️ LeftInputAdapterNode (id=10)
   │     └─ 🔗 JoinNode (id=13) 🔗 [no constraints]
   │       └─ 🔗 BiLinearJoinNode (id=14) 🔗 [left=13, right=7]
   │         └─ 🏁 RuleTerminalNode (id=15) 🏁 [Rule1]
   │
   │ 🏭 OTN: B (id=11)
   │   └─ ➡️ JoinRightAdapterNode (id=12)
   │     ├─ ➡️  Adapts to: JoinNode (id=13)
   │
   │ 🏭 OTN: C (id=3)
   │   └─ ⬅️ LeftInputAdapterNode (id=4)
   │     └─ 🔗 JoinNode (id=7) 🔗 [no constraints]
   │       ├─ 🏁 RuleTerminalNode (id=8) 🏁 [Rule2]
   │       └─ 🔗 BiLinearJoinNode (id=14) 🔗 [left=13, right=7]
   │         └─ 🏁 RuleTerminalNode (id=15) 🏁 [Rule1]
   │
   │ 🏭 OTN: D (id=5)
   │   └─ ➡️ JoinRightAdapterNode (id=6)
   │     ├─ ➡️  Adapts to: JoinNode (id=7)
   │
   │ 🏭 OTN: InitialFactImpl (id=2)
   │
   └─────────────────────────────────────────────────────────────┘
   ```
   
   Before building the network we use `BiLinearDetector` to find candidates for 
bilinear joins. 
   Right now the mechanism is limited. We only look for other rules that 
already create a network that can be shared with the end of another rule. This 
is one of the improvement points for the future.
   It uses hashes for each pattern and generates a tail hash, that is the hash 
for the chain of patterns starting from the current pattern and including every 
pattern after it. Once two hashes are same, we can share that part of the 
network.
   
   Each bilinear opportunity is a `JoinNode` that can be replaced with a 
`BiLinearJoinNode`.
   `BiLinearJoinNode` takes two left inputs, instread of a left and right. To 
make this work, `BetaRightInput` was added as an interface to serve the right 
input for other nodes and second left for `BiLinearJoinNode`.
   `BiLinearJoinNode` takes the first left input when rule1 is created ( A() 
B() -> BiLinear join ), this leaves it half done. Then when the second rule2 is 
created we link the other left bringing in the shared network, ( D() C() -> 
BiLinear join ). Due to this the order of the rule creation sometimes needs to 
be reordered.
   
   This PR proves that bilinear joins works. There next step after this is to 
increase the bilinear reuse.
   * Detect network areas that can be shared from any part of the rule. Look 
for independent isolated sections that appear in other rules.
   * Get rid of the rule ordering issue, just build the network parts that are 
shared last. Not rules.
   * The shared network should support bilinear joins inside bilinear joins.
   
   The additional changes will be smaller PRs. I have experimented with a 
solution for each task, but haven't done a perfectly working solution yet.
   One of the use cases that will get the most out of these changes is decision 
table like structures where certain patterns and constraints tend to repeat.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to