vấn đề thỏa mãn ràng buộc thiếu một ràng buộc


13

Tôi là một gia sư thực hành tại phòng thí nghiệm tại trường đại học, dựa trên những nhận xét của sinh viên năm ngoái, chúng tôi muốn, ông chủ của tôi và tôi, giải quyết chúng. Sếp của tôi đã chọn viết kịch bản C và tôi chọn python (python-ràng buộc) để cố gắng giải quyết vấn đề của chúng tôi.

Thông tin

  • Có 6 buổi
  • Có 4 vai trò
  • Có 6 thực hành
  • Có 32 học sinh
  • Có 4 học sinh mỗi đội

Vấn đề :

Chỉ định mỗi học sinh với 4 vai trò, trong 4 thực hành trong 4 phiên khác nhau.

Các ràng buộc:

  1. Học sinh nên làm một lần
  2. Học sinh nên làm 4 thực hành khác nhau trong số 6
  3. Học sinh chỉ nên thực hành một lần mỗi buổi
  4. Học sinh chỉ nên gặp cùng một người bạn đời một lần

Mẫu:

Đây là mẫu mà tôi cảm thấy với các sinh viên, trong đó mỗi đội gồm 4 sinh viên, các vị trí [0, 1, 2 hoặc 3] là các vai trò được giao cho họ. Mỗi vị trí khả dụng được đánh số từ 1 đến 128

[# Semester
   [ # Session
     [ # Practice/Team
1, 2, 3, 4],
  [5, 6, 7, 8],
  [9, 10, 11, 12],
  [13, 14, 15, 16],
  [17, 18, 19, 20],
  [21, 22, 23, 24]],
 [[25, 26, 27, 28],
  [29, 30, 31, 32],
  [33, 34, 35, 36],
  [37, 38, 39, 40],
  [41, 42, 43, 44],
  [45, 46, 47, 48]],
 [[49, 50, 51, 52],
  [53, 54, 55, 56],
  [57, 58, 59, 60],
  [61, 62, 63, 64],
  [65, 66, 67, 68],
  [69, 70, 71, 72]],
 [[73, 74, 75, 76],
  [77, 78, 79, 80],
  [81, 82, 83, 84],
  [85, 86, 87, 88],
  [89, 90, 91, 92],
  [93, 94, 95, 96]],
 [[97, 98, 99, 100],
  [101, 102, 103, 104],
  [105, 106, 107, 108],
  [109, 110, 111, 112]],
 [[113, 114, 115, 116],
  [117, 118, 119, 120],
  [121, 122, 123, 124],
  [125, 126, 127, 128]]]

Nói cách khác :

Đây là một phiên:

 [[1, 2, 3, 4],
  [5, 6, 7, 8],
  [9, 10, 11, 12],
  [13, 14, 15, 16],
  [17, 18, 19, 20],
  [21, 22, 23, 24]],

Những đội đó thực hiện cùng một thực hành:

[
    [1, 2, 3, 4],
    [25, 26, 27, 28],
    [49, 50, 51, 52],
    [73, 74, 75, 76],
    [97, 98, 99, 100],
    [113, 114, 115, 116]
]

Những vị trí đó làm cùng một vai trò:

[
   1,
   5,
   9,
   13,
   17,
   21,
   25,
   ...
]

Những gì tôi có cho đến nay:

Sử dụng python-ràng buộc tôi có thể xác nhận ba ràng buộc đầu tiên:

Valid solution : False
            - sessions  : [True, True, True, True, True, True]
            - practices : [True, True, True, True, True, True]
            - roles     : [True, True, True, True]
            - teams     : [False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False]

Đối với những người có thể thú vị, tôi chỉ đơn giản là làm như thế này:

Đối với mỗi điều kiện tôi sử dụng AllDifferentConstraint . Ví dụ: trong một phiên tôi làm:

problem.addConstraint(AllDifferentConstraint(), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24])

