kısıtlama memnuniyet sorunu bir kısıtlama eksik


13

Geçen yıl öğrenci yorumlarına dayanarak üniversitede laboratuar uygulamaları öğretmeniyim, patronum ve ben onlara hitap etmek istedik. Patronum bir C betiği yazmayı seçti ve sorunumuzu çözmeye çalışmak için python (python-kısıtlama) seçiyorum.

Bilgiler

  • 6 oturum var
  • 4 rol var
  • 6 uygulama var
  • 32 öğrenci var
  • Takım başına 4 öğrenci var.

Sorun :

Her öğrenciyi 4 farklı oturumda 4 uygulamada 4 role atayın.

Kısıtlamalar:

  1. Öğrenciler bir kez rol yapmalı
  2. Öğrenciler 6 üzerinden 4 farklı uygulama yapmalıdır
  3. Öğrenciler oturum başına sadece bir uygulama yapmalıdır
  4. Öğrenci aynı arkadaşı sadece bir kez karşılamalıdır

Şablonlar:

İşte her takımın 4 öğrenciden oluştuğu öğrencilerle birlikte hissettiğim şablon, [0, 1, 2 veya 3] pozisyonları kendilerine atanan roller. Her kullanılabilir konum 1'den 128'e kadar numaralandırılıyor

[# 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]]]

Başka bir deyişle :

Bu bir oturum:

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

Bu ekip aynı uygulamayı yapıyor:

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

Bu pozisyon aynı rolü üstlenir:

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

Şimdiye kadar ne var:

Python-kısıtlamasını kullanarak ilk üç kısıtlamayı doğrulayabildim:

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]

İlginç olanlar için ben sadece böyle yapmak:

Her koşul için AllDifferentConstraint kullanıyorum . Örneğin, bir oturum için:

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

Ekibi kısıtlamak için bir yol bulamıyorum, genel olarak son denemem semesterşuydu:

    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

Sorular:

  1. Takım şartları için istediğimi yapmak mümkün mü? Demek istediğim, her öğrenciye 12 eş atamanın mümkün olup olmadığı konusunda hiçbir fikrim yok ve her biri aynı arkadaşı sadece bir kez karşılar.
  2. Takım kısıtı için daha performanslı bir algoritmayı kaçırdım mı?
  3. Takip edebileceğim bir pist var mı?

1
Son iki seans neden diğerleri gibi (4, 4)değil (4, 6)?
r.ook

Bu dersin sadece bir kredi olduğu ve çok fazla iş gerektirdiği gerçeğiyle eşleşmelidir, bu yüzden patronum öğrencilerin sadece 4 uygulama yapmasını istiyor. Bu yüzden, 4 uygulama (128 pozisyon) yapması gereken 32 öğrencimiz var.
Florian Bernard

1
Rasgele ve kaba kuvvet yaklaşımını denerdim. Oturum 1: Rol 1 Öğrenci 1 Alıştırma 1 ... 2 ila 4 ile aynı olan bir permütasyon gibi yapın. Daha sonra her 6 oturum için artırın, zaten tanıştığınız öğrencileri atın. Rastgele ile aynı. Neden 128 pozisyon ve Oturum başına 32 öğrenci farklı izinlerde maksimum olarak kullanılmıyor? Belki stackMath'te bunun olası bir kombinasyon / permütasyon olup olmadığını söyleyebilirler
Cristo

Şu anda kaba kuvvet yöntemi çalışıyor, patronum senaryosu ve çalışmasıyla bana geri döndü. Ama yine de python kullanmak istemiyorum.
Florian Bernard

Yanıtlar:


2

Asıl soru şu şekilde cevaplanacaktı ...

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

Düzenleme Eklendi

Dün sorununa bir kez daha baktım - (kuşkusuz uzun süredir, şu anda üzerinde çok çalıştığım için) ve ...

Her şeyden önce, 'takım' varlığınızın hemen hemen 'eylem' varlığım olduğunu görüyorum ve geçmişe göre 'takım' (veya 'grup') bunun daha iyi bir kelime olduğunu düşünüyorum.

Hala kısıtlamaları zor buluyorsanız, bunları kırmanızı ve bireysel olarak çalışmanızı öneririm - özellikle ekip / kişi / oturum kısıtlamaları, ardından rol / görev kısıtlamaları.

/ Düzenleme Eklendi

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

Son zamanlarda benzer bir sorun yaşadım ve sonunda OR-araçlarına döndüm. https://developers.google.com/optimization/cp/cp_solver

Özellikle, hemşire planlama sorununa bir göz atın: https://developers.google.com/optimization/scheduling/employee_scheduling#nurse_scheduling

Her neyse, sorun çok karmaşık değil, bu yüzden belki bir çözücü kullanmak sizin için aşırıya kaçabilir.

Benzer şekilde, bu tür bir sorun için, iç içe listeler yerine değişkenlerinizi tutmak için bir grup anahtarlı dikt kullanmak daha iyi olabilir:

{Takım, Oturum, Kişi: BoolVar}

Bunun temel nedeni, filtreler aracılığıyla kısıtlamalar uygulayabilmenizdir, bu da iç içe liste manipülasyonları yapmaktan çok daha kolaydır, örneğin, kişiler / ekipler arasında bir kısıtlama uygulamak için şunları yapabilirsiniz (kişinin dizin 2 olduğu ve ekibin dizin olduğu yer) 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 döngüsü için mi demek istediniz p for p in all_people?
Florian Bernard

1
Evet üzgünüm! İsimlerimi modelinize 'tercüme ettim', ama işteydim bu yüzden biraz hızlıydı.
Konchog

1
Ayrıca, posta listesi OR araçlarında gerçekten destekleyicidir. Sorununuzu modelleme konusunda yardıma ihtiyacınız varsa, sizi örnek koda yönlendirecek veya grup / bağımlılık kısıtlamalarını nasıl ayarlayacağınız konusunda harika bir fikir verecektir
Konchog

Üzgünüm ama baş çözümünüzü takip etmek zor, benlikten nereden geliyor? P, S ve G değişkenleri nelerdir? Pv nedir? Yardımın için teşekkürler.
Florian Bernard

0

Her bir yineleme için sadece bir permütasyon algoritması fikri her bir öğrenciden birine veya her oturumdan birine odaklanabilir:

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

Burada öğrenci 2, oturum 1'de öğrenci 1'in yerini alır ve böyle devam eder

Roles 1234
St 2,5,6,7 

Öğrenci 1 ile devam et S3 R 1234 St 10,9,1,8

S4
R 1234
St 11,12,13,1

Sonunda, öğrenci 1 için etkileşimleri kaldırırsınız, örneğin bir sonraki yinelemenin permütasyonları gibi akımı kaldırırsınız.

Rubik küpü gibi.

Bunu kodlamak veya bu algo ile bazı kod biliyorsanız bana bildirin.

Belki itertools permütasyonları ile

Oturumların, uygulama sayısından daha fazla olduğuna inanmıyorum. Sadece bazı havuz tükendiğinde daha fazla almak veya rotasyon için daha fazla yer. Belki ilk önce 4 seans = uygulama hedefleyen sorunu basitleştirebilir?

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.