Algoritmo RetePlus

RetePlus é um modo de execução de regra baseado no algoritmo Rete. Ele depende da memória de trabalho e da agenda e suporta padrões negativos, notificação de objeto e objetos lógicos.

RetePlus é a extensão Decision Server baseada no algoritmo Rete. No modo RetePlus , a execução de regra usa um ambiente baseado em uma memória e agenda de trabalho.

Memória de trabalho e a agenda

No modo de execução RetePlus , o mecanismo de regras funciona com Memória de trabalho e uma Agenda, incluindo Instâncias de regras para execução quando as condições são atendidas

Memória ativa

No modo de execução do RetePlus , um mecanismo de regras no Decision Server é pareado com uma memória de trabalho. A memória de trabalho contém todos os objetos contidos no objeto Engine associado É possível modificar a memória de trabalho incluindo uma instrução na parte da ação de uma regra ou usando a Interface de Programação de Aplicativos (API). Assim, o motor de regra está ciente dos objetos que estão na memória de trabalho e de quaisquer objetos que estejam ligados a eles. O mecanismo de regra pode utilizar apenas objetos que sejam acessíveis a partir da memória de trabalho.

Programação

A agenda é onde Decision Server armazena as regras cujos padrões são todos correspondidos. Qualquer regra que entra na agenda é dito como instanciado, ele se torna uma instância de regra, veja Instâncias de regra.

A agenda armazena instâncias de regra que são elegíveis para serem rund. Se a agenda está vazia, a execução não tem efeito. Instâncias de regras colocadas na agenda são consideradas como elegíveis. Muitas vezes, na agenda, várias regras são elegíveis. Consequentemente, o motor de regra tem que ter alguma forma de decidir qual regra particular na agenda deve ser executada.

Na agenda, as instâncias de regras são ordenadas de acordo com três critérios que determinam qual regra deve ser executada primeiro. O controle de execução adicional é oferecido com a implementação de recursos mais complexos, veja Notificações de objetos.

Refração

Uma instância de regra que foi executada não pode ser reinserida na agenda se nenhum fato novo tiver ocorrido, ou seja, se nenhum dos objetos correspondido pela regra for modificado, ou se nenhum objeto novo for correspondido pela regra.

O princípio de refração reforça que apenas uma instância de regra é criada para um determinado tupla. Como a unidade de dados para um ciclo do motor é a memória de trabalho, o motor pode gravar facilmente todas as tuplas possíveis e verificar se há apenas uma instância de regra para cada tupla.

Por exemplo considere a seguinte ruleset:

class Person {
  Person(int age, boolean sick);
  boolean sick;
  int age;
}

