¿Cómo se pueden manejar miles de reglas IF ... THEN ... ELSE?


214

Estoy considerando construir una aplicación, que, en esencia, consistiría en miles de declaraciones ... si ... más El propósito de la aplicación es poder predecir cómo se mueven las vacas en cualquier paisaje. Se ven afectados por cosas como el sol, el viento, la fuente de alimentos, los eventos repentinos, etc.

¿Cómo se puede gestionar una aplicación de este tipo? Me imagino que después de unos cientos de declaraciones IF, sería tan impredecible cómo reaccionaría el programa y depurar lo que llevaría a una cierta reacción significaría que uno tendría que atravesar todo el árbol de declaraciones IF cada vez.

He leído un poco sobre los motores de reglas, pero no veo cómo resolverían esta complejidad.


22
Debe echar un vistazo a la programación DSL: en.wikipedia.org/wiki/Domain-specific_language Además, también podría crear un motor de meta reglas basado en datos. Por ejemplo, podría generar modelos a partir de datos (por ejemplo, KDD de minería de datos)
Darknight

14
google para "sistema experto" y "rete net"; buena suerte.
Steven A. Lowe

99
Mueva las sentencias if / then codificadas del código fuente a datos externos que impulsen la simulación.
Kwebble

66
Bung algunos valores en un archivo de texto y uso un bucle para recorrer un HashMap que contiene nombres.
James P.

2
David: las preguntas de los programadores se convierten a CW cuando se publican más de 15 respuestas. No podemos controlar quién publica la 16a respuesta.
ChrisF

Respuestas:


73

El lenguaje de programación lógica Prolog puede ser lo que estás buscando. Su enunciado del problema no es lo suficientemente específico para que yo pueda evaluar si se ajusta bien, pero es bastante similar a lo que usted dice.

Un programa Prolog consta de hechos y reglas que se aplican. Aquí hay una regla de ejemplo simple que dice "Una vaca se mueve a una ubicación si tiene hambre y hay más comida en la nueva ubicación que en la antigua":

moves_to(Cow, Location) :-
  hungry(Cow),
  current_location(Cow, OldLoc),
  food_in(OldLoc, OldFood), food_in(Location, NewFood),
  NewFood > OldFood.

Todas las cosas en mayúsculas son variables, cosas de las que no sabes el valor. Prolog intenta encontrar valores para estas variables que satisfagan todas las condiciones. Este proceso se realiza con un poderoso algoritmo llamado unificación que es el corazón de Prolog y entornos de programación lógica similares.

Además de las reglas, se proporciona una base de datos de hechos. Un ejemplo simple que funciona con las reglas anteriores podría ser algo como:

current_location(white_cow, pasture).

current_location(black_cow, barn).
hungry(black_cow).

current_location(angry_bull, forest).
hungry(angry_bull).

food_in(barn, 3).
food_in(pasture, 5).
food_in(forest, 1).

Observe que white_cow y pasture, etc. no están escritos en mayúsculas. No son variables, son átomos.

Finalmente haces una consulta y preguntas qué va a pasar.

?- moves_to(white_cow, Destination).
No.
?- moves_to(black_cow, Destination).
Destination = pasture
?- moves_to(Cow, Destination).
Cow = black_cow, Destination = pasture
Cow = angry_bull, Destination = barn
Cow = angry_bull, Destination = pasture

La primera consulta pregunta dónde se moverá la vaca blanca. Dadas las reglas y los hechos anteriores, la respuesta es No. Esto puede interpretarse como "No sé" o "No se mueve" dependiendo de lo que desee.

La segunda consulta pregunta dónde se mueve la vaca negra. Se mueve al pasto para comer.

La consulta final pregunta dónde se mueven todas las vacas. Como resultado, obtienes todo lo posible (Vaca, Destino) que tiene sentido. En este caso, el toro negro se mueve al pasto como se esperaba. Sin embargo, el toro enojado tiene dos opciones que satisfacen las reglas: puede moverse al pasto o al establo.

Nota: Han pasado años desde la última vez que escribí Prolog, todos los ejemplos pueden no ser sintácticamente válidos, pero la idea debería ser correcta.


10
-1: No creo que Prolog pueda ser la respuesta correcta. Sí, puede ser fácil obtener reglas if-else en Prolog. Pero ciertamente tendrás que hacer otra cosa. Y no importa lo que sea (IO; GUI, desarrollo web, ...) será un problema con Prolog.
Martin Thoma

