2009-06-09 15 views
10

Lavoro in una società di consulenza e sono il più delle volte presso le sedi dei clienti. Per questo motivo incontro raramente i miei colleghi. Per conoscerci meglio, organizzeremo una cena. Ci saranno molti piccoli tavoli così le persone potranno chattare. Per parlare al maggior numero di persone possibile durante la festa, tutti devono cambiare tabella ad intervalli, ad esempio ogni ora.Algoritmo di datazione delle velocità

Come si scrive un programma che crea il programma di cambio tabella? Solo per darti dei numeri; in questo caso ci saranno circa 40 persone e ci possono essere al massimo 8 persone per ogni tavolo. Ma, l'algoritmo deve essere generica, naturalmente

+0

Ci deve essere un numero uguale di maschi e femmine per tavolo? – Unknown

+0

No, penso che il problema sia abbastanza difficile. – Hallis

+9

Perché non creare un gruppo Facebook per restare in contatto tra loro? –

risposta

4

questo suona come una domanda di algoritmo genetico:

  1. Selezionare un permutazione casuale dei 40 ospiti - questo è una disposizione dei posti a sedere
  2. Ripetere la permutazione N tempo casuale (n è quante volte sei per passare seggi nella notte)
  3. Unire le permutazioni insieme - questo è il cromosoma per un organismo
  4. Ripetere per come mai gli organismi quanti si vuole allevare in una generazione
  5. il punteggio fitness è il numero di persone che ogni persona avuto modo di vedere in una notte (o in alternativa - l'inverso del numero di persone che non ha vedi)
  6. Razza, muta e introduce nuovi organismi usando il metodo normale e ripeti fino ad ottenere una risposta soddisfacente

È possibile aggiungere qualsiasi altro fattore alla propria forma fisica, ad esempio il rapporto uomo/donna e così via senza modificare notevolmente il metodo sottostante.

+0

Se ho torto, per favore fai notare perché invece della cosa silenziosa, grazie –

+2

, non dovresti lanciare indiscriminatamente algoritmi genetici a qualsiasi problema di ottimizzazione che si presenta, in particolare a problemi piccoli e regolari come questo. – starblue

+2

Qui ci sono molti buoni suggerimenti, ma alla fine ho implementato questo come un algoritmo genetico. Soprattutto perché non avevo mai fatto alcun GA e mi sembrava divertente. Puoi scaricare il mio codice da qui: http://hallvardkorsgaard.spaces.live.com/blog/cns!6A4336898CA0055D!407.entry – Hallis

11

Heres un'idea
primo lavoro dal punto di vista della prima persona .. gli permette di chiamare X
X deve soddisfare tutte le altre persone nella stanza, così abbiamo dovrebbe dividere le persone rimanenti in n gruppi (dove n = # _di_le persone/capacity_per_table) e farlo sedere con uno di questi gruppi per iterazione
Ora che X è stato curato, prenderemo in considerazione la persona successiva Y
WLOG Y essere una persona con cui X doveva sedersi nella prima iterazione stessa ... quindi conosciamo già il gruppo di tavoli di Y per quel periodo di tempo .. dovremmo quindi dividere le restanti persone in gruppi in modo tale che ogni gruppo si trovi con Y per ogni co iterazione nsecutive .. e per ogni iterazione il gruppo di X ed il gruppo di Y hanno nessuna persona in comune
.. Credo che, se continuare a fare qualcosa di simile, si otterrà una soluzione ottimale (se ne esiste uno)

In alternativa si potrebbe affollare il problema dando a ciascuno una carta dove poter scrivere i nomi di tutte le persone con cui hanno cenato .. e alla fine dell'evento, presentare una sorta di premio alla persona con il maggior numero di nomi nella propria carta

+6

+1 al suggerimento alternativo – tanascius

+2

Come la tua idea delle carte! Programmazione genetica in azione. :) –

+1

Mi ricorda http://en.wikipedia.org/wiki/Dance_card – mouviciel

2

Intuitivamente non penso che tu possa fare meglio di un perfect shuffle, ma è al di là della mia conoscenza pre-caffè per dimostrarlo.

4
+1

Sono l'autore di PerfectTablePlan. PerfectTablePlan può gestire questo scenario, ma richiede un po 'di intervento manuale: http://www.perfecttableplan.com/html/PerfectTablePlan_Windows_Help_402/index.html?arrange_multiple_seatings_for_an_event.htm È sulla mia' lista dei desideri 'estendere PerfectTablePlan a gestire meglio sedili multipli. –

+1

@Andy Brice: Bel programma! –

+0

@Andy Brice - Hehe, ho appena fatto il commento per scherzo. Aggiornamento – user79755

6

Perché non imitare mondo reale?

class Person { 
    void doPeriodically() { 
     do { 
      newTable = random (numberOfTables); 
     } while (tableBusy(newTable)) 
     switchTable (newTable) 
    } 
} 

Oh, e notare che v'è un algoritmo simile per trovare un partner di accoppiamento e si dice di essere efficace per coloro il 99% delle persone che non spendono tutte le loro domande di programmazione del tempo libero di rispondere ...

+0

Sono contento di vedere che il mio algoritmo di datazione della velocità ha un certo successo su questo forum ... –

0

Non mi preoccuperei di algoritmi genetici. Invece, farei quanto segue, che è un leggero perfezionamento su ripetuti rimescoli perfetti.

Mentre (ci sono due persone che non hanno soddisfatto):

  1. Consideriamo il grafico in cui ogni nodo è un ospite e il bordo (A, B) esiste se A e B non si sono seduti allo stesso tavolo. Trova tutti gli connected components di questo grafico. Se sono presenti componenti collegati di dimensioni <, pianificare i componenti connessi alle tabelle. Si noti che anche questa è in realtà un'istanza di un problema difficile noto come Imballaggio del contenitore, ma in primo luogo il ridimensionamento probabilmente andrà bene, che può essere ottenuto ordinando i componenti collegati nell'ordine dal più grande al più piccolo, e quindi inserendoli ciascuno di essi in girare al primo tavolo dove si adattano.
  2. Eseguire una permutazione casuale degli elementi rimanenti. (In altre parole, posiziona le persone rimanenti casualmente, che in un primo momento saranno tutti.)
  3. Contatore di incremento che indica il numero di round.

Ripetere quanto sopra per un po 'fino a quando il numero di round sembra convergere.

0

WRT @ commento di neodimio, ecco un page sul sito che è rilevante:

Si discute algoritmi genetici.

2

Questo era molto divertente! : D

Ho provato un metodo diverso ma la logica suggerita da adi92 (card + premio) è quella che funziona meglio di qualsiasi altra che ho provato.

funziona così:

  1. un ragazzo arriva e prende in esame tutti i tavoli
  2. per ogni tabella con i posti liberi si conta quante persone deve incontrare ancora, poi scegliere quella con più sconosciuta persone
  3. se due tabelle hanno un uguale numero di persone sconosciute, allora il ragazzo sceglierà quella con posti a sedere più liberi, in modo che non v'è più probabilità di incontrare più persone nuove

ad ogni giro l'ordine delle persone che prendono posti è casuale (questo evitare possibili loop infinito), questo è un "demo" dell'algoritmo di lavorare in pitone:

import random 

class Person(object): 

    def __init__(self, name): 
     self.name = name 
     self.known_people = dict() 

    def meets(self, a_guy, propagation = True): 
     "self meets a_guy, and a_guy meets self" 
     if a_guy not in self.known_people: 
      self.known_people[a_guy] = 1 
     else: 
      self.known_people[a_guy] += 1 

     if propagation: a_guy.meets(self, False) 

    def points(self, table): 
     "Calculates how many new guys self will meet at table" 
     return len([p for p in table if p not in self.known_people]) 

    def chooses(self, tables, n_seats): 
     "Calculate what is the best table to sit at, and return it" 
     points = 0 
     free_seats = 0 
     ret = random.choice([t for t in tables if len(t)<n_seats]) 

     for table in tables: 
      tmp_p = self.points(table) 
      tmp_s = n_seats - len(table) 
      if tmp_s == 0: continue 
      if tmp_p > points or (tmp_p == points and tmp_s > free_seats): 
       ret = table 
       points = tmp_p 
       free_seats = tmp_s 

     return ret 

    def __str__(self): 
     return self.name 
    def __repr__(self): 
     return self.name 


def Switcher(n_seats, people): 
    """calculate how many tables and what switches you need 
     assuming each table has n_seats seats""" 

    n_people = len(people) 
    n_tables = n_people/n_seats 

    switches = [] 
    while not all(len(g.known_people) == n_people-1 for g in people): 
     tables = [[] for t in xrange(n_tables)] 

     random.shuffle(people) # need to change "starter" 

     for the_guy in people: 
      table = the_guy.chooses(tables, n_seats) 
      tables.remove(table) 
      for guy in table: 
       the_guy.meets(guy) 
      table += [the_guy] 
      tables += [table] 

     switches += [tables] 

    return switches 



lst_people = [Person('Hallis'), 
     Person('adi92'), 
     Person('ilya n.'), 
     Person('m_oLogin'), 
     Person('Andrea'), 
     Person('1800 INFORMATION'), 
     Person('starblue'), 
     Person('regularfry')]  



s = Switcher(4, lst_people) 

print "You need %d tables and %d turns" % (len(s[0]), len(s)) 
turn = 1 
for tables in s: 
    print 'Turn #%d' % turn 
    turn += 1 
    tbl = 1 
    for table in tables: 
     print ' Table #%d - '%tbl, table 
     tbl += 1 
    print '\n' 

Questa volontà di uscita qualcosa di simile:

You need 2 tables and 3 turns 
Turn #1 
    Table #1 - [1800 INFORMATION, Hallis, m_oLogin, Andrea] 
    Table #2 - [adi92, starblue, ilya n., regularfry] 


Turn #2 
    Table #1 - [regularfry, starblue, Hallis, m_oLogin] 
    Table #2 - [adi92, 1800 INFORMATION, Andrea, ilya n.] 


Turn #3 
    Table #1 - [m_oLogin, Hallis, adi92, ilya n.] 
    Table #2 - [Andrea, regularfry, starblue, 1800 INFORMATION] 

A causa del casuale, non sempre viene fornito con il numero minimo di interruttori, specialmente con gruppi di persone più grandi. Dovresti eseguirlo un paio di volte e ottenere il risultato con meno svolte (in modo da non stressare tutte le persone alla festa: P), ed è una cosa facile da codificare: P

PS: Sì , è possibile salvare il montepremi: P