Tôi không thể tìm cách ràng buộc đội, nỗ lực cuối cùng của tôi trên toàn bộ semesterlà:

    def team_constraint(self, *semester):
        students = defaultdict(list)

        # get back each teams based on the format [# Semester [ #Session [# Practice/Team ... 
        teams = [list(semester[i:i+4]) for i in range(0, len(semester), 4)]

        # Update Students dict with all mate they work with
        for team in teams:
            for student in team:
                students[student] += [s for s in team if s != student]

        # Compute for each student if they meet someone more than once 
        dupli = []
        for student, mate in students.items():
            dupli.append(len(mate) - len(set(mate)))

        # Loosly constraint, if a student meet somone 0 or one time it's find
        if max(dupli) >= 2:
            print("Mate encounter more than one time", dupli, min(dupli) ,max(dupli))
            return False
        pprint(students)
        return True

Câu hỏi:

  1. Có thể làm những gì tôi muốn cho các điều kiện đội? Ý tôi là tôi không biết liệu có thể chỉ định 12 người bạn cho mỗi sinh viên và mỗi người chỉ gặp một người bạn đời giống nhau một lần.
  2. Đối với các ràng buộc nhóm, tôi đã bỏ lỡ một thuật toán hiệu suất hơn?
  3. Bất kỳ pist mà tôi có thể làm theo?

1
Tại sao hai bộ phiên cuối cùng có hình dạng (4, 4)thay vì (4, 6)giống như các phiên khác?
r.ook

Nó phù hợp với thực tế là khóa học này chỉ có một tín chỉ và đòi hỏi nhiều công việc, vì vậy ông chủ của tôi cho rằng sinh viên chỉ nên thực hiện 4 thực hành. Vì vậy, chúng tôi đã đưa ra điều này, chúng tôi có 32 sinh viên, cần thực hiện 4 thực hành (128 vị trí).
Florian Bernard

1
Tôi sẽ thử cách tiếp cận ngẫu nhiên và vũ phu. Chỉ cần thực hiện một hoán vị nơi bạn chọn Phần 1: Vai trò 1 Học sinh 1 Thực hành 1 ... tương tự với 2 đến 4. Sau đó tăng dần cho mỗi 6 phiên, loại bỏ các sinh viên đã gặp. Tương tự với ngẫu nhiên. Tại sao 128 vị trí và không sử dụng cho mỗi phiên 32 số sinh viên là tối đa trong các hoán vị khác nhau? Có lẽ trong stackMath họ có thể cho bạn biết nếu đây là sự kết hợp / hoán vị có thể
Cristo

Hiện tại phương pháp vũ phu hoạt động, ông chủ của tôi đã trở lại với tôi với kịch bản của nó và công việc của nó thực sự tốt. Nhưng tôi vẫn muốn sử dụng python.
Florian Bernard

Câu trả lời:


2

Câu hỏi chính sẽ được trả lời bằng một cái gì đó như ...

   def person_works_with_different():
        # over all the sessions, each person works with each other person no more than once.
        # 'works with' means in 'same session team'
        for p in all_people:
            buddy_constraint = []
            for s in all_sessions:
                for g in all_teams:
                    p_list = [pv[k] for k in filter(lambda i: i[P] == p and i[S] == s and i[G] == g, pv)]
                    for o in all_people:
                        if o != p:  # other is not person
                            o_list = [self.pv[k] for k in filter(lambda i: i[self.P] == o and i[self.S] == s and i[self.G] == g, self.pv)]
                            tmp = model.NewBoolVar('')
                            buddy_constraint.append(tmp)
                            model.Add(sum(o_list) == sum(p_list)).OnlyEnforceIf(tmp)
                            # tmp is set only if o and p are in the same session/team
            # The number of times a student gets to take part is the number of roles.
            # The size of the group controlled by the number of roles
            model.Add(sum(buddy_constraint) = all_roles * (all_roles - 1)) 

Đã thêm Chỉnh sửa

Tôi đã có một cái nhìn khác về vấn đề của bạn ngày hôm qua - (phải thừa nhận là không lâu, vì tôi có rất nhiều công việc vào lúc này), và ...

Trước hết, tôi thấy rằng thực thể 'nhóm' của bạn, gần như là cái mà tôi gọi là thực thể 'hành động' và khi nhìn lại tôi nghĩ 'nhóm' (hoặc 'nhóm') là một từ tốt hơn cho nó.

Nếu bạn vẫn thấy khó khăn trong các ràng buộc, tôi khuyên bạn nên loại bỏ chúng và làm việc riêng lẻ - đặc biệt là các ràng buộc nhóm / người / phiên, theo sau là các ràng buộc về vai trò / nhiệm vụ.

