OptaPy は、Python 用の AI 制約ソルバーであり、車両ルートの問題、従業員名簿、メンテナンス スケジュール、タスクの割り当て、学校の時間割、クラウドの最適化、会議のスケジュール、ジョブ ショップのスケジュール、ビンの梱包、その他多くの計画の問題を最適化します。
OptaPy は OptaPlanner エンジンを内部でラップしますが、Python で OptaPy を使用すると、Java または Kotlin で OptaPlanner を使用するよりも大幅に時間がかかります。
OptaPy Jupyter ノートブックを試してください。
JAVA_HOME
を JDK インストール ディレクトリに構成して、JDK 11 以降をインストールします。 OptaPy では、ドメインは 3 つの部分で構成されます。
問題の事実を宣言するには、 @problem_fact
デコレーターを使用します
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
プランニング エンティティを宣言するには、 @planning_entity
デコレータを使用します。
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
メソッドのデコレータは、どのフィールドを変更できるかを示すために使用されます。 get で始まり、対応する set メソッド (つまり、 get_room(self)
、 set_room(self, newRoom)
) がなければなりません。デコレータの最初のパラメータは、プランニング変数のタイプです (必須)。 value_range_provider_refs
パラメーターは、このプランニング変数が値を取得できるプランニング ソリューション上の値範囲プロバイダーを OptaPlanner に指示します。
@planning_id
は、特定のクラスのエンティティ オブジェクトを一意に識別するために使用されます。同じプランニング ID を異なるクラスのエンティティに使用できますが、同じクラス内のすべてのエンティティの ID は異なる必要があります。
計画ソリューションを宣言するには、 @planning_solution
デコレーターを使用します。
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)
メソッドがプランニング変数が取得できる値を返すことを示すために使用されます。 @planning_variable
のvalue_range_provider_refs
パラメーターの ID によって参照できます。 @problem_fact_collection_property
または@planning_entity_collection_property
も必要です。
@problem_fact_collection_property(type)
は、メソッドが問題の事実を返すことを示すために使用されます。デコレータの最初のパラメータは、問題ファクト コレクションのタイプです (必須)。リストである必要があります。
@planning_entity_collection_property(type)
は、メソッドがプランニング エンティティを返すことを示すために使用されます。デコレータの最初のパラメータは、プランニング エンティティ コレクションのタイプです (必須)。リストである必要があります。
@planning_score(scoreType)
は、OptaPlanner にスコアを保持するフィールドを指示するために使用されます。メソッドは get で始まり、対応する set メソッド (つまりget_score(self)
、 set_score(self, score)
) を持たなければなりません。デコレータの最初のパラメータはスコア タイプ (必須) です。
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 )
制約ストリームの詳細については、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
最後に見つかった最適なソリューションに設定された計画変数を持つTimeTable
インスタンスになります。
クイックスタートについては、optapy クイックスタート リポジトリにアクセスしてください。完全な API 仕様については、OptaPy のドキュメントを参照してください。