Các nhà phát triển Python hiện có thể giải quyết các vấn đề về lập kế hoạch AI [chẳng hạn như vấn đề định tuyến phương tiện và phân công nhân viên] bằng OptaPy. Hãy để tôi chỉ cho bạn cách sử dụng OptaPy và một chút mã Python đơn giản để giải quyết vấn đề tối ưu hóa toán học điển hình. tạo thời khóa biểu học tốt hơn cho giáo viên và học sinh. OptaPy là một dự án mã nguồn mở. Nó có sẵn trong PyPI và có thể sử dụng được từ bản cài đặt Python thông thường. Trong nội bộ, OptaPy sử dụng OptaPlanner, vì vậy nó cần cài đặt JDK. Hiện tại, nó chậm hơn đáng kể so với việc sử dụng OptaPlanner trực tiếp từ Java [hoặc Kotlin cho vấn đề đó], nhưng nó hoạt động và chúng tôi đang nghiên cứu các cách để thu hẹp khoảng cách về hiệu suất. Hãy tối ưu hóa thời gian biểu của trường đó bằng Python thuần túy. Vui lòng theo dõi trong sổ ghi chép OptaPy Jupyter
điều kiện tiên quyết
Trăn 3. 9 trở lên được cài đặt
JDK 11 trở lên được cài đặt với biến môi trường Java_HOME được định cấu hình cho thư mục cài đặt JDK
Cài đặt
Tạo môi trường ảo Python mới
python3 -m venv optapy-env
Kích hoạt môi trường ảo Python
source optapy-env/bin/activate
Sử dụng pip để cài đặt OptaPy
python3 -m pip install optapy
thời gian biểu của trường
Trong thời khóa biểu ở trường, chúng ta cần gán một danh sách các bài học cho các khoảng thời gian và phòng. Ngoài ra, có một số ràng buộc
Một phòng có thể có nhiều nhất một bài học cùng một lúc
Một giáo viên có thể dạy cùng một lúc nhiều nhất một tiết học
Một học sinh có thể tham dự nhiều nhất một buổi học cùng một lúc
Một giáo viên thích dạy tất cả các bài học trong cùng một phòng
Một giáo viên thích dạy các bài học theo trình tự và không thích khoảng cách giữa các bài học
Một học sinh không thích các bài học liên tiếp về cùng một chủ đề
Mô hình hóa miền
Các đối tượng được sử dụng trong các ràng buộc được gọi là miền của vấn đề. Trong thời gian biểu của trường, miền bao gồm các bài học, phòng và thời gian biểu
Sự kiện vấn đề
Sự thật vấn đề không thay đổi trong suốt quá trình giải quyết. Phòng và thời gian là ví dụ về sự thật của vấn đề. Tạo một tệp
source optapy-env/bin/activate
3 với đoạn mã sau để tạo lớp source optapy-env/bin/activate
4from optapy import problem_fact, planning_id
@problem_fact
class Room:
def __init__[self, id, name]:
self.id = id
self.name = name
@planning_id
def get_id[self]:
return self.id
def __str__[self]:
return f"Room[id={self.id}, name={self.name}]"
Trình trang trí
source optapy-env/bin/activate
5 đăng ký lớp như một sự thật của vấn đề, điều này cho phép nó được sử dụng trong các ràng buộc. Người trang trí source optapy-env/bin/activate
6 đăng ký source optapy-env/bin/activate
7 làm ID lập kế hoạch cho source optapy-env/bin/activate
4. OptaPlanner yêu cầu ID lập kế hoạch cho một số chức năng, chẳng hạn như tạo các cặp duy nhất. ID lập kế hoạch phải là duy nhất cho các phiên bản của cùng một lớpBây giờ, trong
source optapy-env/bin/activate
3, hãy thêm đoạn mã sau để tạo lớp python3 -m pip install optapy
0@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_id
def get_id[self]:
return self.id
def __str__[self]:
return [
f"Timeslot["
f"id={self.id}, "
f"day_of_week={self.day_of_week}, "
f"start_time={self.start_time}, "
f"end_time={self.end_time}]"
]
Thực thể lập kế hoạch
Các thực thể lập kế hoạch thay đổi trong suốt quá trình giải quyết. Bài học là một thực thể lập kế hoạch, vì các thuộc tính
python3 -m pip install optapy
1 và python3 -m pip install optapy
2 của nó thay đổi trong suốt quá trình giải. Vì các thuộc tính python3 -m pip install optapy
1 và python3 -m pip install optapy
2 thay đổi trong suốt quá trình giải nên chúng được gọi là các biến lập kế hoạch. Hãy thêm đoạn mã sau vào source optapy-env/bin/activate
3 để tạo lớp python3 -m pip install optapy
6from optapy import planning_entity, 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, ["timeslotRange"]]
def get_timeslot[self]:
return self.timeslot
def set_timeslot[self, new_timeslot]:
self.timeslot = new_timeslot
@planning_variable[Room, ["roomRange"]]
def get_room[self]:
return self.room
def set_room[self, new_room]:
self.room = new_room
def __str__[self]:
return [
f"Lesson["
f"id={self.id}, "
f"timeslot={self.timeslot}, "
f"room={self.room}, "
f"teacher={self.teacher}, "
f"subject={self.subject}, "
f"student_group={self.student_group}"
f"]"
]
Trình trang trí
python3 -m pip install optapy
7 đăng ký lớp dưới dạng một thực thể lập kế hoạch, cho phép OptaPlanner gán các biến lập kế hoạch của nó và để nó được sử dụng trong các ràng buộc. Trình trang trí python3 -m pip install optapy
8 đăng ký một phương thức làm phương thức nhận của một biến lập kế hoạch. Getter phải được đặt tên là python3 -m pip install optapy
9 và setter phải được đặt tên là from optapy import problem_fact, planning_id
@problem_fact
class Room:
def __init__[self, id, name]:
self.id = id
self.name = name
@planning_id
def get_id[self]:
return self.id
def __str__[self]:
return f"Room[id={self.id}, name={self.name}]"
0. Đối số đầu tiên, from optapy import problem_fact, planning_id
@problem_fact
class Room:
def __init__[self, id, name]:
self.id = id
self.name = name
@planning_id
def get_id[self]:
return self.id
def __str__[self]:
return f"Room[id={self.id}, name={self.name}]"
1, cho OptaPlanner biết loại giá trị mà OptaPlanner có thể gán cho biến lập kế hoạch này. Đối số thứ hai, from optapy import problem_fact, planning_id
@problem_fact
class Room:
def __init__[self, id, name]:
self.id = id
self.name = name
@planning_id
def get_id[self]:
return self.id
def __str__[self]:
return f"Room[id={self.id}, name={self.name}]"
2, cho OptaPlanner biết phạm vi giá trị mà nó lấy giá trị từ. Chúng tôi sẽ giải thích phạm vi giá trị sau trong ví dụ nàyHạn chế
Các ràng buộc xác định phép tính điểm hoặc hàm thích nghi của một bài toán lập kế hoạch. Mỗi lời giải của bài toán quy hoạch được chấm điểm. Điểm thể hiện chất lượng của một giải pháp cụ thể. Điểm càng cao càng tốt. OptaPlanner tìm kiếm giải pháp tốt nhất, là giải pháp có số điểm cao nhất được tìm thấy trong thời gian khả dụng. Nó có thể hoặc không thể là giải pháp tối ưu
Vì trường hợp sử dụng này có các ràng buộc cứng và mềm, hãy sử dụng lớp HardSoftScore để biểu diễn điểm số
Các ràng buộc cứng không được phá vỡ. Ví dụ. Một phòng có thể có nhiều nhất một bài học cùng một lúc
Các ràng buộc mềm không nên bị phá vỡ. Ví dụ. Một giáo viên thích dạy trong một phòng đơn
Các ràng buộc cứng được tính trọng số so với các ràng buộc cứng khác. Các ràng buộc mềm cũng có trọng số, so với các ràng buộc mềm khác. Các ràng buộc cứng luôn lớn hơn các ràng buộc mềm, bất kể trọng số tương ứng của chúng
Để tính điểm, hãy tạo hàm cung cấp ràng buộc trong tệp
from optapy import problem_fact, planning_id
@problem_fact
class Room:
def __init__[self, id, name]:
self.id = id
self.name = name
@planning_id
def get_id[self]:
return self.id
def __str__[self]:
return f"Room[id={self.id}, name={self.name}]"
3from domain import Lesson, Room
from optapy import constraint_provider, get_class
from optapy.constraint import Joiners
from optapy.score import HardSoftScore
# Constraint Factory takes Java Classes, not Python Classes
LessonClass = get_class[Lesson]
RoomClass = get_class[Room]
@constraint_provider
def define_constraints[constraint_factory]:
return [
# Hard constraints
room_conflict[constraint_factory],
teacher_conflict[constraint_factory],
student_group_conflict[constraint_factory],
# Soft constraints are only implemented in the optapy-quickstarts code
]
def room_conflict[constraint_factory]:
# A room can accommodate at most one lesson at the same time.
return constraint_factory \
.forEach[LessonClass] \
.join[LessonClass,
[
# .. in the same timeslot ...
Joiners.equal[lambda lesson: lesson.timeslot],
# .. in the same room ...
Joiners.equal[lambda lesson: lesson.room],
# .. and the pair is unique [different id, no reverse pairs] ...
Joiners.lessThan[lambda lesson: lesson.id]
]] \
.penalize["Room conflict", HardSoftScore.ONE_HARD]
def teacher_conflict[constraint_factory]:
# A teacher can teach at most one lesson at the same time.
return constraint_factory \
.forEach[LessonClass]\
.join[LessonClass,
[
Joiners.equal[lambda lesson: lesson.timeslot],
Joiners.equal[lambda lesson: lesson.teacher],
Joiners.lessThan[lambda lesson: lesson.id]
]] \
.penalize["Teacher conflict", HardSoftScore.ONE_HARD]
def student_group_conflict[constraint_factory]:
# A student can attend at most one lesson at the same time.
return constraint_factory \
.forEach[LessonClass] \
.join[LessonClass,
[
Joiners.equal[lambda lesson: lesson.timeslot],
Joiners.equal[lambda lesson: lesson.student_group],
Joiners.lessThan[lambda lesson: lesson.id]
]] \
.penalize["Student group conflict", HardSoftScore.ONE_HARD]
Trình trang trí
from optapy import problem_fact, planning_id
@problem_fact
class Room:
def __init__[self, id, name]:
self.id = id
self.name = name
@planning_id
def get_id[self]:
return self.id
def __str__[self]:
return f"Room[id={self.id}, name={self.name}]"
4 cho phép OptaPlanner sử dụng một chức năng làm trình cung cấp ràng buộc. Hàm phải nhận chính xác một đối số; . Để biết thêm thông tin, hãy xem trong tài liệu OptaPlannerTập hợp các đối tượng miền trong một giải pháp lập kế hoạch
Một lớp TimeTable bao bọc tất cả các phiên bản Khe thời gian, Phòng và Bài học của một tập dữ liệu. Hơn nữa, vì nó chứa tất cả các bài học, mỗi bài học có một trạng thái biến lập kế hoạch cụ thể nên lớp TimeTable là một giải pháp lập kế hoạch và có điểm số
Nếu các bài học vẫn chưa được gán, thì đó là một giải pháp chưa được khởi tạo, ví dụ: một giải pháp có điểm -4init/0hard/0soft
Nếu nó phá vỡ các ràng buộc cứng, thì đó là một giải pháp không khả thi, ví dụ, một giải pháp có điểm -2hard/-3soft
Nếu nó tuân thủ tất cả các ràng buộc cứng, thì đó là một giải pháp khả thi, ví dụ: một giải pháp có điểm số 0hard/-7soft
Trong
source optapy-env/bin/activate
3, hãy thêm đoạn mã sau để tạo lớp from optapy import problem_fact, planning_id
@problem_fact
class Room:
def __init__[self, id, name]:
self.id = id
self.name = name
@planning_id
def get_id[self]:
return self.id
def __str__[self]:
return f"Room[id={self.id}, name={self.name}]"
7from optapy import planning_solution, planning_entity_collection_property, \
problem_fact_collection_property, \
value_range_provider, planning_score
from optapy.score import HardSoftScore
def format_list[a_list]:
return ',\n'.join[map[str, a_list]]
@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["timeslotRange"]
def get_timeslot_list[self]:
return self.timeslot_list
@problem_fact_collection_property[Room]
@value_range_provider["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
def __str__[self]:
return [
f"TimeTable["
f"timeslot_list={format_list[self.timeslot_list]},\n"
f"room_list={format_list[self.room_list]},\n"
f"lesson_list={format_list[self.lesson_list]},\n"
f"score={str[self.score.toString[]] if self.score is not None else 'None'}"
f"]"
]
Trình trang trí
from optapy import problem_fact, planning_id
@problem_fact
class Room:
def __init__[self, id, name]:
self.id = id
self.name = name
@planning_id
def get_id[self]:
return self.id
def __str__[self]:
return f"Room[id={self.id}, name={self.name}]"
8 nói với OptaPlanner rằng lớp from optapy import problem_fact, planning_id
@problem_fact
class Room:
def __init__[self, id, name]:
self.id = id
self.name = name
@planning_id
def get_id[self]:
return self.id
def __str__[self]:
return f"Room[id={self.id}, name={self.name}]"
7 chứa dữ liệu đầu vào và đầu ra. Trình trang trí @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_id
def get_id[self]:
return self.id
def __str__[self]:
return [
f"Timeslot["
f"id={self.id}, "
f"day_of_week={self.day_of_week}, "
f"start_time={self.start_time}, "
f"end_time={self.end_time}]"
]
0 cho OptaPlanner biết chức năng cung cấp thông tin về vấn đề. Đối số @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_id
def get_id[self]:
return self.id
def __str__[self]:
return [
f"Timeslot["
f"id={self.id}, "
f"day_of_week={self.day_of_week}, "
f"start_time={self.start_time}, "
f"end_time={self.end_time}]"
]
1 cho OptaPlanner biết loại dữ kiện mà nó cung cấp [ví dụ: Phòng]Trình trang trí
@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_id
def get_id[self]:
return self.id
def __str__[self]:
return [
f"Timeslot["
f"id={self.id}, "
f"day_of_week={self.day_of_week}, "
f"start_time={self.start_time}, "
f"end_time={self.end_time}]"
]
2 cho OptaPlanner biết hàm cung cấp một phạm vi giá trị, được sử dụng để nhận các giá trị có thể có của các biến lập kế hoạch. Đối số của nó, @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_id
def get_id[self]:
return self.id
def __str__[self]:
return [
f"Timeslot["
f"id={self.id}, "
f"day_of_week={self.day_of_week}, "
f"start_time={self.start_time}, "
f"end_time={self.end_time}]"
]
3 là một chuỗi được sử dụng trong trang trí @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_id
def get_id[self]:
return self.id
def __str__[self]:
return [
f"Timeslot["
f"id={self.id}, "
f"day_of_week={self.day_of_week}, "
f"start_time={self.start_time}, "
f"end_time={self.end_time}]"
]
4 để liên kết cả hai [ví dụ: @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_id
def get_id[self]:
return self.id
def __str__[self]:
return [
f"Timeslot["
f"id={self.id}, "
f"day_of_week={self.day_of_week}, "
f"start_time={self.start_time}, "
f"end_time={self.end_time}]"
]
5 được liên kết với @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_id
def get_id[self]:
return self.id
def __str__[self]:
return [
f"Timeslot["
f"id={self.id}, "
f"day_of_week={self.day_of_week}, "
f"start_time={self.start_time}, "
f"end_time={self.end_time}]"
]
6Trình trang trí
@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_id
def get_id[self]:
return self.id
def __str__[self]:
return [
f"Timeslot["
f"id={self.id}, "
f"day_of_week={self.day_of_week}, "
f"start_time={self.start_time}, "
f"end_time={self.end_time}]"
]
7 cho OptaPlanner biết chức năng cung cấp các thực thể lập kế hoạch. Đối số @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_id
def get_id[self]:
return self.id
def __str__[self]:
return [
f"Timeslot["
f"id={self.id}, "
f"day_of_week={self.day_of_week}, "
f"start_time={self.start_time}, "
f"end_time={self.end_time}]"
]
8 cho OptaPlanner biết loại thực thể mà nó cung cấp [ví dụ: Bài học]Trình trang trí
@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_id
def get_id[self]:
return self.id
def __str__[self]:
return [
f"Timeslot["
f"id={self.id}, "
f"day_of_week={self.day_of_week}, "
f"start_time={self.start_time}, "
f"end_time={self.end_time}]"
]
9 cho OptaPlanner biết hàm trả về điểm số. Nó phải được đặt tên là python3 -m pip install optapy
9 và có một setter tương ứng là from optapy import problem_fact, planning_id
@problem_fact
class Room:
def __init__[self, id, name]:
self.id = id
self.name = name
@planning_id
def get_id[self]:
return self.id
def __str__[self]:
return f"Room[id={self.id}, name={self.name}]"
0. Đối số from optapy import planning_entity, 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, ["timeslotRange"]]
def get_timeslot[self]:
return self.timeslot
def set_timeslot[self, new_timeslot]:
self.timeslot = new_timeslot
@planning_variable[Room, ["roomRange"]]
def get_room[self]:
return self.room
def set_room[self, new_room]:
self.room = new_room
def __str__[self]:
return [
f"Lesson["
f"id={self.id}, "
f"timeslot={self.timeslot}, "
f"room={self.room}, "
f"teacher={self.teacher}, "
f"subject={self.subject}, "
f"student_group={self.student_group}"
f"]"
]
2 cho OptaPlanner biết loại điểm sẽ sử dụng [ví dụ: from optapy import planning_entity, 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, ["timeslotRange"]]
def get_timeslot[self]:
return self.timeslot
def set_timeslot[self, new_timeslot]:
self.timeslot = new_timeslot
@planning_variable[Room, ["roomRange"]]
def get_room[self]:
return self.room
def set_room[self, new_room]:
self.room = new_room
def __str__[self]:
return [
f"Lesson["
f"id={self.id}, "
f"timeslot={self.timeslot}, "
f"room={self.room}, "
f"teacher={self.teacher}, "
f"subject={self.subject}, "
f"student_group={self.student_group}"
f"]"
]
3]. Loại nên được lấy từ mô-đun from optapy import planning_entity, 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, ["timeslotRange"]]
def get_timeslot[self]:
return self.timeslot
def set_timeslot[self, new_timeslot]:
self.timeslot = new_timeslot
@planning_variable[Room, ["roomRange"]]
def get_room[self]:
return self.room
def set_room[self, new_room]:
self.room = new_room
def __str__[self]:
return [
f"Lesson["
f"id={self.id}, "
f"timeslot={self.timeslot}, "
f"room={self.room}, "
f"teacher={self.teacher}, "
f"subject={self.subject}, "
f"student_group={self.student_group}"
f"]"
]
4giải quyết
Để giải quyết, trước tiên chúng ta cần tạo một thể hiện của vấn đề. Thêm đoạn mã sau vào
source optapy-env/bin/activate
3from datetime import time
def generate_problem[]:
timeslot_list = [
Timeslot[1, "MONDAY", time[hour=8, minute=30], time[hour=9, minute=30]],
Timeslot[2, "MONDAY", time[hour=9, minute=30], time[hour=10, minute=30]],
Timeslot[3, "MONDAY", time[hour=10, minute=30], time[hour=11, minute=30]],
Timeslot[4, "MONDAY", time[hour=13, minute=30], time[hour=14, minute=30]],
Timeslot[5, "MONDAY", time[hour=14, minute=30], time[hour=15, minute=30]],
Timeslot[6, "TUESDAY", time[hour=8, minute=30], time[hour=9, minute=30]],
Timeslot[7, "TUESDAY", time[hour=9, minute=30], time[hour=10, minute=30]],
Timeslot[8, "TUESDAY", time[hour=10, minute=30], time[hour=11, minute=30]],
Timeslot[9, "TUESDAY", time[hour=13, minute=30], time[hour=14, minute=30]],
Timeslot[10, "TUESDAY", time[hour=14, minute=30], time[hour=15, minute=30]],
]
room_list = [
Room[1, "Room A"],
Room[2, "Room B"],
Room[3, "Room C"]
]
lesson_list = [
Lesson[1, "Math", "A. Turing", "9th grade"],
Lesson[2, "Math", "A. Turing", "9th grade"],
Lesson[3, "Physics", "M. Curie", "9th grade"],
Lesson[4, "Chemistry", "M. Curie", "9th grade"],
Lesson[5, "Biology", "C. Darwin", "9th grade"],
Lesson[6, "History", "I. Jones", "9th grade"],
Lesson[7, "English", "I. Jones", "9th grade"],
Lesson[8, "English", "I. Jones", "9th grade"],
Lesson[9, "Spanish", "P. Cruz", "9th grade"],
Lesson[10, "Spanish", "P. Cruz", "9th grade"],
Lesson[11, "Math", "A. Turing", "10th grade"],
Lesson[12, "Math", "A. Turing", "10th grade"],
Lesson[13, "Math", "A. Turing", "10th grade"],
Lesson[14, "Physics", "M. Curie", "10th grade"],
Lesson[15, "Chemistry", "M. Curie", "10th grade"],
Lesson[16, "French", "M. Curie", "10th grade"],
Lesson[17, "Geography", "C. Darwin", "10th grade"],
Lesson[18, "History", "I. Jones", "10th grade"],
Lesson[19, "English", "P. Cruz", "10th grade"],
Lesson[20, "Spanish", "P. Cruz", "10th grade"],
]
lesson = lesson_list[0]
lesson.set_timeslot[timeslot_list[0]]
lesson.set_room[room_list[0]]
return TimeTable[timeslot_list, room_list, lesson_list]
Tiếp theo, chúng ta cần tạo một
from optapy import planning_entity, 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, ["timeslotRange"]]
def get_timeslot[self]:
return self.timeslot
def set_timeslot[self, new_timeslot]:
self.timeslot = new_timeslot
@planning_variable[Room, ["roomRange"]]
def get_room[self]:
return self.room
def set_room[self, new_room]:
self.room = new_room
def __str__[self]:
return [
f"Lesson["
f"id={self.id}, "
f"timeslot={self.timeslot}, "
f"room={self.room}, "
f"teacher={self.teacher}, "
f"subject={self.subject}, "
f"student_group={self.student_group}"
f"]"
]
6, cho OptaPlanner biết về vấn đề và các chiến lược sẽ sử dụng. Trong from optapy import planning_entity, 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, ["timeslotRange"]]
def get_timeslot[self]:
return self.timeslot
def set_timeslot[self, new_timeslot]:
self.timeslot = new_timeslot
@planning_variable[Room, ["roomRange"]]
def get_room[self]:
return self.room
def set_room[self, new_room]:
self.room = new_room
def __str__[self]:
return [
f"Lesson["
f"id={self.id}, "
f"timeslot={self.timeslot}, "
f"room={self.room}, "
f"teacher={self.teacher}, "
f"subject={self.subject}, "
f"student_group={self.student_group}"
f"]"
]
7, thêm đoạn mã saufrom domain import Lesson, TimeTable, generate_problem
from constraints import define_constraints
from optapy import get_class
import optapy.config
from optapy.types import Duration
solver_config = optapy.config.solver.SolverConfig[] \
.withEntityClasses[get_class[Lesson]] \
.withSolutionClass[get_class[TimeTable]] \
.withConstraintProviderClass[get_class[define_constraints]] \
.withTerminationSpentLimit[Duration.ofSeconds[30]]
Đối với
from optapy import planning_entity, 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, ["timeslotRange"]]
def get_timeslot[self]:
return self.timeslot
def set_timeslot[self, new_timeslot]:
self.timeslot = new_timeslot
@planning_variable[Room, ["roomRange"]]
def get_room[self]:
return self.room
def set_room[self, new_room]:
self.room = new_room
def __str__[self]:
return [
f"Lesson["
f"id={self.id}, "
f"timeslot={self.timeslot}, "
f"room={self.room}, "
f"teacher={self.teacher}, "
f"subject={self.subject}, "
f"student_group={self.student_group}"
f"]"
]
6 ở trên, chúng tôi sử dụng các chiến lược mặc định, sử dụng mô hình mà chúng tôi đã xác định ở trên và đặt nó kết thúc sau 30 giâyCuối cùng, chúng tôi chuyển
from optapy import planning_entity, 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, ["timeslotRange"]]
def get_timeslot[self]:
return self.timeslot
def set_timeslot[self, new_timeslot]:
self.timeslot = new_timeslot
@planning_variable[Room, ["roomRange"]]
def get_room[self]:
return self.room
def set_room[self, new_room]:
self.room = new_room
def __str__[self]:
return [
f"Lesson["
f"id={self.id}, "
f"timeslot={self.timeslot}, "
f"room={self.room}, "
f"teacher={self.teacher}, "
f"subject={self.subject}, "
f"student_group={self.student_group}"
f"]"
]
6 và trường hợp vấn đề cho hàm from domain import Lesson, Room
from optapy import constraint_provider, get_class
from optapy.constraint import Joiners
from optapy.score import HardSoftScore
# Constraint Factory takes Java Classes, not Python Classes
LessonClass = get_class[Lesson]
RoomClass = get_class[Room]
@constraint_provider
def define_constraints[constraint_factory]:
return [
# Hard constraints
room_conflict[constraint_factory],
teacher_conflict[constraint_factory],
student_group_conflict[constraint_factory],
# Soft constraints are only implemented in the optapy-quickstarts code
]
def room_conflict[constraint_factory]:
# A room can accommodate at most one lesson at the same time.
return constraint_factory \
.forEach[LessonClass] \
.join[LessonClass,
[
# .. in the same timeslot ...
Joiners.equal[lambda lesson: lesson.timeslot],
# .. in the same room ...
Joiners.equal[lambda lesson: lesson.room],
# .. and the pair is unique [different id, no reverse pairs] ...
Joiners.lessThan[lambda lesson: lesson.id]
]] \
.penalize["Room conflict", HardSoftScore.ONE_HARD]
def teacher_conflict[constraint_factory]:
# A teacher can teach at most one lesson at the same time.
return constraint_factory \
.forEach[LessonClass]\
.join[LessonClass,
[
Joiners.equal[lambda lesson: lesson.timeslot],
Joiners.equal[lambda lesson: lesson.teacher],
Joiners.lessThan[lambda lesson: lesson.id]
]] \
.penalize["Teacher conflict", HardSoftScore.ONE_HARD]
def student_group_conflict[constraint_factory]:
# A student can attend at most one lesson at the same time.
return constraint_factory \
.forEach[LessonClass] \
.join[LessonClass,
[
Joiners.equal[lambda lesson: lesson.timeslot],
Joiners.equal[lambda lesson: lesson.student_group],
Joiners.lessThan[lambda lesson: lesson.id]
]] \
.penalize["Student group conflict", HardSoftScore.ONE_HARD]
0, hàm này trả về giải pháp tốt nhất cuối cùng được tìm thấy. Thêm đoạn mã sau vào from optapy import planning_entity, 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, ["timeslotRange"]]
def get_timeslot[self]:
return self.timeslot
def set_timeslot[self, new_timeslot]:
self.timeslot = new_timeslot
@planning_variable[Room, ["roomRange"]]
def get_room[self]:
return self.room
def set_room[self, new_room]:
self.room = new_room
def __str__[self]:
return [
f"Lesson["
f"id={self.id}, "
f"timeslot={self.timeslot}, "
f"room={self.room}, "
f"teacher={self.teacher}, "
f"subject={self.subject}, "
f"student_group={self.student_group}"
f"]"
]
7source optapy-env/bin/activate
0Giải pháp được trả về là một trường hợp
from optapy import problem_fact, planning_id
@problem_fact
class Room:
def __init__[self, id, name]:
self.id = id
self.name = name
@planning_id
def get_id[self]:
return self.id
def __str__[self]:
return f"Room[id={self.id}, name={self.name}]"
7 của giải pháp tốt nhất được tìm thấy. Khi giải pháp được định dạng thành một bảng, nó sẽ trông giống như thế nàysource optapy-env/bin/activate
1Chạy ứng dụng
Để chạy ứng dụng, hãy thực thi tệp chính
source optapy-env/bin/activate
2Phần kết luận
Với OptaPy, các nhà phát triển Python hiện có thể sử dụng OptaPlanner bằng mã Python đơn giản [không cần mã Java]. Ví dụ đầy đủ có thể được tìm thấy trong khởi động nhanh OptaPy