Search code examples
optaplannerdrools-planner

update planning variable's property during planning


I am using optaplanner to solve a scheduling problem. For proprietary reasons I am using analogy to ask the question instead of posting the actual problem

I need to do assign books to different people based on some constraints. Here is how i have modeled the problem:

Role - ProblemFact [Executive, Supervisor etc]

Person - ProblemFact [List of different people and each have a role assigned]

Book - ProblemFact and Planning Variable. It has bookCode and bookStatus properties.

BookAssignment - Planing Entity. It has book and person object.

Each book has some logical status(new, used). Each book's status is initialized to new/used based on some history. The book assignment depends on the status of the book that I am handling in drools file. One of the requirement is that a new book should be assigned to certain role, after assignment the book status should be changed from new to used during planning.

For example the rule is: role = executive gets new book, all other roles gets used book lets say I have 3 books: books1 = new, book2 = new, book3= used

During planning when planner assigns 'book1' to a person with role= 'executive', after this assignment the book1 status should be changed to "used". For the next assignment to another person with the executive role, book1 can not be used because its status is used.

I need to update the property(bookStatus) of planning variable (Book) during planning. How do i achieve this functionality using optaplanner?

I read about shadow variables but it does not fit the model that i have.

Your help is very much appreciated!


Solution

  • FWIW just closing the loop here. I hope it helps someone else who is also new to optaplanner and drools :)

    I solved this issue in a different way details here

    My use case requires to use 'book1' with new status only once so I implemented a hard constraint in drools file that uses accumulate function.

    rule "Every new book is used once" when $total: Number(this > 1) from accumulate ( BookAssignment(book != null , book.status == BookStatusEnum.NEW), sum(1)) then scoreHolder.addHardConstraintMatch(kcontext, -10); end