2009-06-09 19 views
10

Trabajo en una organización de consultoría y la mayor parte del tiempo en las instalaciones de los clientes. Por eso rara vez conozco a mis colegas. Para conocernos mejor, organizaremos una cena. Habrá muchas mesas pequeñas para que la gente pueda charlar. Para hablar con tantas personas diferentes como sea posible durante la fiesta, todo el mundo tiene que cambiar las tablas en algún intervalo, por ejemplo, cada hora.Speed ​​dating algorithm

¿Cómo escribo un programa que crea el horario de cambio de tabla? Solo para darte algunos números; en este caso, habrá alrededor de 40 personas y puede haber como máximo 8 personas en cada mesa. Sin embargo, el algoritmo necesita ser genérica por supuesto

+0

¿Tiene que haber un número igual de hombres y mujeres por mesa? – Unknown

+0

No, creo que el problema ya es bastante difícil. – Hallis

+9

¿Por qué no creas un grupo de Facebook para mantenerte en contacto? –

Respuesta

4

Esto suena como una solicitud de algoritmo genético:

  1. Seleccione una permutación aleatoria de las 40 personas - esta es una disposición de los asientos
  2. Repita la permutación N tiempo aleatorio (n es el número de veces que es para cambiar asientos en la noche)
  3. Combinar las permutaciones juntos - este es el cromosoma de una organismo
  4. Repita cómo cada vez organismos número de boletos para reproducirse en una generación
  5. la puntuación de fitness es el número de personas que cada persona recibió de ver en una noche (o, alternativamente, - el inverso del número de personas a las que no lo hicieron ver)
  6. Criar, mutar e introducir nuevos organismos usando el método normal y repetir hasta que obtenga una respuesta satisfactoria

Puede agregar cualquier otro factor que desee en la condición física, como la relación hombre/mujer y así sucesivamente sin cambiar mucho el método subyacente.

+0

Si me equivoco, señale por qué en lugar del voto silencioso, gracias –

+2

No debe arrojar indiscriminadamente algoritmos genéticos en cualquier problema de optimización que se presente, en particular, no en problemas pequeños y regulares como este. – starblue

+2

Aquí hay muchas buenas sugerencias, pero terminé implementando esto como un algoritmo genético. Principalmente porque no había hecho ningún GA antes y sonaba divertido de hacer. Puede descargar mi código desde aquí: http://hallvardkorsgaard.spaces.live.com/blog/cns!6A4336898CA0055D!407.entry – Hallis

11

aquí una idea
primer trabajo desde la perspectiva de la primera persona .. le permite llamar X
X tiene que cumplir con todas las otras personas en la habitación, por lo que debería dividir a las personas restantes en n grupos (donde n = # _of_people/capacity_per_table) y hacer que se siente con uno de estos grupos por iteración
Ahora que se ha ocupado de X, consideraremos a la siguiente persona Y
WLOG Y ser una persona con la que X tuvo que sentarse en la primera iteración en sí ... así que ya conocemos el grupo de la tabla de Y para ese marco de tiempo ... entonces deberíamos dividir a las personas restantes en grupos para que cada grupo se siente con Y por cada co iteración nsecutive .. y para cada iteración grupo de X y el grupo de Y tienen ninguna persona en común
.. supongo, si seguir haciendo algo como esto, obtendrá una solución óptima (si existe)

alternativa, podría agrupar el problema dando a cada persona una tarjeta donde puedan escribir los nombres de todas las personas con las que cenaron ... y al final del evento, presente algún tipo de premio a la persona que tenga más nombres en su tarjeta

+6

+1 a la sugerencia alternativa – tanascius

+2

¡Te gusta tu idea sobre las cartas! Programación genética en acción. :) –

+1

Me recuerda http://en.wikipedia.org/wiki/Dance_card – mouviciel

2

Intuitivamente no creo que puedas hacer mejor que un perfect shuffle, pero está más allá de mi conocimiento previo al café probarlo.

4
+1

Soy el autor de PerfectTablePlan. PerfectTablePlan puede manejar este escenario, pero necesita un poco de intervención manual: http://www.perfecttableplan.com/html/PerfectTablePlan_Windows_Help_402/index.html?arrange_multiple_seatings_for_an_event.htm Está en mi 'lista de deseos' para extender PerfectTablePlan a manejar múltiples asientos mejor. –

+1

@Andy Brice: ¡Buen programa! –

+0

@Andy Brice - Hehe, acabo de hacer el comentario en broma. – user79755

6

Por qué no imitar el mundo real?

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

Ah, y tenga en cuenta que existe un algoritmo similar para encontrar una pareja de apareamiento y se rumorea para ser eficaz para aquellos 99% de las personas que no pasan todo su tiempo respondiendo a las preguntas de programación libre ...

+0

Me alegra ver que mi algoritmo de citas rápidas tiene cierto éxito en este foro ... –

0

No me molestaría con los algoritmos genéticos. En su lugar, haría lo siguiente, que es un ligero refinamiento en repetidas mezclas perfectas.

bien (hay dos personas que no han cumplido):

  1. Considere el gráfico, donde cada nodo es un invitado y el borde (A, B) existe si A y B no se han sentado en la misma mesa. Encuentra todos los connected components de este gráfico. Si hay componentes conectados de tamaño de tabla <, planifique los componentes conectados en las tablas. Tenga en cuenta que incluso esto es en realidad una instancia de un problema difícil conocido como Bin packing, pero la disminución del primer ajuste probablemente sea buena, lo cual se puede lograr clasificando los componentes conectados en orden de mayor a menor, y luego poniéndolos en cada uno de ellos gira en la primera mesa donde encajen.
  2. Realice una permutación aleatoria de los elementos restantes. (En otras palabras, asiente a las personas restantes al azar, que al principio serán todas).
  3. Contador de incremento que indica el número de rondas.

Repite lo anterior por un tiempo hasta que el número de vueltas parezca converger.

0

WRT @ comentario de neodimio, aquí hay un page en el sitio que es relevante:

Se analizan los algoritmos genéticos.

2

¡Este fue muy divertido! : D

Probé con un método diferente pero la lógica sugerida por adi92 (tarjeta + premio) es la que funciona mejor que cualquier otra que probé.

funciona así:

  1. un tipo llega y examina todas las tablas
  2. para cada mesa con asientos libres que cuenta la cantidad de gente que tiene que cumplir, sin embargo, a continuación, elegir el que tenga más desconocida
  3. personas
  4. si dos tablas tienen un número igual de personas desconocidas entonces el chico va a elegir el que tenga asientos más libre, por lo que hay más probabilidad de conocer más gente nueva

En cada vuelta del orden de las personas que toman asientos es al azar (esto evitar posibles bucles infinitos), este es un "demo" del algoritmo de trabajo en Python:

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' 

Esto sería algo así como:

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] 

Debido a lo aleatorio, no siempre tendrá la cantidad mínima de interruptores, especialmente con grupos de personas más grandes. Debería ejecutarlo un par de veces y obtener el resultado con menos giros (para no estresar a todas las personas en la fiesta: P), y es fácil codificar: P

PD: Sí , puede guardar el dinero del premio: P