OptaPy هو حل لقيود الذكاء الاصطناعي لـ Python لتحسين مشكلة توجيه المركبات، وقوائم الموظفين، وجدولة الصيانة، وتعيين المهام، وجدول المواعيد المدرسية، وتحسين السحابة، وجدولة المؤتمرات، وجدولة متجر الوظائف، وتعبئة الصناديق والعديد من مشكلات التخطيط الأخرى.
يقوم OptaPy بتغليف محرك OptaPlanner داخليًا، ولكن استخدام OptaPy في Python أبطأ بكثير من استخدام OptaPlanner في Java أو Kotlin.
جرب دفتر OptaPy Jupyter.
JAVA_HOME
الذي تم تكوينه في دليل تثبيت JDK. في OptaPy، يتكون النطاق من ثلاثة أجزاء:
للإعلان عن حقائق المشكلة، استخدم مصمم الديكور @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 ولها طريقة ضبط مقابلة (على سبيل المثال get_room(self)
, set_room(self, newRoom)
). المعلمة الأولى لمصمم الديكور هي نوع متغير التخطيط (مطلوب). تخبر المعلمة value_range_provider_refs
OptaPlanner بموفري نطاق القيمة في حل التخطيط الذي يمكن لمتغير التخطيط هذا أخذ القيم منه.
يتم استخدام @planning_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)
للإشارة إلى أسلوب يُرجع القيم التي يمكن أن يأخذها متغير التخطيط. يمكن الرجوع إليه من خلال المعرف الخاص به في معلمة value_range_provider_refs
الخاصة بـ @planning_variable
. يجب أن تحتوي أيضًا على @problem_fact_collection_property
أو @planning_entity_collection_property
.
يتم استخدام @problem_fact_collection_property(type)
للإشارة إلى طريقة إرجاع حقائق المشكلة. المعلمة الأولى لمصمم الديكور هي نوع مجموعة حقائق المشكلة (مطلوب). يجب أن تكون قائمة.
يتم استخدام @planning_entity_collection_property(type)
للإشارة إلى طريقة إرجاع كيانات التخطيط. المعلمة الأولى لمصمم الديكور هي نوع مجموعة كيان التخطيط (مطلوب). يجب أن تكون قائمة.
يتم استخدام @planning_score(scoreType)
لإخبار OptaPlanner بالحقل الذي يحمل النتيجة. يجب أن تبدأ الطريقة بـ get ولها طريقة تعيين مقابلة (على سبيل المثال 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. للحصول على مواصفات واجهة برمجة التطبيقات الكاملة، قم بزيارة وثائق OptaPy.