44
Eche un vistazo a learnprolognow.com Y incrustar el prólogo dentro de otro idioma es mucho más fácil de lo que solía ser
Zachary K

@ZacharyK: el enlace está roto.
RenniePet

@ MartinThoma: ¿puedes explicar tu comentario? Los principales problemas con Prolog IMHO son la falta de 1. una forma declarativa de controlar la búsqueda y 2. escribir. Pero si su aplicación no depende en gran medida de estos dos, entonces no veo a priori un problema con el uso de Prolog aquí
SN

139

Al abordar el problema de si web , puede crear un motor de reglas donde cada regla específica se codifique de forma independiente. Una mejora adicional para esto sería crear un lenguaje específico de dominio (DSL) para crear las reglas, sin embargo, un DSL solo desplaza el problema de una base de código (principal) a otra (DSL). Sin estructura, el DSL no funcionará mejor que el lenguaje nativo (Java, C #, etc.), por lo que volveremos a él después de encontrar un enfoque estructural mejorado.

El problema fundamental es que tiene un problema de modelización. Siempre que se encuentre con situaciones combinatorias como esta, es una señal clara de que la abstracción de su modelo que describe la situación es demasiado burda. Lo más probable es que combine elementos que deberían pertenecer a diferentes modelos en una sola entidad.

Si sigue desglosando su modelo, eventualmente disolverá por completo este efecto combinatorio. Sin embargo, al tomar este camino es fácil perderse en su diseño creando un desastre aún mayor, el perfeccionismo aquí no es necesariamente su amigo.

Las máquinas de estados finitos y los motores de reglas son solo un ejemplo de cómo este problema puede desglosarse y hacerse más manejable. La idea principal aquí es que una buena manera de deshacerse de un problema combinatorio como este es a menudo crear un diseño y repetirlo ad-nauseam en niveles anidados de abstracción hasta que su sistema funcione satisfactoriamente. Similar a cómo se usan los fractales para crear patrones intrincados. Las reglas siguen siendo las mismas sin importar si miras tu sistema con un microscopio o desde una vista panorámica.

Ejemplo de aplicar esto a su dominio.

Estás intentando modelar cómo se mueven las vacas por un terreno. Aunque su pregunta carece de detalles, supongo que su gran cantidad de ifs incluye un fragmento de decisión como, por ejemplo, if cow.isStanding then cow.canRun = trueque se atasca a medida que agrega detalles del terreno. Por lo tanto, para cada acción que desee tomar, debe verificar todos los aspectos que pueda pensar y repetir estas verificaciones para la próxima acción posible.

Primero necesitamos nuestro diseño repetible, que en este caso será un FSM para modelar los estados cambiantes de la simulación. Entonces, lo primero que haría es implementar un FSM de referencia, definir una interfaz de estado , una interfaz de transición y quizás un contexto de transiciónque puede contener información compartida que se pondrá a disposición de los otros dos. Una implementación básica de FSM cambiará de una transición a otra independientemente del contexto, aquí es donde entra en juego un motor de reglas. El motor de reglas encapsula limpiamente las condiciones que deben cumplirse para que la transición tenga lugar. Un motor de reglas aquí puede ser tan simple como una lista de reglas, cada una con una función de evaluación que devuelve un valor booleano. Para verificar si se debe realizar una transición, iteremos la lista de reglas y si alguna de ellas se evalúa como falsa, la transición no tiene lugar. La transición en sí contendrá el código de comportamiento para modificar el estado actual del FSM (y otras tareas posibles).

Ahora, si empiezo a implementar la simulación como un solo FSM grande en el nivel de DIOS, termino con MUCHOS estados posibles, transiciones, etc. Parece que el lío if-else está solucionado, pero en realidad solo se extiende: cada IF es ahora una regla que realiza una prueba contra una información específica del contexto (que en este punto contiene casi todo) y cada cuerpo IF está en algún lugar del código de transición.

Ingrese el desglose de fractales: el primer paso sería crear un FSM para cada vaca donde los estados son los propios estados internos de la vaca (de pie, correr, caminar, pastar, etc.) y las transiciones entre ellas se verían afectadas por el medio ambiente. Es posible que el gráfico no esté completo, por ejemplo, el pastoreo solo es accesible desde el estado de reposo, cualquier otra transición se descarta porque simplemente está ausente del modelo. Aquí separa efectivamente los datos en dos modelos diferentes, la vaca y el terreno. Cada uno con su propio conjunto de propiedades. Este desglose le permitirá simplificar el diseño general del motor. Ahora, en lugar de tener un único motor de reglas que decida todo lo que tiene, tiene motores de reglas múltiples y más simples (uno para cada transición) que deciden detalles muy específicos.

Debido a que estoy reutilizando el mismo código para el FSM, esta es básicamente una configuración del FSM. ¿Recuerdas cuando mencionamos DSL antes? Aquí es donde el DSL puede hacer mucho bien si tiene muchas reglas y transiciones para escribir.

Yendo más profundo

Ahora DIOS ya no tiene que lidiar con toda la complejidad en el manejo de los estados internos de la vaca, pero podemos impulsarlo aún más. Todavía hay mucha complejidad involucrada en la gestión del terreno, por ejemplo. Aquí es donde decides dónde es suficiente el desglose. Si, por ejemplo, en su DIOS termina manejando la dinámica del terreno (pasto largo, barro, barro seco, pasto corto, etc.) podemos repetir el mismo patrón. No hay nada que le impida incorporar tal lógica en el terreno mismo extrayendo todos los estados del terreno (hierba larga, hierba corta, fangosa, seca, etc.) en un nuevo FSM de terreno con transiciones entre los estados y quizás reglas simples. Por ejemplo, para llegar al estado fangoso, el motor de reglas debe verificar el contexto para encontrar líquidos, de lo contrario no es posible. Ahora Dios se volvió más simple aún.

Puede completar el sistema de FSM haciéndolos autónomos y dándoles un hilo a cada uno. Este último paso no es necesario, pero le permite cambiar dinámicamente la interacción del sistema al ajustar cómo delega su toma de decisiones (iniciar un FSM especializado o simplemente devolver un estado predeterminado).

¿Recuerdas cómo mencionamos que las transiciones también podrían hacer "otras tareas posibles"? Exploremos eso agregando la posibilidad de que diferentes modelos (FSM) se comuniquen entre sí. Puede definir un conjunto de eventos y permitir que cada FSM registre la escucha de estos eventos. Por lo tanto, si, por ejemplo, una vaca entra en un hex de terreno, el hex puede registrar oyentes para los cambios de transición. Aquí se vuelve un poco complicado porque cada FSM se implementa a un nivel muy alto sin ningún conocimiento del dominio específico que alberga. Sin embargo, puede lograr esto haciendo que la vaca publique una lista de eventos y la celda puede registrarse si ve eventos a los que puede reaccionar. Una buena jerarquía de eventos familiares aquí es una buena inversión.

Puede profundizar aún más modelando los niveles de nutrientes y el ciclo de crecimiento de la hierba, con ... lo adivinó ... un FSM de hierba incrustado en el modelo del parche de terreno.

Si llevas la idea lo suficientemente lejos, DIOS tiene muy poco que hacer, ya que todos los aspectos son casi autogestionados, liberando tiempo para gastar en cosas más piadosas.

Resumen

Como se indicó anteriormente, el FSM aquí no es la solución, solo un medio para ilustrar que la solución a dicho problema no se encuentra en el código por ejemplo, sino en cómo modela su problema. Lo más probable es que haya otras soluciones posibles y mucho mejores que mi propuesta FSM. Sin embargo, el enfoque de "fractales" sigue siendo una buena forma de manejar esta dificultad. Si se hace correctamente, puede asignar dinámicamente niveles más profundos donde sea importante y, al mismo tiempo, proporcionar modelos más simples donde sea menos importante. Puede poner en cola los cambios y aplicarlos cuando los recursos estén más disponibles. En una secuencia de acción, puede no ser tan importante calcular la transferencia de nutrientes de la vaca al parche de hierba. Sin embargo, puede registrar estas transiciones y aplicar los cambios en un momento posterior o simplemente aproximarse con una suposición educada simplemente reemplazando los motores de reglas o quizás reemplazando la implementación FSM por una versión ingenua más simple para los elementos que no están en el campo directo de interés (esa vaca en el otro extremo del campo) para permitir interacciones más detalladas para obtener el foco y una mayor parte de los recursos. Todo esto sin volver a visitar el sistema en su conjunto; Como cada parte está bien aislada, resulta más fácil crear un reemplazo directo que limite o extienda la profundidad de su modelo. Al usar un diseño estándar, puede aprovechar eso y maximizar las inversiones realizadas en herramientas ad-hoc como un DSL para definir reglas o un vocabulario estándar para eventos, comenzando nuevamente a un nivel muy alto y agregando refinamientos según sea necesario. Como cada parte está bien aislada, se hace más fácil crear un reemplazo directo que limite o extienda la profundidad de su modelo. Al usar un diseño estándar, puede aprovechar eso y maximizar las inversiones realizadas en herramientas ad-hoc como un DSL para definir reglas o un vocabulario estándar para eventos, comenzando nuevamente a un nivel muy alto y agregando refinamientos según sea necesario. Como cada parte está bien aislada, se hace más fácil crear un reemplazo directo que limite o extienda la profundidad de su modelo. Al usar un diseño estándar, puede aprovechar eso y maximizar las inversiones realizadas en herramientas ad-hoc como un DSL para definir reglas o un vocabulario estándar para eventos, comenzando nuevamente a un nivel muy alto y agregando refinamientos según sea necesario.

Proporcionaría un ejemplo de código, pero esto es todo lo que puedo permitirme ahora.


1
He aceptado esta respuesta, porque es un orden de magnitud mejor para explicar una solución que los demás. Sin embargo, podría cambiar mi respuesta aceptada si aparece una mejor. Su solución también parece lo suficientemente radical como para marcar la diferencia. Sin embargo, todavía tengo problemas para entender cómo definir las reglas sobre cómo deberían interactuar los diferentes modelos. ¿Podrías hacer un ejemplo de esto?
David

-1 No veo por qué esto no se puede resolver simplemente a través de un árbol de decisión. (junto con un DSL que toma el modelo y lo convierte en código ejecutable)?
Darknight

14
DIOS vs el FSM?
John Cromartie

1
Los árboles de decisión y los motores de reglas se usan precisamente en casos en los que no hay un valor intrínseco para modelar los aspectos en cuestión, ya que son simplemente un medio para finalizar un cálculo. Usted ve esto en el software de atención médica todo el tiempo. Dicho esto, si está tratando de modelar el comportamiento real, debe intentar hacerlo. Hay toneladas de casos en los que la única lógica que se puede encontrar en un problema es el resultado de miles de, si esto es así, hasta el infinito. Y es válido, por eso tenemos herramientas para lidiar con eso.
deleted_user

1
Esto ha demostrado ser muy exitoso en el mundo de la programación de juegos; es mucho más rápido y fácil cambiar una regla o propiedad y dejar que emerja el comportamiento, luego examinar un valor para decidir cómo actuar sobre él.
Ben Leggiero

89

Parece que todas estas declaraciones condicionales de las que estás hablando realmente deberían ser datos que configuran tu programa en lugar de ser parte de tu propio programa. Si puede tratarlos de esa manera, podrá modificar la forma en que funciona su programa simplemente cambiando su configuración en lugar de tener que modificar su código y volver a compilar cada vez que desee mejorar su modelo.

Hay muchas formas diferentes de modelar el mundo real, dependiendo de la naturaleza de su problema. Sus diversas condiciones pueden convertirse en reglas o restricciones que se aplican a la simulación. En lugar de tener un código similar al siguiente:

if (sunLevel > 0.75) {
   foreach(cow in cows) {
       cow.desireForShade += 0.5;
   }
}
if (precipitation > 0.2) {
   foreach(cow in cows) {
       cow.desireForShelter += 0.8;
   }
}

en su lugar, puede tener un código similar al siguiente:

foreach(rule in rules) {
   foreach (cow in cows) {
      cow.apply(rule);
   }
}

O, si puede desarrollar un programa lineal que modele el comportamiento de la vaca dada una cantidad de entradas, cada restricción podría convertirse en una línea en un sistema de ecuaciones. Luego puede convertirlo en un modelo de Markov que puede iterar.

Es difícil decir cuál es el enfoque correcto para su situación, pero creo que será mucho más fácil si considera que sus restricciones son entradas a su programa y no código.


44
Describa cómo "vaca.aplicar (regla);" funciona con archivos de configuración?
Kromster

8
@Krom, es difícil decirlo en términos concretos sin saber de qué tipo de sistema estamos hablando realmente. Mi punto anterior es tratar las miles de condiciones como entradas al programa para que no tenga que escribir código para cada una y pueda cambiar las condiciones sin cambiar el programa. Pero sí, si las condiciones se pueden tratar como datos, las almacenaría por separado del programa en algún tipo de documento o archivo de configuración.
Caleb

2
@Krom - Simple. Leería la regla y luego la aplicaría a la vaca dada.
Ramhound

55
Mover código a archivos de configuración no siempre es un buen enfoque. La magia es difícil de depurar.
Ricky Clarkson

44

Nadie ha mencionado esto, así que pensé que lo diría explícitamente:

Miles de reglas "If .. Then .. Else" son un signo de una aplicación mal diseñada.

Si bien la representación de datos específica del dominio podría parecerse a estas reglas, ¿está absolutamente seguro de que su implementación debe parecerse a la representación específica del dominio?


18
No necesariamente cierto. Hay problemas que solo se pueden resolver a través de enormes árboles de decisión. Pero, por supuesto, una solución para aquellos compuestos por un árbol literal de if-then-else es uno mal diseñado. Existen formas mucho más flexibles y sostenibles de hacerlo.
SF.

43
Pensé que ese era el punto de la pregunta. El OP tiene un problema específico para su dominio que, en una implementación ingenua, requeriría miles de si ... entonces ... más. Tenía la intuición de que esto iba a ser problemático y preguntó a esta comunidad aquí sobre mejores formas de hacerlo. El mero hecho de que se haya hecho la pregunta es un buen canto de que esto ya se entendió, su respuesta, aunque correcta, no ayuda de ninguna manera a la pregunta.
Newtopian

@Newtopian Un usuario o programador avanzado lo entendería y lo consideraría obvio. Sin embargo, un usuario o programador ingenuo podría no darse cuenta de eso. A sabiendas, dije lo que la mayoría de la gente aquí considera obvio: confirme que el OP es correcto en su suposición de que esto sería problemático y que definitivamente no debería ir con la implementación inmediata o ingenua.
blueberryfields

Estoy de acuerdo, puede reemplazarlo si lo hace con polimorfismo y DI. Si tienes millones de si no, tu diseño es muy malo.
DarthVader

17

Utilice los lenguajes de software / computadora que sean adecuados para la tarea. Matlab se usa muy a menudo para modelar sistemas complejos, donde puede tener literalmente miles de condiciones. No utilizando las cláusulas if / then / else, sino mediante análisis numérico. R es un lenguaje de computadora de código abierto que está lleno de herramientas y paquetes para hacer lo mismo. Pero esto significa que también debe reformular su modelo en términos más matemáticos, de modo que pueda incluir tanto las influencias principales como las interacciones entre las influencias en los modelos.

Si aún no lo hizo, siga un curso sobre modelado y simulación. Lo último que debe hacer es considerar escribir un modelo como ese en términos de if - then - else. Tenemos cadenas de Monte Carlo Markov, máquinas de vectores de soporte, redes neuronales, análisis de variables latentes, ... Por favor, no retrocedas 100 años ignorando la riqueza de las herramientas de modelado que tienes disponibles.


Me sorprende cómo esta pregunta recibió tan poca atención. El análisis numérico y el modelado son, en esencia, una máquina if-else. Sin embargo, adolece de falsos positivos que pueden no ser tolerados si la aplicación requiere un estricto cumplimiento de las reglas. (Piense en la banca)
Arun Jose

13

Los motores de reglas pueden ayudar porque si hay tantas reglas if / then, podría ser útil tenerlas todas en un lugar fuera del programa donde los usuarios puedan editarlas sin necesidad de conocer un lenguaje de programación. Además, las herramientas de visualización pueden estar disponibles.

También puede buscar soluciones de programación lógica (como Prolog). Puede modificar rápidamente la lista de sentencias if / then y hacer que haga cosas como ver si cualquier combinación de entradas conduciría a ciertos resultados, etc. También podría ser más limpio en la lógica de predicados de primer orden que como código de procedimiento (o como código orientado a objetos).


11

De repente me di cuenta:

Debe usar un árbol de aprendizaje de decisiones (algoritmo ID3).

Es muy probable que alguien lo haya implementado en su idioma. Si no, podría portar una biblioteca existente


Vaya con la idea DSL dada anteriormente. Trate de descubrir cómo abstraer el problema a alguna forma de álgebra simbólica, luego implemente eso.
Zachary K


9

Cada aplicación grande contiene miles de if-then-elsedeclaraciones, sin contar otros controles de flujo, y esas aplicaciones aún se depuran y mantienen, a pesar de su complejidad.

Además, el número de declaraciones no hace que el flujo sea impredecible . La programación asincrónica sí. Si usa algoritmos deterministas sincrónicamente, tendrá un comportamiento 100% predecible, siempre.

Probablemente debería explicar mejor qué está tratando de hacer en Stack Overflow o Code Review para que las personas puedan sugerirle las técnicas de refactorización precisas que debe usar. También es posible que desee hacer preguntas más precisas, como "¿Cómo evito anidar demasiadas ifdeclaraciones <dado un código>?".


1
La mayoría de las aplicaciones tienen 2-3 niveles de anidamiento y condiciones de 1 línea. ¿Qué pasa con un problema que requiere un árbol de decisión anidado 50 niveles hacia abajo, y muchas condiciones son compuestos lógicos de 30 o más variables cada uno?
SF.

Si bien "Toda aplicación grande ..." es cierto, es bastante claro que el OP está hablando de secuencias largas de expresiones condicionales que esencialmente forman las reglas en un modelo. ifEn el mejor de los casos, enormes grupos anidados de declaraciones se vuelven difíciles de manejar, por lo que se requiere un mejor enfoque.
Caleb

@Caleb: tienes razón, está claro ahora , con el ejemplo preciso al comienzo de la pregunta. No fue antes de que la pregunta fuera editada cuando escribí mi respuesta. Esto explica la incoherencia real de mis y otras dos respuestas publicadas al mismo tiempo.
Arseni Mourzenko

2

Haga que su aplicación sea manejable diseñándola bien. Diseñe su aplicación dividiendo las diversas lógicas comerciales en clases / módulos separados. Escriba pruebas unitarias que prueben cada una de estas clases / módulos individualmente. Esto es crucial y lo ayudará a garantizar que la lógica empresarial se implemente como se espera.


2

Probablemente no haya una sola forma de diseñar su solución a su problema, pero puede manejar la complejidad de la misma pieza por pieza si intenta separar las diferentes áreas donde se encuentra escribiendo grandes bloques de declaraciones if y aplicando soluciones a cada uno de esos pequeños problemas.

Busque técnicas como las reglas de las que se habló en Refactorización para encontrar formas de dividir grandes condicionales en fragmentos manejables: por ejemplo, varias clases con una interfaz común pueden reemplazar una declaración de caso.

Salir temprano también es de gran ayuda. Si tiene condiciones de error, elimínelas al comienzo de la función lanzando una excepción o regresando en lugar de dejar que se aniden.

Si divide sus condiciones en funciones de predicado, puede ser más fácil hacer un seguimiento de ellas. Además, si puede obtenerlos en un formato estándar, podría ser posible obtenerlos en una estructura de datos construida dinámicamente, en lugar de una codificada.


2

Te sugiero que uses un motor de reglas. En el caso de Java, jBPM u Oracle BPM pueden ser útiles. Los motores de reglas básicamente le permiten configurar la aplicación a través de XML.


+1 Últimamente he estado usando Drools junto con Mvel como lenguaje para expresar las reglas, y es exactamente lo que estás buscando. A pesar del hecho de que es muy rápido.
Jalayn

Drools es una buena opción. Personalmente estoy usando Oracle BPM en este momento. También está Feugo. Un montón de código abierto y herramientas de propiedad disponibles.
Sid

2

El problema no está bien resuelto por las "reglas", ya sea descrito por el código de procedimiento "si-entonces" o por las numerosas soluciones de reglas diseñadas para aplicaciones comerciales. El aprendizaje automático proporciona una serie de mecanismos para modelar tales escenarios.

Fundamentalmente, uno tiene que formular algún esquema para la representación discreta de los factores (p. Ej., Sol, viento, fuente de alimento, eventos repentinos, etc.) que influyen en el "sistema" (es decir, las vacas en un potrero). A pesar de la creencia equivocada de que uno puede crear una representación funcional valorada real, en lugar de discreta, ninguna computadora en el mundo real (incluido el sistema nervioso humano) se basa en valores reales o se basa en valores reales.

Una vez que tenga su representación numérica para los factores relevantes, puede construir cualquiera de varios modelos matemáticos. Sugeriría un gráfico bipartito donde un conjunto de nodos representa vacas y el otro un área unitaria de pasto. Una vaca en cualquier caso ocupa una unidad de área de pasto. Para cada vaca existe un valor de utilidad asociado con la actual y todas las demás unidades de pasto. Si el modelo presupone que la vaca busca optimizar (lo que sea que signifique para la vaca) el valor de utilidad de su unidad de pasto, entonces las vacas se moverán de una unidad a otra en un esfuerzo por optimizar.

Un autómata celular funciona bien para ejecutar el modelo. La matemática subyacente en el mundo matemático realmente valioso que motiva el movimiento de las vacas es un modelo de gradiente de campo. Las vacas se mueven de posiciones de menor valor de utilidad percibido a posiciones de mayor valor de utilidad percibido.

Si se inyecta un cambio ambiental en el sistema, entonces no se moverá a una solución de estado estable de posicionamiento de vacas. También se convertirá en un modelo al que se podrían aplicar aspectos de la teoría de juegos; no es que eso necesariamente agregaría mucho a este caso.

La ventaja aquí es la matanza de vacas o la adquisición de nuevas vacas se puede manejar fácilmente restando y agregando celdas de "vaca" al gráfico bipartito, mientras el modelo se está ejecutando.


1

No creo que deba definir tantas declaraciones if-else. Desde mi punto de vista, su problema tiene múltiples componentes:

  • Debe ser asíncrono o multiproceso, porque tiene varias vacas con diferentes personalidades, diferentes configuraciones. Cada vaca se pregunta en qué dirección ir antes de su próximo movimiento. En mi opinión, un código de sincronización es una herramienta pobre para este problema.

  • La configuración del árbol de decisión cambia constantemente. Depende de la posición de la vaca real, el clima, el tiempo, el terreno, etc. En lugar de construir un árbol complejo si no, creo que deberíamos reducir el problema a una rosa de los vientos o una dirección - función de peso : Figura 1 figura 1 - dirección - funciones de peso para algunas de las reglas

    La vaca siempre debe ir en la dirección que tenga el mayor peso total. Entonces, en lugar de construir un gran árbol de decisión, puede agregar un conjunto de reglas (con diferentes direcciones - funciones de peso) a cada vaca, y simplemente procesar el resultado cada vez que pregunte la dirección. Puede reconfigurar esas reglas por cada cambio de posición, o al pasar el tiempo, o puede agregar estos detalles como parámetros, cada regla debería obtener. Es una decisión de implementación. La forma más sencilla de obtener una dirección es agregar un bucle simple de 0 ° a 360 ° con un paso de 1 °. Después de eso, puede contar el peso de la suma de cada dirección 360 y ejecutar una función max () para obtener la dirección correcta.

  • No necesariamente necesita una red neuronal para hacer esto, solo una clase para cada regla, una clase para las vacas, tal vez para el terreno, etc. y una clase para el escenario (por ejemplo, 3 vacas con diferentes reglas y 1 terreno específico). Figura 2 figura 2: conexiones y nodos de decisión asíncronos de aplicaciones de vaca

    • rojo para la dirección de mensajes: mapa de peso a través de las reglas
    • azul para actualizaciones de orientación y posición después de la toma de decisiones
    • verde para actualizaciones de entrada después de la orientación y actualización de posición
    • negro para obtener entradas

    nota: probablemente necesitará un marco de mensajería para implementar algo como esto

    Entonces, si hacer vacas de aprendizaje no es parte de su problema, no necesita una red neuronal o algoritmos genéticos. No soy un experto en IA, pero supongo que si desea adaptar sus vacas a las reales, puede hacerlo simplemente con un algoritmo genético y el conjunto adecuado de reglas. Si entiendo bien, necesita una población de vacas con configuraciones de reglas aleatorias. Después de eso, puede comparar el comportamiento de las vacas reales con el comportamiento de su población modelo y mantener el 10% que recorre el camino más cercano a las reales. Después de eso, puede agregar nuevas restricciones de configuración de reglas a su fábrica de vacas en función del 10% que mantuvo, y agregar nuevas vacas aleatorias a la población, y así sucesivamente, hasta que obtenga una vaca modelo que se comporte como las reales ...


0

Añadiría que podría ser el caso de que si realmente tienes miles de reglas IF ... LUEGO, podrías estar especificando en exceso. Por lo que vale, las charlas de modelado de redes neuronales a las que he asistido a menudo comienzan afirmando cómo con "un simple conjunto de reglas" pueden generar un comportamiento bastante complejo y razonablemente coincidente con la realidad (de, en esos casos, neuronas reales en acción). Entonces, ¿estás seguro?necesitas miles de condiciones? Quiero decir, además de 4-5 aspectos del clima, la ubicación de las fuentes de alimentos, los eventos repentinos, el pastoreo y el terreno, ¿realmente van a tener muchas más variables? Claro, si trataste de hacer todas las permutaciones posibles de combinar esas condiciones, entonces fácilmente podrías tener muchos miles de reglas, pero ese no es el enfoque correcto. Quizás un enfoque de estilo de lógica difusa en el que los diversos factores introducen un sesgo en la ubicación de cada vaca que se combinan con una decisión general le permitiría hacer esto en muchas menos reglas.

También estoy de acuerdo con todos los demás en que el conjunto de reglas debe estar separado del flujo general de código, para que pueda modificarlo fácilmente sin cambiar el programa. Incluso podría crear conjuntos de reglas de la competencia y ver cómo funcionan contra los datos reales del movimiento de las vacas. Suena divertido.


0

Se han mencionado sistemas expertos, que son un área de IA. Para ampliar un poco sobre estos, leer sobre motores de inferencia puede ayudarlo con esto. Una búsqueda en Google podría ser más útil: escribir el DSL es la parte fácil, puede hacerlo trivialmente con un analizador como Gold Parser. La parte difícil proviene de construir su árbol de decisiones y ejecutarlas de manera eficiente.

Muchos sistemas médicos ya utilizan estos motores, por ejemplo, el sitio web NHS Direct del Reino Unido .

Si eres un .NET'er, entonces Infer.NET puede ser útil para ti.


0

Debido a que observa el movimiento de la vaca, están atrapados en una dirección de 360 ​​grados (las vacas no pueden volar). También tiene una tarifa que está viajando. Esto se puede definir como un vector.

Ahora, ¿cómo lidias con cosas como la posición del sol, la pendiente de la colina, el ruido fuerte?

Cada uno de los grados sería una variable que significaría el deseo de ir en esa dirección. Digamos que una ramita se rompe a la derecha de la vaca a 90 grados (suponiendo que la vaca mire 0 grados). El deseo de ir a la derecha disminuirá y el deseo de ir a 270 (izquierda) aumentará. Revisa todos los estímulos sumando o restando su influencia en el deseo de las vacas de ir en una dirección. Una vez que se aplican todos los estímulos, la vaca irá en la dirección del deseo más elevado.

También puede aplicar gradientes para que los estímulos no tengan que ser binarios. Por ejemplo, una colina no está recta en una dirección. Tal vez la vaca está en un valle o en una carretera en una colina donde estaba completamente recta, a 45 * cuesta arriba leve a 90 * colina abajo levemente. A 180 * cuesta arriba empinada.

Luego puede ajustar el peso de un evento y su dirección de influencia. En lugar de una lista de if thens, tienes una prueba buscando el máximo. Además, cuando desee agregar un estímulo, simplemente puede aplicarlo antes de la prueba y no tiene que lidiar con agregar más y más complejidad.

En lugar de decir que la vaca irá en cualquier dirección 360, vamos a dividirla en 36 direcciones. Cada uno de 10 grados

En lugar de decir que la vaca irá en cualquier dirección 360, vamos a dividirla en 36 direcciones. Cada uno de 10 grados. Dependiendo de cuán específico debes ser.


-2

Usa POO. ¿Qué tal crear un grupo de clases que manejen las condiciones básicas y ejecuten métodos aleatorios para simular lo que está haciendo?

Consigue un programador para que te ayude.

class COW_METHODS {

    Function = array('Action1','Action2',....'ActionX');

    function doAction() {
       execute(Function[random(1,5000]);
    }

    function execute(DynamicFunction) {
        exec(DynamicFunction());
    }

    Function Action1() {
        turnRight();
        eatGrass();
    }
    /*  keep adding functions for COW Methods ...  etc  */
    /*  and add classes for conditions inherit them as needed  */
    /*  keep an object to define conditions =  Singleton etc.  */
}

¿Por qué es esta la última respuesta? Llega al punto, que es que miles de declaraciones if else son simplemente una forma de diseñar un programa.
wfbarksdale

1
Porque recomendar " Usar OOP. Obtener un programador para ayudar " vale lo mismo que dar el consejo "¡ Haga más llamadas telefónicas! " Cuando se le pregunte " ¿Cómo puedo cuadruplicar mis ventas? ". No es estrictamente incorrecto, pero tampoco ayuda mucho.
JensG

2
Voté en contra, porque esta es una mala respuesta. Técnicamente; su respuesta tiene poco que ver con OOP. Una clase llamada COW_METHODSparece no ser más que una colección de métodos poco relacionados. ¿Dónde está la separación de las preocupaciones? Relacionado con la pregunta, ¿cómo ayuda esto al autor de la pregunta?
2015
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.