Algoritmo secuencial

A diferencia del algoritmo RetePlus , la modalidad de ejecución secuencial no proporciona inferencia. El algoritmo secuencial sólo funciona de forma predecible cuando las reglas son homogéneas, es decir, cuando utilizan los mismos enlaces.

Para garantizar la misma ejecución con cualquiera de los algoritmos, se requieren las dos condiciones siguientes:

  • Las reglas deben ser homogéneas. Las reglas homogéneas significan que las condiciones de esas reglas deben establecerse en el mismo tipo y número de objetos. Si intenta aplicar el algoritmo secuencial a reglas heterogéneas, normalmente crea más objetos de tupla, lo que puede hacer que se ejecuten más reglas que en la modalidad RetePlus . La firma de tupla común también puede provocar que no se activen reglas heterogéneas: cuando no hay instancias correspondientes en la memoria de trabajo, no se pueden crear tuplas.

  • Las reglas no deben encadenarse, es decir, la modificación realizada en la parte de acción de una regla no debe llevar a la ejecución de otra regla.

Si especifica la modalidad de ejecución secuencial para reglas que no son compatibles con ella, el motor genera un error.

El uso de la modalidad de ejecución secuencial se describe más adelante en las secciones:

Tuplas

Una tupla es una lista de objetos que cumple con una estructura determinada. Una estructura de tupla es simplemente una secuencia de descriptores de clase. Cada ubicación de una estructura de tupla se denomina ranura. El mismo descriptor de clase puede aparecer más de una vez en diferentes ranuras.

Tome una estructura de tupla:

(Customer,Product)

Aquí hay una tupla que cumple con esta estructura:

(new Customer("Henry"),new DVD("Mickey"))

Tenga en cuenta que la subclase se tiene en cuenta porque un DVD es un Product. Sin embargo, algunas tuplas que no cumplen con la estructura:

Por ejemplo, la siguiente tupla es demasiado grande:


(new Customer("Henry"),new CD("Madona"),new DVD("Mickey"))

Esta tupla no está ordenada correctamente:


(new DVD("Lord of the rings"),new Customer("Henry"))

Y esta tupla es demasiado pequeña:


(new Customer("Henry"))

En Java™, una tupla se implementa fácilmente como una matriz de objetos:


Java Tuple = Object[]

El código Java para crear una tupla y sus objetos es:


new Object[] {new Customer("Henry"),new DVD("Mickey")}

En tiempo de ejecución, las tuplas se crean a mano o automáticamente a partir del contenido de la memoria de trabajo y, a continuación, se pasan al motor de reglas. Las tuplas se pasan una tras otra al método de coincidencia de tuplas.

Las tuplas se construyen a partir de los objetos de la memoria de trabajo sólo si coinciden con la estructura de tupla: una firma común que comparten todas las reglas de la tarea secuencial. Después de la generación de tuplas, todas las reglas se ejecutan en todas las tuplas. Por lo tanto, se recomienda utilizar reglas homogéneas con el algoritmo secuencial.

Si proporciona su propia tupla, siempre debe coincidir con la firma, pero no necesariamente tiene que estar completa. Una tupla parcial es una tupla con ranuras no utilizadas. Las ranuras no utilizadas simplemente se establecen en un valor nulo. Por ejemplo, la tupla(new Customer("Henry")) que era demasiado pequeña se podría codificar como (new Customer("Henry"),null) para poder satisfacer la estructura de la tupla.