rule incrementAge {
when {
  p: Person(!sick; age < 50);
} then {
  p.age += 1;
  update p;
}

rule cure {
when {
  p: Person(sick);
} then {
  p.sick = false;
  update p;
}

Se o objeto Person(18,true) estiver inserido na memória de trabalho, o princípio da refração produz o seguinte rastreio de execução:

  1. cure
  2. incrementAge

Você pode adicionar a propriedade repetível na regra incrementAge :

rule incrementAge {
 property com.ibm.rules.engine.repeatable=true;
when {
  p: Person(!sick; age < 50);
} then {
  p.age += 1;
}

Se o objeto Person(18,true) estiver inserido na memória de trabalho, a propriedade repetível produz o seguinte rastreio de execução:

  1. cure
  2. incrementAge
  3. incrementAge
  4. incrementAge
  5. ...
  6. incrementAge

    Até que a condição age < 50 seja falsa.

Regras repetíveis
Para quebrar o princípio da refração, você pode usar a propriedade de regra booleana com.ibm.rules.engine.repeatable. No mecanismo de decisão, você deve usar esta propriedade para marcar os conjuntos de regras que deseja ser repetível.
  • Quando uma regra não é repetível, o princípio da refração impede que uma instância de regra seja postada novamente para a agenda.
  • Quando uma regra é repetível, ela pode ser inserida novamente como uma instância de regra na agenda se uma modificação ocorrer contra seus objetos de condição.
Recência

Se duas instâncias de regras possuem a mesma prioridade, a regra que corresponde ao objeto mais recente (o objeto mais recentemente inserido, modificado ou retraído) é executada primeiro.

Prioridade e recência são usados para resolver conflitos quando várias instâncias de regras são candidatos à execução ao mesmo tempo. Se, após usar todos os métodos de resolução de conflitos especificados, várias instâncias de regras permaneceram candidíase, então o motor usa metarculas internas; isto garante que a mesma sequência de regras executando é sempre seguida, dadas as mesmas condições.

Exemplo de ordem de execução de regra

O exemplo de regra técnica a seguir mostra a ordem em que as regras são executadas:


rule init {
   when {
      angel();
   }
   then {
      insert clown();
      insert dascyllus();
   }
};
rule last {
   priority = -100;
   when {
      dascyllus();
   }
   then {
      System.out.println("last");
   }
};
rule first {
   priority = 100;
   when {
      angel();
      clown();
      dascyllus();
   }
   then {
      System.out.println("first");
   }
};
rule second {
   priority = 0;
   when {
      angel();
      dascyllus();
      clown();
   }
   then {
      System.out.println("second");
   }
};
rule third {
   priority = 0;
   when {
      angel();
      clown();
      dascyllus();
   }
   then {
      System.out.println("third");
   }
};

Suponhamos que o objeto angel tenha sido inserido a partir do aplicativo usando a API e, portanto, tenha sido inserido na memória de trabalho, e que executamos todas as regras que podem ser executadas.

Aqui está a ordem em que as regras são executadas:

  1. init regra: Como o objeto angel foi inserido a partir do aplicativo, a regra init é a única regra que pode ser executada. Ele insere os objetos clown e, em seguida, o objeto dascyllus na memória de trabalho. O objeto mais recente é, portanto, dascyllus.

  2. first regra: Esta regra é executada antes da regra second . O objeto mais recente correspondido por essas duas regras é o mesmo. No entanto, o primeiro objeto tem uma prioridade maior do que a segunda, o que determina sua ordem de execução.

  3. second regra: Esta regra é executada antes da regra third . O segundo e o terceiro regras têm a mesma prioridade, mas o objeto dascyllus é mais recente do que o objeto clown.

  4. third regra: Esta regra é executada antes da regra last . Embora o objeto dascyllus seja mais recente do que clown, a regra third tem uma prioridade maior do que a regra last .

  5. last regra.

Instâncias de Regra

Uma instância de regra é adicionada à agenda quando objetos na memória de trabalho satisfazem a condição parte dessa regra.

Consideremos a seguinte regra técnica:


rule rule1 {
   when {
      Fish(color == green; type == shark);
      Fish(type == trigger);
   }
   then {...}
};

As seguintes instâncias de regras serão colocadas em pauta:

Regra Regra Regra Regra
rule1(A,C®) rule1(A, D) rule1(B, C) rule1(B, D)

Neste exemplo, é possível ver que uma instância de regra é um conceito dinâmico: a instância de regra é produzida por qualquer combinação de objetos na memória de trabalho que correspondam aos padrões especificados na regra. Em contraste, uma regra é um conceito estático.

Padrões negativos

As condições de regra padrão podem ser descritas como existenciais, no sentido de que poderiam ser correspondidas por um ou vários objetos que realmente acontecem para existir. No modo de execução RetePlus há um conceito complementar conhecido como padrões negativos. Para expressar a não existência de um determinado objeto na memória de trabalho, situamos a palavra-chave not antes da condição do objeto, como mostrado aqui:


not Fish(type==eel);

Esse padrão negativo dá origem a uma correspondência bem-sucedida porque não há nenhum objeto que corresponda ao padrão positivo correspondente:


Fish(type==eel);

Inversamente, este padrão negativo:


not Fish(type==angel);

o not dá origem a uma correspondência bem-sucedida pela simples razão de que há um objeto que corresponde ao padrão positivo correspondente:


Fish(type==angel);

Notificações de objetos

Com o modo de execução RetePlus , você tem instruções para controlar operações individuais:

Inserção de objeto

A instrução insert permite que você crie um novo objeto e insira-o na memória de trabalho. Esta palavra-chave é seguida pelo nome da classe e pelos valores dos atributos do objeto a ser criado.

Aqui está um exemplo que envolve a criação de um novo objeto Course cujos atributos department e number levam os valores History e 324, respectivamente:


insert Course(History,324);

Existem duas possibilidades para a forma como uma operação insert é processada:

  • O objeto já está na memória de trabalho. Nesse caso, a operação de inserção é equivalente a uma atualização.

  • O objeto não está na memória de trabalho. Nesse caso, o objeto é inserido na memória de trabalho e o daemon de inserção da classe correspondente e suas superclasses, se houver, é chamado, e a agenda é atualizada.

Retração de objeto

A instrução retract permite remover da memória de trabalho um objeto que está ligado a uma variável de regra.

No exemplo a seguir, o primitivo retract remove o objeto ligado à variável ?c :


rule RemoveCourse {
   when {
      ?c: Course(department == History; number == 254);
   }
   then {
      retract ?c;
   }
};

O daemon retract da classe correspondente, se houver, é chamado, e a agenda é atualizada em conformidade. A retrair um objeto da memória de trabalho pode fazer com que um objeto lógico perca uma ou várias de suas justificativas.

Atualização de objeto

Quando um objeto é modificado por Java™, as modificações não são vistas pelo Decision Server Isso significa que os dados mantidos pelo Decision Server não serão consistentes com o novo conteúdo do objeto modificado

Para evitar inconsistências, a instrução update deve ser chamada para tal objeto. Essa instrução permite que o Decision Server atualize suas estruturas internas de acordo com o novo conteúdo do objeto modificado

Na regra a seguir, a primeira ação modifica o atributo number. A primitiva update é chamada para informar Decision Server que o objeto foi modificado.


rule NumberingUpdate {
   when {
      ?c: Course(department == "history"; number > 300);
   }
   then {
      ?c.updateNumbering(); // This call modifies ?c 
      update ?c;
   }
};
Importante:

Se você não usar modify, deverá usar a primitiva update para informar Decision Server que os objetos foram modificados. Esquecer de notificar o Decision Server de modificações leva a estados inconsistentes.

Operação de rede

A rede RetePlus pode minimizar o número de regras e condições:

Operação de rede RetePlus

A rede RetePlus indexa regras para minimizar o número de regras e condições que precisam ser avaliadas sempre que a memória de trabalho for alterada. A rede minimiza o número de avaliações compartilhando testes entre regras e propagando mudanças incrementalmente. Quando todos os testes foram concluídos, a rede designa uma regra.

Na maioria dos casos, executar uma regra modifica a memória de trabalho. Os objetos na memória de trabalho referenciados por essas regras podem ser inseridos, removidos e modificados. A rede processa as alterações inferidas pela execução da regra e produz um novo conjunto de regras a serem executadas.

Quando ocorre uma mudança na memória de trabalho, duas coisas podem acontecer, dependendo da natureza da mudança:

  • Se houver uma inserção de um objeto na memória de trabalho (positiva), a regra pode ser executada.

  • Se houver a remoção de um objeto da memória de trabalho (negativa), a regra deve ser retirada da agenda. A agenda é o local onde o atual conjunto de regras a ser executado é mantido.

Esse processo continua ciclicamente até que não haja mais instâncias de regras deixadas em pauta.

Nota:

Uma condição not retorna true para uma condição simples se a memória de trabalho não contém nenhum objeto que possa coincidem com a condição.

Exemplo de uma rede RetePlus

Para ilustrar nossa descrição de uma rede RetePlus , devemos usar uma regra filter trivial, gravada na linguagem de regra que se refere a classes denominadas A, Be C:


rule filter {
   when {
      A (a1==3; ?x:a2);
      B (b1==2; ?y:b2; b3==?x);
      C (c1==?y);
   }
   then {
      System.out.println("filter");
   }
}

Os atributos de classe são os seguintes:

  • A classe A tem dois atributos, denominados a1 e a2.

  • A classe B possui três atributos, denominados b1, b2e b3.

  • A classe C possui um único atributo, denominado c1.

Suponha que a memória de trabalho contenha os seguintes objetos:


A( a1=3 a2=10 )
B( b1=2 b2=4 b3=10 )
B( b1=2 b2=7 b3=10 )
C( c1=4 )

Estrutura de rede RetePlus

Uma rede RetePlus pode ser representada como um gráfico composto por três zonas:

Árvore de discriminação

Uma árvore de discriminação é um processo de correspondência de padrões que faz testes. Esses testes são representados por formas de losango no topo da rede. Os testes dizem respeito às classes de objetos e aos valores de seus atributos. A entrada para esta árvore consiste em tokens representando cada um dos objetos atuais na memória de trabalho.

Quando o padrão lida com apenas um objeto e seus atributos, diz-se que se trata de um teste de discriminação. Quando é uma combinação, ela é chamada de junção; estas aparecem na parte inferior do gráfico.

Nós Alfa

Um nó alfa é formado no nível seguinte da rede, para cada token que passa nos testes da árvore de discriminação. Cada nó é composto por um ou vários tokens, representados por retângulos encurralados redondos (há três nós alfa na figura). Um nó alfa contém dois tokens de classe B. Os outros dois nós contêm apenas um token de classe cada-Um-classe e tokens C-class, respectivamente.

Testes e tuplas

A terceira zona da rede combina com tokens de várias classes de objetos. Os nós resultantes são conhecidos como tuplas, que serão feitos de vários tokens. O teste de igualdade entre atributos a2 e b3 dá origem a um nó composto de dois pares de tokens, e o teste entre atributos b2 e c1 filtra então um triplet de tokens. Em uma rede RetePlus , geralmente nos referimos a tuplas desse tipo como nós de junção .

Adição de objeto

Para demonstrar ainda mais essa ideia da rede RetePlus , suponha que um objeto extra seja inserido na memória de trabalho.. O objeto adicionado é da classe C, e o valor de seu atributo c1 é 7.


C( c1=7 )

Nessa fase, quando todos os testes dos nós são realizados, apenas o terceiro teste C (c1==?y); (class of object = C) está satisfeito. Os testes dos nós filhos continuam conforme o token descende através da rede.

Aqui, não há nódulo infantil na árvore de discriminação. Por essa razão, o objeto é armazenado diretamente no nódulo alfa.

Quando o token atinge o segundo nó de junção B (b1==2; ?y:b2; b3==?x), o teste é realizado entre cada objeto B dos pares armazenados ao lado da memória do nó de junção e do objeto C contido no token que acabou de chegar no nó de junção. O teste é satisfeito para o objeto B do segundo par. Podemos, portanto, proceder e criar um triplet formado pelo segundo par e o objeto no token.

Ao formar esse triplet temos, de fato, decrescido todo o caminho através da rede, e uma nova instância da regra filter pode ser executada.

Remoção de objetos

Suponhamos que agora removemos o objeto que acabamos de adicionar à memória de trabalho.

O progresso do token através da árvore de discriminação é o mesmo que no caso da adição de objetos, mas a chegada do token negativo no nódulo alfa provoca a remoção do objeto contido no token.

Quando o token chega ao segundo nó de junção, todos os triplets que contêm o objeto no token são removidos e o token continua sua progressão através da rede.

Como no exemplo de adição de objeto, o nó de regra é atingido. A instância da regra filter cujos objetos satisfazem as condições correspondentes aos objetos no token são retirados da agenda.