/ Đã thêm Chỉnh sửa

team: a gathering of 4 persons during a session
person (32): a participant of a team
session (6): time: eg, 8am -10am
role (4): what responsibility a person has in an action
task (6): type of action

A person does:
 0..1 action per session-group
 1 role per action
 1 task per action
 0..1 of each task
 1 of each role in an action
 4 persons in an action

A person meets each other person 0..1 times
An action requires exactly 4 people

Tôi đã có một vấn đề tương tự gần đây và cuối cùng đã chuyển sang công cụ OR. https://developers.google.com/optimization/cp/cp_solver

Đặc biệt, hãy xem xét vấn đề lập lịch trình của y tá: https://developers.google.com/optimization/schedcing/employee_scheduling#nurse_scheduling

Nhưng dù sao, vấn đề không quá phức tạp, vì vậy có lẽ việc sử dụng một bộ giải sẽ là quá mức cần thiết cho bạn.

Tương tự như vậy, đối với loại vấn đề này, có thể tốt hơn là sử dụng một lệnh chính được khóa bằng tuple để giữ các biến của bạn, thay vì các danh sách lồng nhau:

{Đội, Phiên, Người: BoolVar}

Lý do chính là sau đó bạn có thể áp dụng các ràng buộc thông qua các bộ lọc, điều này dễ hơn nhiều so với việc phải thực hiện các thao tác danh sách lồng nhau, ví dụ, để áp dụng một ràng buộc giữa các người / nhóm, bạn có thể làm (trong đó người là chỉ số 2 và nhóm là chỉ mục 0):

for p in all_persons:
    for t in all_teams:
        stuff = [b_vars[k] for k in filter(lambda i: i[2] == p and i[0] == t, b_vars)]
        model.Add(sum(stuff) == 4)  # persons per team == 4

1
Cảm ơn, vì ý nghĩa của vòng lặp for p for p in all_people?
Florian Bernard

1
Ừ, xin lỗi! Tôi đã "dịch" tên của tôi sang mô hình của bạn, nhưng tại nơi làm việc nên hơi nhanh.
Konchog

1
Ngoài ra, danh sách gửi thư thực sự hỗ trợ tại OR-tools. Nếu bạn cần trợ giúp với việc mô hình hóa vấn đề của mình, họ sẽ chỉ cho bạn ví dụ mã hoặc cung cấp cho bạn một ý tưởng tuyệt vời về cách đặt các ràng buộc nhóm / phụ thuộc
Konchog

Tôi xin lỗi nhưng giải pháp đầu của bạn là khó theo dõi, từ đâu đến từ bản thân? Và các biến P, S và G là gì? Pv là gì? Cảm ơn bạn đã giúp đỡ.
Florian Bernard

0

Chỉ là một ý tưởng thuật toán hoán vị, cho mỗi lần lặp có thể được tập trung vào một trong mỗi học sinh hoặc trong một trong mỗi phiên:

Session 1:
Roles
1,2,3,4
Students
1,2,3,4

(Note is 1st permutation 1234)

Sess 2 for student 1
Roles 1234
Students 5,1,7,6

Ở đây học sinh 2 diễn ra của học sinh 1 trong buổi 1 và tiếp tục như thế này

Roles 1234
St 2,5,6,7 

Tiếp tục với học sinh 1 S3 R 1234 St 10,9,1,8

S4
R 1234
St 11,12,13,1

Cuối cùng, bạn xóa các tương tác cho sinh viên 1, như hoán vị cho lần lặp tiếp theo mà bạn xóa hiện tại.

Nó giống như một khối rubiks.

Nếu bạn nhận được mã này hoặc biết một số mã với thuật toán này, hãy cho tôi biết.

Có lẽ với hoán vị itertools

Phiên làm việc> hơn thực tiễn tôi tin là không liên quan đến số lượng của nó. Chỉ cần một số hồ bơi để có thêm khi bạn chạy ra ngoài hoặc nhiều chỗ hơn cho vòng quay. Có lẽ có thể đơn giản hóa vấn đề đầu tiên nhắm đến 4 phiên = thực hành?

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.