OptaPy ist ein KI-Einschränkungslöser für Python zur Optimierung des Fahrzeugroutingproblems, der Mitarbeiterplanung, der Wartungsplanung, der Aufgabenzuweisung, der Schulstundenplanung, der Cloud-Optimierung, der Konferenzplanung, der Werkstattplanung, der Behälterverpackung und vieler weiterer Planungsprobleme.
OptaPy umschließt die OptaPlanner-Engine intern, aber die Verwendung von OptaPy in Python ist deutlich langsamer als die Verwendung von OptaPlanner in Java oder Kotlin.
Probieren Sie das OptaPy Jupyter-Notebook aus.
JAVA_HOME
die für das JDK-Installationsverzeichnis konfiguriert ist. In OptaPy besteht die Domäne aus drei Teilen:
Um Problemfakten zu deklarieren, verwenden Sie den @problem_fact
Dekorator
from optapy import problem_fact
@ problem_fact
class Timeslot :
def __init__ ( self , id , day_of_week , start_time , end_time ):
self . id = id
self . day_of_week = day_of_week
self . start_time = start_time
self . end_time = end_time
Um Planungsentitäten zu deklarieren, verwenden Sie den @planning_entity
Dekorator
from optapy import planning_entity , planning_id , planning_variable
@ planning_entity
class Lesson :
def __init__ ( self , id , subject , teacher , student_group , timeslot = None , room = None ):
self . id = id
self . subject = subject
self . teacher = teacher
self . student_group = student_group
self . timeslot = timeslot
self . room = room
@ planning_id
def get_id ( self ):
return self . id
@ planning_variable ( Timeslot , value_range_provider_refs = [ "timeslotRange" ])
def get_timeslot ( self ):
return self . timeslot
def set_timeslot ( self , new_timeslot ):
self . timeslot = new_timeslot
@ planning_variable ( Room , value_range_provider_refs = [ "roomRange" ])
def get_room ( self ):
return self . room
def set_room ( self , new_room ):
self . room = new_room
@planning_variable
-Methodendekoratoren werden verwendet, um anzugeben, welche Felder geändert werden können. MUSS mit get beginnen und über eine entsprechende Set-Methode verfügen (z. B. get_room(self)
, set_room(self, newRoom)
). Der erste Parameter des Dekorators ist der Typ der Planungsvariablen (erforderlich). Der Parameter value_range_provider_refs
teilt OptaPlanner mit, aus welchen Wertebereichsanbietern in der Planungslösung diese Planungsvariable Werte übernehmen kann.
@planning_id
wird verwendet, um ein Entitätsobjekt einer bestimmten Klasse eindeutig zu identifizieren. Die gleiche Planungs-ID kann für Entitäten verschiedener Klassen verwendet werden, aber die IDs aller Entitäten derselben Klasse müssen unterschiedlich sein.
Um die Planungslösung zu deklarieren, verwenden Sie den @planning_solution
Dekorator
from optapy import planning_solution , problem_fact_collection_property , value_range_provider , planning_entity_collection_property , planning_score
@ planning_solution
class TimeTable :
def __init__ ( self , timeslot_list , room_list , lesson_list , score = None ):
self . timeslot_list = timeslot_list
self . room_list = room_list
self . lesson_list = lesson_list
self . score = score
@ problem_fact_collection_property ( Timeslot )
@ value_range_provider ( range_id = "timeslotRange" )
def get_timeslot_list ( self ):
return self . timeslot_list
@ problem_fact_collection_property ( Room )
@ value_range_provider ( range_id = "roomRange" )
def get_room_list ( self ):
return self . room_list
@ planning_entity_collection_property ( Lesson )
def get_lesson_list ( self ):
return self . lesson_list
@ planning_score ( HardSoftScore )
def get_score ( self ):
return self . score
def set_score ( self , score ):
self . score = score
@value_range_provider(range_id)
wird verwendet, um anzugeben, dass eine Methode Werte zurückgibt, die eine Planungsvariable annehmen kann. Es kann über seine ID im Parameter value_range_provider_refs
von @planning_variable
referenziert werden. Es sollte auch eine @problem_fact_collection_property
oder eine @planning_entity_collection_property
haben.
@problem_fact_collection_property(type)
wird verwendet, um anzugeben, dass eine Methode Problemfakten zurückgibt. Der erste Parameter des Dekorators ist der Typ der Problem Fact Collection (erforderlich). Es sollte eine Liste sein.
@planning_entity_collection_property(type)
wird verwendet, um anzugeben, dass eine Methode Planungsentitäten zurückgibt. Der erste Parameter des Dekorators ist der Typ der Planning Entity Collection (erforderlich). Es sollte eine Liste sein.
@planning_score(scoreType)
wird verwendet, um OptaPlanner mitzuteilen, welches Feld die Punktzahl enthält. Die Methode MUSS mit get beginnen und über eine entsprechende Set-Methode verfügen (z. B. get_score(self)
, set_score(self, score)
). Der erste Parameter des Dekorators ist der Score-Typ (erforderlich).
Sie definieren Ihre Einschränkungen mithilfe der ConstraintFactory
from domain import Lesson
from optapy import constraint_provider
from optapy . types import Joiners , HardSoftScore
@ constraint_provider
def define_constraints ( constraint_factory ):
return [
# Hard constraints
room_conflict ( constraint_factory ),
# Other constraints here...
]
def room_conflict ( constraint_factory ):
# A room can accommodate at most one lesson at the same time.
return constraint_factory . for_each_unique_pair ( Lesson ,
# ... in the same timeslot ...
Joiners . equal ( lambda lesson : lesson . timeslot ),
# ... in the same room ...
Joiners . equal ( lambda lesson : lesson . room ))
. penalize ( "Room conflict" , HardSoftScore . ONE_HARD )
Weitere Einzelheiten zu Constraint Streams finden Sie unter https://www.optaplanner.org/docs/optaplanner/latest/constraint-streams/constraint-streams.html
from optapy import solver_factory_create
from optapy . types import SolverConfig , Duration
from constraints import define_constraints
from domain import TimeTable , Lesson , generate_problem
solver_config = SolverConfig (). withEntityClasses ( Lesson )
. withSolutionClass ( TimeTable )
. withConstraintProviderClass ( define_constraints )
. withTerminationSpentLimit ( Duration . ofSeconds ( 30 ))
solver = solver_factory_create ( solver_config ). buildSolver ()
solution = solver . solve ( generate_problem ())
solution
handelt es sich um eine TimeTable
Instanz mit Planungsvariablen, die auf die letztendlich beste gefundene Lösung eingestellt sind.
Für Schnellstarts besuchen Sie das Optapy-Schnellstart-Repository. Eine vollständige API-Spezifikation finden Sie in der OptaPy-Dokumentation.