0

I'm newbie here and my English isn't that good, so I hope what I want to explain can reach all of you. Now I am using Python library called Optapy, and I tried to try it to auto scheduling production in my factory.

I set Schedule Class as a planning entity with this code snippet:

from optapy import planning_entity, planning_variable

@planning_entity
class Schedule:
    today_date:date
    part:Part
    machine:Machine
    operator:Operator
    timeslot:Timeslot
    
    def __init__(self, id:int, today_date:date , part:Part = None, machine:Machine = None, operator: Operator = None, timeslot:Timeslot = None):
        self.id = id
        self.today_date = today_date
        self.part = part
        self.machine = machine
        self.operator = operator
        self.timeslot = timeslot
    @planning_id
    def get_id(self):
        return self.id
    
    @planning_variable(Part,["partRange"])
    def get_part(self):
        return self.part
    
    def set_part(self, new_part):
        self.part = new_part
    
    @planning_variable(Machine,["machineRange"])
    def get_machine(self):
        return self.machine
    
    def set_machine(self, new_machine):
        self.machine = new_machine
    
    @planning_variable(Timeslot,["timeslotRange"])
    def get_timeslot(self):
        return self.timeslot
    
    def set_timeslot(self, new_timeslot):
        self.timeslot = new_timeslot

    def __str__(self) -> str:
        return (
            f"Production("
            f"id={self.id},"
            f"part={self.part},"
            f"machine={self.machine},"
            f"timeslot={self.timeslot},"
            f"shift ={self.timeslot.shift.value}"
        )

Then I set the constraint like this :

from optapy import constraint_provider
from optapy.score import HardSoftScore
from optapy.constraint import Joiners, ConstraintFactory

@constraint_provider
def define_constraints(constraint_factory: ConstraintFactory):
    return [
        # Hard constraints
        machine_conflict(constraint_factory),
        less_than_8_workhours(constraint_factory),
    ]

def machine_conflict(constraint_factory: ConstraintFactory):
    return constraint_factory \
        .from_(Schedule) \
        .join(Schedule,
              Joiners.equal(lambda schedule: schedule.timeslot),
              Joiners.equal(lambda schedule: schedule.machine),
              Joiners.equal(lambda schedule: schedule.today_date),
              Joiners.less_than(lambda schedule: schedule.id)
              ) \
        .penalize("Machine conflict", HardSoftScore.ONE_HARD)
    #HARD
    
def less_than_8_workhours(constraint_factory: ConstraintFactory):
         
    return constraint_factory \
        .for_each(Schedule) \
        .join(Schedule,
              Joiners.equal(lambda schedule: schedule.operator),
              Joiners.equal(lambda schedule: schedule.today_date)
              ) \
        .filter(lambda schedule1, schedule2: sum(1 for slot in schedule2 if slot.operator == schedule1.operator and slot.today_date == schedule1.today_date)<4) \
        .penalize("At least 8 Workhours a day", HardSoftScore.ONE_HARD)
    #HARD

When I tried to verify the Less_than_8_workhours Constraint, I got this error messages : org.drools.modelcompiler.constraints.ConstraintEvaluationException: org.drools.modelcompiler.constraints.ConstraintEvaluationException: Error evaluating constraint '' in and in more rules

I think I had mistakes during constraint defining, but I dont know how to fix it. For further information, I use Timeslot in my problem_fact. 1 timeslot is about 2 hours long. With this being said, to prevent the computer to let 1 operator only work less than 8 hours a day, I want to join all Schedule with the same operator and today_date, and count it then check it, whether it is less than 4 or not. If it is, then it violates the constraint.

Geoffrey De Smet
  • 26,223
  • 11
  • 73
  • 120

1 Answers1

0

This looks like a bug in constraintStreamType=DROOLS, you might want to try constraintStreamType=BAVET by calling SolverConfig.withConstraintStreamType(BAVET).

Geoffrey De Smet
  • 26,223
  • 11
  • 73
  • 120