Using Drools Planner, I created a planning solution for planning matches on tournaments. When I created a score calculating rule using the accumulate function, I realized that it behaves very strange. This is possibly because of Working Memory corruption. I think so, because I need to performa several changes in WM to recreate the problem. When I use only the last state of WM and put it in a freshly instantiated WM, it works fine.
Attached is an reproducer application. You can just unzip and run 'mvn test'. The test does not fail, but you can see the corruption in its output.
First, I would like to describe the solution. There are the following entities - Team, Group (a group of teams, usually only teams in the same group play together), Court, Match (between teams), and Slot (Slot connects a numbered time slot on a particular Court). A Match can be assigned to a Slot to denote which teams are supposed to play a match at the given court in the given time.
All of the teams, groups, courts, and maches appear in the WM at the beginning. Planner then adds slots and tries to assign Matches to the slots.
The test executed by 'mvn test', fills a WM with specific facts. Then it adds a Slot with some assignment and fires all rules. After that, different match is assigned to the slot and all rules are fired again. The last step is repeated several times.
The problematic rule is the following one:
Its main goal is for each team to collect all slots that has a match assigned in which this team has to play (Slot -> Match -> Teams_in_match contains Team).
Some data is collected for each Slot - most of these are just to show the bug. As you can see, only Slots that fulfills the condition 'teams contains $t' can be taken into account.
$ts refers to the set teams in this Slot. A list of these sets is collected ($tslist). On the RHS, this rule contains some debug output. It mainly prints out the team ($t) and the list of team sets (list of all $ts). According to the rule condition, each set in $tslist must contain the team $t. However, this is not true as you can see from the test output after 4th rules firing:
Team X0 does not appear in [Team X1, Team X2]. Because of that, wrong Slots are taken into account and the rule breaks the score.
Another problem is that the list of collected slots ($slist) and the set of collected slots ($sset) differ in size. The list simply contains some duplicates and this means that some Slots were considered multiple times. This can be seen after 3nd rules firing:
You can see the duplicate Slot in the list. I tried running equals() on them and they are equal. On the other hand, a Slot with teams X0 and X2 must have been considered because it appears in the list of $ts sets ([[Team X0, Team X2], [Team X0, Team X3]]). How is this possible? We no longer have a Slot assigned with the match between team X0 and X2.
Each step of rules firing produces an output in the following format:
In the output you can see all constraints that were created base on the WM content.