OptaPy เป็น ตัวแก้ปัญหาข้อจำกัดของ AI สำหรับ 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 และมีวิธี set ที่สอดคล้องกัน (เช่น get_room(self)
, set_room(self, newRoom)
) พารามิเตอร์แรกของมัณฑนากรคือประเภทของตัวแปรการวางแผน (จำเป็น) พารามิเตอร์ value_range_provider_refs
จะบอก OptaPlanner ว่าผู้ให้บริการช่วงค่าใดใน Planning Solution ที่ตัวแปรการวางแผนนี้สามารถรับค่าได้
@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)
ใช้เพื่อระบุวิธีการส่งคืนค่าที่ตัวแปรการวางแผนสามารถทำได้ สามารถอ้างอิงได้ด้วย 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 และมีวิธีการ 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 )
สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับ Constraint Streams โปรดดู 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