Por ejemplo, si tiene las dos reglas siguientes, la firma es [Entero, Entero]. Si sólo hay un entero en la memoria de trabajo, la regla r2 no se activa.
rule r1 {
when{
  Integer();
  Integer();
}
then {...


rule r2 {
when{
  Integer();
}
then {...
Por ejemplo, si tiene las dos reglas siguientes, la firma es [String, Integer]. Si tiene dos series (S1, S2) en la memoria de trabajo y un entero (I1), la regla r2 se activa una vez para cada tupla [S1, I1] [S2, I1]. Esto significa que r2 se activa dos veces para I1.
rule r1 {
when{
  Integer();
  String();
}
then {...


rule r2 {
when{
  Integer();
}
then {...

Selección de reglas en modalidad secuencial

Las reglas de una tarea de regla que se establecen con la propiedad algorithm igual a sequential se convierten dinámicamente en código de bytes Java. El código de bytes es capaz de realizar un proceso secuencial cuando se ejecuta la tarea.

La propiedad body de una tarea de regla es obligatoria. Selecciona las reglas del conjunto de reglas que la tarea de reglas tiene en cuenta.

Consulte también Selección de reglas de tiempo de ejecución.

Propiedades de control en modalidad secuencial

Las propiedades de control afectan a la ejecución en modalidad secuencial y a la estructura de tupla. Consulte Propiedades de control para tareas de reglas en modalidades de ejecución para obtener más información general.

El número de reglas que se deben ejecutar por tupla y el orden en el que se ejecutan se pueden especificar con las propiedades de control: orden, activacióny firinglimit.

La propiedad de ordenación

La propiedad ordering es obligatoria para el proceso secuencial. Describe el orden en el que se ejecutarán las reglas de la tarea de regla.

Hay dos valores disponibles:

  • literal: las reglas se mantienen en el orden en el que se establecen en el cuerpo de la tarea (utilizando flechas arriba/abajo).

  • sorted: las reglas se ordenan según sus prioridades estáticas.

Tenga en cuenta que otro valor, dynamic, sólo está disponible para las tareas de regla que utilizan la modalidad de ejecución RetePlus .

La propiedad de activación

La propiedad firing especifica si, para cada tupla, se deben ejecutar todas las reglas o sólo la primera regla que se aplica. Esta propiedad es opcional.

Tiene dos valores posibles:

  • allrules

    Este valor significa que todas las reglas que se aplican deben ejecutarse antes de saltarse a la siguiente tupla. Este es el valor predeterminado.

  • rule

    Este valor significa que sólo se debe ejecutar la primera regla que se aplica en la primera tupla.

La propiedad firinglimit

La propiedad firinglimit proporciona otro nivel de control cuando la propiedad firing se establece en allrules. Se utiliza para especificar un número que representa el número máximo de reglas que se deben ejecutar antes de saltar a la siguiente tupla. Este número debe ser mayor que cero.

Limitaciones conocidas del algoritmo secuencial

En casi todos los casos no hay limitación en el número de reglas manejadas por una sola tarea que tiene una propiedad de algoritmo igual a secuencial. La única excepción es con tablas de decisiones extremadamente grandes con un otherwise. El proceso es el siguiente: todas las condiciones de todas las líneas se niegan en una sola expresión. Esta expresión única se convierte en el cuerpo de un único método una vez traducido al código de bytes. Esto es un problema porque el verificador Java rechaza los métodos con un cuerpo demasiado grande. El algoritmo de escalabilidad utilizado para las reglas no se reduce al cuerpo del método. Se notifica al usuario de esta limitación cuando el cargador de clases rechaza las reglas. El límite en el número de reglas no es claro, pero es probable que el número sea de varios miles.

La tabla siguiente describe las limitaciones del proceso secuencial, en particular su uso combinado con determinadas construcciones de ILOG ® Rule Language (IRL).

Limitación Descripción
Limitaciones de ILOG Rule Language (IRL)

No todos los patrones de reglas que se han diseñado para la coincidencia de Rete con estado están disponibles. Los errores de tiempo de compilación se producen cuando una regla no es compatible con la implementación de coincidencia de tupla actual.

Por lo tanto, cuando se utiliza el proceso secuencial, IRL no da soporte a las características siguientes:

  • prioridades dinámicas

    Puesto que no hay ninguna agenda en el proceso secuencial, sólo se permiten las reglas con prioridades estáticas.

  • not, exists, collect condiciones sin un enumerador

    Las condiciones not, existsy collect con un enumerador (from o in) se convierten al código de bytes Java. Cuando se especifica un enumerador, el conjunto de objetos está disponible como un valor vinculado a la condición. (Tenga en cuenta que esto no es una limitación para RetePlus o Fastpath.)

Construcciones de condición

Las siguientes construcciones de condición están disponibles en el proceso secuencial:

  • los enlaces de condición simples y las pruebas están disponibles

  • from

  • in

Manejo de excepciones

El manejo de excepciones no está soportado en las partes de condición de regla en las modalidades secuencial y de vía de acceso rápida.

Por ejemplo, si especifica un manejador de excepciones en un contexto, no se tiene en cuenta en las modalidades secuencial y Fastpath:

IlrContext mycontext="....";
IlrExceptionHandler myhandler="....";
mycontext.setExceptionHandler(myhandler);
Refracción

La unidad de datos para un ciclo de motor es la tupla. El motor no registra las tuplas ya que están emparejadas, más bien las olvida entre ciclos. Por lo tanto, no hay soporte incorporado para la refracción.

Utilizando la modalidad de ejecución secuencial, la tarea de regla anterior se convierte en:


ruletask main {
   algorithm = sequential;
   ordering = literal;
   body = {Person,PersonProduct}
}

La estructura de tupla calculada:


(Person,Product)

El código de coincidencia de tupla generado:


void matchObjects(Object[] tuple) {
   rule_Person((Person)tuple[0]);
   rule_PersonProduct((Person)tuple[0],(Product)tuple[1]);
}

El código principal sigue siendo el mismo:

  1. context.insert(new Person("Henry"));

  2. context.insert(new CD("Madona"));

  3. context.insert(new DVD("Mickey"));

  4. context.execute();

Bucle de iterador de memoria de trabajo:

  1. matcher.matchObjects((Person("Henry"),CD("Madona")));

  2. matcher.matchObjects((Person("Henry"),DVD("Mickey")));

El rastreo de ejecución:

  1. // matcher.matchObjects((Person("Henry"),CD("Madona")));

  2. Person(Henry)

  3. PersonProduct(Henry,Madona)

  4. // matcher.matchObjects((Person("Henry"),DVD("Mickey")));

  5. Person(Henry)

  6. PersonProduct(Henry,Mickey)

El rastreo de ejecución muestra que, utilizando la modalidad de ejecución secuencial, la misma regla se ejecuta dos veces para las mismas partes de dos tuplas diferentes.

Recursos IRL (ILOG Rule Language)

Por el contrario, prácticamente todas las expresiones y sentencias de nivel de script del IRL están disponibles en el proceso secuencial. Sirven principalmente para mantener la coherencia de las otras tareas de regla que no están establecidas en el algoritmo secuencial.

A continuación se muestra una lista de estas características:

Funciones

Las definiciones de función y las llamadas están totalmente disponibles.

Expresiones de nivel de script

Todas las expresiones IRL están disponibles. (Tenga en cuenta que ?instance funciona en cualquier modalidad de ejecución.)

Sentencias a nivel de script

Todas las sentencias IRL están disponibles.

Actualizar

La construcción de actualización está disponible porque pueden existir actualizaciones falsas en las tareas de regla establecidas en el algoritmo secuencial. Una actualización falsa es una actualización en un objeto que no puede coincidir con ninguna parte de condición de las tareas de regla establecidas en el algoritmo secuencial, pero que puede ser significativa para otras tareas de regla que utilizan el algoritmo RetePlus . Todas las tareas de reglas se especifican en el conjunto de reglas y deben mantenerse coherentes con el motor actual. Sin embargo, es importante tener en cuenta que la actualización habitual no la maneja en absoluto el algoritmo de proceso secuencial sin estado.

Actualizar renovación

La modalidad de renovación no la maneja en absoluto el algoritmo de proceso secuencial, pero puede ser relevante para otras tareas de regla utilizando el algoritmo RetePlus .

Insertar

La inserción de objetos que podrían coincidir con partes de condición de tareas de regla establecidas en el algoritmo secuencial puede provocar incoherencias cuando las tuplas de objetos se extraen de la memoria de trabajo. Esto se debe a que los objetos se insertan en la primera posición y no se notifica al iterador que crea las tuplas. Por lo tanto, el iterador no proporciona las tuplas que implican el nuevo objeto al motor de proceso secuencial. Sin embargo, la inserción sigue siendo relevante para otras tareas de reglas utilizando el algoritmo RetePlus .

Los ejemplos siguientes muestran casos que causan errores de compilación JIT (Just-In-Time), es decir, un error en tiempo de ejecución en lugar de un error de análisis.

Ejemplo 1: Limitación de IRL que provoca un error de compilación

Este ejemplo da como resultado errores de compilación JIT debido a que faltan enumeradores.


ruletask T {
  algorithm = sequential;
  body = { R1, R2, R3, R4, R5, R6, R7, R8, R9 }
}

rule R1 {
  when {
    not MyObject();  // No enumerator, an error will occur
  }
  then {
  }
}

rule R2 {
  when {
    exists MyObject();  // No enumerator, an error will occur
  }
  then {
  }
}

rule R3 {
  when {
    collect MyObject() where (size() == 1);  // No enumerator, an error
                                                will occur
  }
  then {
  }
}

function Object getObject() {
  return new MyObject();
}

function Object[] getObjects() {
  Object objs = new Object[1];
  objs[0] = getObject();
  return objs;
}

rule R4 {
  when {
    not MyObject() from getObject();  // An enumerator, no error
  }
  then {
  }
} 

rule R5 {
  when {
    not MyObject() in getObjects();  // An enumerator, no error
  }
  then {
  }
} 

rule R6 {
  when {
    exists MyObject() from getObject();  // An enumerator, no error
  }
  then {
  }
} 

rule R7 {
  when {
    exists MyObject() in getObjects();  // An enumerator, no error
  }
  then {
  }
} 

rule R8 {
  when {
    collect MyObject() from getObject() where (size() == 1); 
    // An enumerator, no error
  }
  then {
  }
} 

rule R9 {
  when {
    collect MyObject() in getObjects() where (size() == 1);  
    // An enumerator, no error
  }
  then {
  }
}

Ejemplo 2: IRL que muestra limitaciones de construcción

A continuación se muestra un ejemplo con una construcción collect para mostrar el ámbito de los enlaces. Esto también se mantiene para not y exists . Este ejemplo también genera errores de compilación JIT debido al uso de construcciones no soportadas.


rule R10 {
  when {
    r:MyRootObject();
    c:collect MyObject(n:name; n.startsWith("ilog")) in r.getObjects(); 
    where (s:size(); s > 1);
  }
  then {
    out.println(r);  // correct
    out.println(c);  // correct
    out.println(s);  // correct
    out.println(n);  // error
  }
}