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 и иметь соответствующий метод 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)
используется для указания того, что метод возвращает значения, которые может принимать переменная планирования. На него можно ссылаться по его идентификатору в параметре 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 )
дополнительную информацию о потоках ограничений см. на странице 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.