하나의 제약이없는 제약 만족 문제


13

저는 작년 학생의 의견을 바탕으로 대학교의 실험실 실습 교사이며, 우리의 상사와 저는 그 문제를 해결하기를 원했습니다. 상사는 C 스크립트 작성을 선택했고 문제를 해결하기 위해 python (python-constraint)을 선택했습니다.

정보

  • 6 개의 세션이 있습니다
  • 4 가지 역할이 있습니다
  • 6 가지 사례가 있습니다
  • 32 명의 학생이 있습니다
  • 팀당 4 명의 학생이 있습니다

문제 :

4 가지 다른 세션에서 4 가지 실습에서 각 학생을 4 가지 역할에 배정하십시오.

제약 사항 :

  1. 학생은 한 번 역할을 수행해야합니다
  2. 학생들은 6 가지 중 4 가지의 다른 관행을 수행해야합니다
  3. 학생들은 한 세션 당 하나의 연습 만해야합니다
  4. 학생은 같은 친구를 한 번만 만나야합니다

템플릿 :

여기 각 팀이 4 명의 학생으로 구성되어 있고 학생들에게 [0, 1, 2 또는 3] 직책이 그들에게 할당 된 역할이 있습니다. 사용 가능한 각 위치는 1에서 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]]]

다시 말해 :

이 세션입니다 :

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

그 팀도 같은 연습을합니다 :

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

그 위치는 같은 역할을합니다.

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

내가 지금까지 무엇을 :

python-constraint를 사용 하여 처음 세 가지 제약 조건을 확인할 수있었습니다.

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]

흥미로운 사람들을 위해 나는 단순히 다음과 같이합니다 :

각 조건에 대해 AllDifferentConstraint 사용 합니다. 예를 들어 한 세션에 대해 다음을 수행합니다.

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])

팀을 구속하는 방법을 찾을 수 없습니다. 전체에 대한 마지막 시도 semester는 다음과 같습니다.

    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

질문 :

  1. 팀 조건에 대해 내가 원하는 것을 할 수 있습니까? 내 말은 각 학생에게 12 명의 친구를 배정 할 수 있는지 그리고 그들 각자가 같은 친구를 한 번만 만나는 지 모른다는 것입니다.
  2. 팀 제약 조건에 대해 더 성능이 뛰어난 알고리즘을 놓쳤습니까?
  3. 내가 따를 수있는 주먹?

1
마지막 두 세션 집합이 다른 세션 (4, 4)대신 모양이되는 이유는 무엇 (4, 6)입니까?
r.ook December

이 과정은 한 학점에 불과하고 많은 직업이 필요하다는 사실과 일치하기 때문에 상사는 학생이 4 가지 연습 만 수행해야한다고 생각합니다. 그래서 우리는 이것을 32 명의 학생으로 구성했고, 4 명의 연습을해야합니다 (128 명).
플로리안 버나드

1
무작위 및 무차별 대입 방식을 시도합니다. 세션 1을 선택하는 순열처럼 역할 1 학생 1 연습 1 ... 2에서 4까지 동일합니다. 그런 다음 6 개의 세션마다 증분하고 이미 만난 학생을 버립니다. 무작위와 동일합니다. 왜 각기 다른 순열에서 최대 32 명의 학생 32 명을 세션 당 128 명의 포지션으로 사용하지 않습니까? 아마 stackMath에서 이것이 가능한 조합 / 치환인지 여부를 알려줄 수 있습니다
Cristo

현재는 무차별 대입법이 효과가 있었지만 제 상사는 대본과 작업을 잘 해주었습니다. 하지만 여전히 파이썬을 사용하고 싶지 않습니다.
Florian Bernard

답변:


2

주요 질문은 ...

   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)) 

편집 추가

어제 당신의 문제를 다시 한 번 보았습니다. (현재 많은 일을하고 있기 때문에 그리 오래 걸리지 않았습니다.)

우선, 나는 당신의 '팀'실체가 내가 '행동'실체라고 부르는 것과 매우 비슷하다는 것을 알고 있으며, '팀'(또는 '그룹')이 더 나은 단어라고 생각합니다.

그래도 제약 조건을 찾기 힘들다면, 팀 / 개인 / 세션 제약 조건과 그에 따른 역할 / 작업 제약 조건을 따로 따로 따로 해결하는 것이 좋습니다.

/ 추가 편집

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

나는 최근에 비슷한 문제가 있었고 결국 OR 도구를 사용했습니다. https://developers.google.com/optimization/cp/cp_solver

특히 간호사 예약 문제 ( https://developers.google.com/optimization/scheduling/employee_scheduling#nurse_scheduling)를 살펴보십시오.

어쨌든, 문제는 너무 복잡하지 않으므로 솔버를 사용하는 것이 과도 할 수 있습니다.

마찬가지로, 이런 종류의 문제에 대해서는 튜플 키 방식을 사용하여 중첩 목록이 아닌 변수를 보유하는 것이 좋습니다.

{팀, 세션, 사람 : BoolVar}

주된 이유는 필터를 통해 제약 조건을 적용 할 수 있기 때문입니다. 예를 들어 개인 / 팀 전체에 제약 조건을 적용하는 등 중첩 목록 조작을 수행하는 것보다 훨씬 쉽습니다. 개인이 색인 2이고 팀이 색인 인 경우 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
고마워요, for 루프를 의미 p for p in all_people합니까?
Florian Bernard

1
그래, 미안해 나는 당신의 모델로 내 이름을 '번역'했지만 직장에 있었기 때문에 조금 빨랐습니다.
Konchog

1
또한 메일 링리스트는 OR-tools에서 실제로 도움이됩니다. 문제 모델링에 도움이 필요하면 예제 코드를 가리 키거나 그룹 / 종속성 제약 조건을 설정하는 방법에 대한 훌륭한 아이디어를 제공합니다.
Konchog

죄송하지만 헤드 솔루션을 찾기가 어렵습니다. 그리고 P, S 및 G 변수는 무엇입니까? pv 란 무엇입니까? 당신의 도움을 주셔서 감사합니다.
Florian Bernard

0

각 반복에 대한 순열 알고리즘 아이디어는 각 학생 중 하나 또는 각 세션 중 하나에 초점을 맞출 수 있습니다.

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

여기서 학생 2는 세션 1에서 학생 1을 대신하여 다음과 같이 진행합니다.

Roles 1234
St 2,5,6,7 

학생 1과 계속하십시오 S3 R 1234 St 10,9,1,8

S4
R 1234
St 11,12,13,1

결국 다음 반복에 대한 순열과 같이 학생 1에 대한 상호 작용을 제거하고 현재를 제거합니다.

루빅스 큐브와 같습니다.

이 코드를 작성 하거나이 알고리즘으로 코드를 알고 있다면 알려주십시오.

아마도 itertools로 순열

내가 믿는 관행보다> 세션은 그 숫자와 관련이 없습니다. 회전 할 공간이 부족하거나 더 많은 공간이 필요할 때 더 많은 수영장이 있습니다. 어쩌면 4 세션 = 연습을 목표로 문제를 단순화 할 수 있습니까?

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.