CLARION (Connectionist Learning with Adaptive Rule Induction ON-line) is a project investigating fundamental structures of the human mind.
Neste experimento utilizamos o CLARION para controlar uma criatura artificial no WorldServer3D, esta atividade é um complemento das Aulas 8 e 9.
O experimento consiste em desenvolver um sistema de controle (mente artificial) para a criatura do WorldServer3D utilizando o CLARION, de modo análogo ao experimento (vide Aula 7) utilizando o SOAR. Nosso desafio será semelhante ao desafio que foi proposto na implementação com o Soar.
A criatura deve obter sua meta de aquisição de jóias a partir de seu leaflet, e buscar de maneira mais rápida todas as pedras designadas e parar ao fim da tarefa. Disponibilizamos um arquivo compactado dos executaiveis [ aqui ] e outro dos fontes [ aqui ]. Para a execução via java-webstart acione ws3d e em seguida demo-clarion.
Duas criaturas devem competir para buscar as jóias que lhes foram delegadas. Uma deverá ser controlado pelo Soar e outra pelo CLARION. Não realizamos esta parte da atividade.
O detalhamento do desenvolvimento dos dois testes segue nas seções abaixo. Porém, antes de iniciarmos a resolução propriamente dita apresentamos rapidamente o esquema do pacote Demo-CLARION (WS3D e Demo) disponibilizado no enunciado.
A simulação Demo-CLARION utiliza o WorldServer3D (WS3D) como arena para o agente CLARION. O agente percorre a arena (anda em linha reta, orientado pela direção da visão frontal: GO_AHEAD
) evitando colidir com as paredes (faz uma rotação, sempre no sentido horário: ROTATE_CLOCKWISE
). A Figura 1 mostra o cenário da simulação do Demo-CLARION (Demo). Do lado esquerdo da arena do WS3D temos na parte superior: o terminal exibindo a conexão com o WS3D e na parte inferior: os projetos associados ao DemoCLARION:
Figura 1. Cenário do Demo CLARION |
Na Aula 7, apresentamos a estrutura e funcionalidades do WS3D. Desse modo, nesta apresentação sobre o Demo-CLARION a parte referente ao WS3D será menos detalhada. Por outro lado, a apresentação da estrutura e funcionalidades do projeto principal Demo-CLARION, vide estrutura da solução (lista dos projetos na Figura 2, destaque em vermelho, lado esquerdo da figura), será um pouco mais detalhada (o suficiente para realizar esta atividade). Comentários adicionais serão feitos ao longo do desenvolvimento dos testes propostos.
Figura 2. Projetos do Demo-CLARION |
ClarionDEMO
contém a classe raiz, usa os outros dois projetos para estabelecer a comunicação entre o WS3D e o agente CLARION.WorldServerLibrary
mantém as classes de comunicação (p.ex., envio de comandos) caracteriza a interface do WS3D.WorldServerAgent
contém a thread do agente CLARION que atua no mundo WS3D via CLARION. O laço de execução da simulação é mantida neste projeto.Iniciamos a apresentação comentando o Main.cs
, a codificação abaixo mostra apenas o esquema:
using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading; using ClarionSimulation; using WorldServerLibrary; using WorldServerLibrary.Model; using WorldServerLibrary.Exceptions; namespace ClarionDEMO { class MainClass { #region properties private WorldServer worldServer = null; private ClarionAgent agent; String creatureId = String.Empty; String creatureName = String.Empty; double prad = 0; #endregion #region constructor public MainClass() { Console.WriteLine ("Clarion Demo V0.4"); agent = new ClarionAgent(); agent.OnNewVisualSensorialInformation += new InputVisualSensorialInformationEventHandler(agent_OnNewVisualSensorialInformation); agent.OnNewExternalActionSelected += new OutputActionChunkEventHandler(agent_OnNewExternalActionSelected); try { worldServer = new WorldServer("localhost", 4011); String message = worldServer.Connect(); if (worldServer != null && worldServer.IsConnected) { . . . // Veja continuação no bloco abaixo [ aqui ] } } . . . tratamento de exceções } #endregion #region Methods public static void Main (string[] args) { new MainClass(); } IList<Thing> agent_OnNewVisualSensorialInformation() { IList<Thing> response = null; if (worldServer != null && worldServer.IsConnected) { . . . } return response; } void agent_OnNewExternalActionSelected(ClarionAgentActionType externalAction) { Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); // Fixa o separador decimal: "." if (worldServer != null && worldServer.IsConnected) { switch (externalAction) { . . . } } } #endregion } }
No esquema acima vemos o conjunto de bibliotecas utilizadas, as duas últimas (ClarionSimulation
e o WorldServerLibrary
) são as que servem de base para essa atividade. Após a declaração dos elementos principais da simulação (worldServer
e agent
) é atribuído ao agente CLARION um sensor visual e um modo de atuar no mundo. Com isso o agente pode ser conectado ao WS3D (com o devido tratamento de exceção, caso ocorra alguma falha na tentativa de conexão). Estabelecida a coneção o agente CLARION pode atuar no mundo. O trecho de código abaixo mostra a inicialização do mundo (com quatro paredes) e a ativação do agente (agent.Run()
).
. . .
namespace ClarionDEMO {
class MainClass {
. . .
#region constructor
. . .
try { // Parte da codificação do bloco acima [ aqui ]
worldServer = new WorldServer("localhost", 4011);
String message = worldServer.Connect();
if (worldServer != null && worldServer.IsConnected) {
Console.Out.WriteLine ("[SUCCESS] " + message + "\n");
worldServer.NewCreature(400, 200, 0, out creatureId, out creatureName);
worldServer.NewBrick(4, 747, 2, 800, 567);
worldServer.NewBrick(4, 50, -4, 747, 47);
worldServer.NewBrick(4, 49, 562, 796, 599);
worldServer.NewBrick(4, -2, 6, 50, 599);
if (!String.IsNullOrWhiteSpace(creatureId)) {
worldServer.SendStartCamera(creatureId);
worldServer.SendStartCreature(creatureId);
}
Console.Out.WriteLine("Creature created with name: " + creatureId + "\n");
agent.Run();
Console.Out.WriteLine("Running Simulation ...\n");
}
}
catch (WorldServerInvalidArgument invalidArtgument) {
Console.Out.WriteLine(String.Format("[ERROR] Invalid Argument: {0}\n",
invalidArtgument.Message));
}
catch (WorldServerConnectionError serverError) {
Console.Out.WriteLine(String.Format("[ERROR] Is is not possible to connect to server: {0}\n",
serverError.Message));
}
catch (Exception ex) {
Console.Out.WriteLine(String.Format("[ERROR] Unknown Error: {0}\n", ex.Message));
}
}
#endregion
. . .
}
O trecho de codificação abaixo mostra que as ações do agente (ações visíveis no mundo) se restringem a mover-se para a frente ou rotacionar de acordo com a informação que recebe do sensor visual.
. . . namespace ClarionDEMO { class MainClass { . . . #region Methods // Parte da codificação do bloco acima [ aqui ] public static void Main (string[] args) { new MainClass(); } IList<Thing> agent_OnNewVisualSensorialInformation() { IList<Thing> response = null; if (worldServer != null && worldServer.IsConnected) { response = worldServer.SendGetCreatureState(creatureName); // Veja em WorldServerLibrary prad = (Math.PI / 180) * response.First().Pitch; while (prad > Math.PI) prad -= 2 * Math.PI; while (prad < - Math.PI) prad += 2 * Math.PI; } return response; } void agent_OnNewExternalActionSelected(ClarionAgentActionType externalAction) { Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); if (worldServer != null && worldServer.IsConnected) { switch (externalAction) { case ClarionAgentActionType.DO_NOTHING: // Do nothing as the own value says break; case ClarionAgentActionType.ROTATE_CLOCKWISE: // Rotaciona para evitar colisão double newprad = prad + Math.PI/1000; // está associada a while (newprad > Math.PI) newprad -= 2 * Math.PI; // NewExternalActionChunk while (newprad < - Math.PI) newprad += 2 * Math.PI; // declarada no ClarionAgent.cs worldServer.SendSetAngle(creatureId, 0, 0, newprad); break; case ClarionAgentActionType.GO_AHEAD:: // Move para frente ... worldServer.SendSetAngle(creatureId, 1, 1, prad); // também está ssociada a break; // NewExternalActionChunk default: break; } } } #endregion . . . }
A informações do sensor visual são tratas pela classe ClarionAgent
, no namespace
ClarionSimulation
(veja em ClarionAgent.cs
no projeto WorldServerAgent
. Isto é, as ações rotacionar e mover para frente são tratadas na classe ClarionAgent
. O trecho de código abaixo mostra como ocorre parte do tratamento: estabelece a forma da representação das informações sensoriais capturadas, define quais as ações do agente, as informações iniciais, descreve as ocorrências inicial e final do ciclo cognitivo e, por fim, fornece as ExternalActionChunks
associadas às ações do agente.
namespace ClarionSimulation { // As informações visuais (na forma de lista) são fornecidas no início de cada ciclo cognitivo. // Este delegate está associado ao SendGetCreatureState (veja em WorldServerLibrary). // Armazena (recebe) o estado atual do agente CLARION public delegate IList<Thing> InputVisualSensorialInformationEventHandler(); // As ações externas escolhidas são disparadas ao fim de cada ciclo cognitivo // Este delegate está associado ao envio de comandos: o agete o cria para envio de comandos // Veja um exrmplo do esquema de um comando em WorldServerLibrary. public delegate void OutputActionChunkEventHandler(ClarionAgentActionType externalAction); // Abaixo estão todas as ações que o agente pode executar (similar ao tratamento feito no Soar). public enum ClarionAgentActionType { DO_NOTHING, ROTATE_CLOCKWISE, GO_AHEAD } public class ClarionAgent { #region Constants // Captura informação do sensor visual private String SENSOR_VISUAL_DIMENSION = "VisualSensor"; // Captura uma das paredes (a frontal) private String DIMENSION_WALL_AHEAD = "WallAhead"; #endregion . . . #region Agent // O agente CLARION private Clarion.Framework.Agent CurrentAgent; // Para cada ciclo cognitivo, o agente atualiza as informações sensoriais correntes public event InputVisualSensorialInformationEventHandler OnNewVisualSensorialInformation; // Para cada ciclo cognitivo, o agente seleciona uma ação public event OutputActionChunkEventHandler OnNewExternalActionSelected; #endregion #region Perception Input /// Perception input to indicates a wall ahead private DimensionValuePair InputWallAhead; #endregion #region Action Output /// Ações externas: rotação e mover para frente private ExternalActionChunk OutputRotateClockwise; private ExternalActionChunk OutputGoAhead; #endregion #region Constructor public ClarionAgent() { // Inicializa: o agente, as informações capturadas e as ações (rotação e mover p/ frente) CurrentAgent = World.NewAgent("Current Agent"); InputWallAhead = World.NewDimensionValuePair(SENSOR_VISUAL_DIMENSION, DIMENSION_WALL_AHEAD); OutputRotateClockwise = World.NewExternalActionChunk(ClarionAgentActionType.ROTATE_CLOCKWISE.ToString()); OutputGoAhead = World.NewExternalActionChunk(ClarionAgentActionType.GO_AHEAD.ToString()); // Cria a thread para a simulação runThread = new Thread(RunThread); Console.WriteLine("Agent started"); } #endregion . . . }
O último trecho do código acima cria a thread para a simulação, o laço principal está descrito na codificação abaixo:
namespace ClarionSimulation { . . . #region Public Methods // Executa a simulação no WS3D public void Run() { Console.WriteLine ("Running ..."); // Ativa o agente CLARION if (runThread != null && !runThread.IsAlive) { SetupAgentInfraStructure(); if (OnNewVisualSensorialInformation != null) { // Dispara a thread da simulação runThread.Start(null); } } } #endregion . . . }
O ciclo cognitivo é descrito na codificação abaixo, antes do laço do ciclo são declaradas as Fixed Rules (ruleGoAhead
e ruleAvoidCollisionWall
), veja maiores comentários no tópico ACS da Aula 8.
namespace ClarionSimulation { . . . #region Delegate Methods #region Fixed Rules private double FixedRuleDelegateToAvoidColissionWall(ActivationCollection currentInput, Rule target) { // Estabelece a lógica para o avoid_collision, a ativação ocorre sempre que houver um // obstáculo num perímetro mínimo return ((currentInput.Contains(InputWallAhead, CurrentAgent.Parameters.MAX_ACTIVATION))) ? 1.0 : 0.0; } private double FixedRuleDelegateToGoAhead(ActivationCollection currentInput, Rule target) { // Estabelece a lógica do go_ahead. Note que o valor de ativação é o contrário da fixed // rule acima. Estas duas funções são reguladas pela SupportCalculator (vide bloco abaixo). return ((currentInput.Contains(InputWallAhead, CurrentAgent.Parameters.MIN_ACTIVATION))) ? 1.0 : 0.0; } #endregion #region Run Thread Method private void RunThread(object obj) { Console.WriteLine("Starting Cognitive Cycle ... press CTRL-C to finish !"); // Ciclo cognitivo: grosso modo, mantém a seqüênciaA
gent.Perceive(si)
, //ExternalActionChunk chosen = Agent.GetChosenExternalAction(si)
. // O ciclo tem início com a captura das informações sensoriais while (CurrentCognitiveCycle != MaxNumberOfCognitiveCycles) { // Captura os dados sensoriais corrente, interpreta-os e os torna informação perceptual IList<Thing> sensorialInformation = OnNewVisualSensorialInformation(); SensoryInformation si = MakePerceptionFromSensorialInput(sensorialInformation); CurrentAgent.Perceive(si); // si é objeto do tipo SensoryInput com informação sensorial. // (1) escolhe uma ação, (2) pega a ção selecionada e (3) executa ExternalActionChunk chosen = CurrentAgent.GetChosenExternalAction(si); String actionLabel = chosen.LabelAsIComparable.ToString(); ClarionAgentActionType actionType = (ClarionAgentActionType)Enum.Parse(typeof(ClarionAgentActionType), actionLabel, true); if (OnNewExternalActionSelected != null) { OnNewExternalActionSelected(actionType); } // incremento do número de ciclos cognitivos e tempo para o agente terminar sua tarefa CurrentCognitiveCycle++; if (TimeBetweenCognitiveCycles > 0) { Thread.Sleep(TimeBetweenCognitiveCycles); } } } #endregion #endregion . . . }
Finalmente, no trecho de código abaixo temos a configuração da infra-estrutura do agente CLARION. Evidentemente, a base é o subsistema ACS (vide Aula 8).
namespace ClarionSimulation { . . . #region Setup Agent Methods //Configura a infra-estrutura (ACS, NACS, MS e MCS) do agente. Abaixo temos o subsistema ACS private void SetupAgentInfraStructure() { SetupACS(); } private void SetupMS() { //RichDrive } // Configuração do ACS private void SetupACS() { // Cria as regras para "Colission-Wall" e "Go Ahead" SupportCalculator avoidCollisionWallSupportCalculator = FixedRuleDelegateToAvoidColissionWall; SupportCalculator goAheadSupportCalculator = FixedRuleDelegateToGoAhead; FixedRule ruleAvoidCollisionWall = AgentInitializer.InitializeActionRule(CurrentAgent, FixedRule.Factory, OutputRotateClockwise, avoidCollisionWallSupportCalculator); FixedRule ruleGoAhead = AgentInitializer.InitializeActionRule(CurrentAgent, FixedRule.Factory, OutputGoAhead, goAheadSupportCalculator); // Agrega as regras ao agente (no ACS) CurrentAgent.Commit(ruleAvoidCollisionWall); CurrentAgent.Commit(ruleGoAhead); // Desativa a regras de refinamento CurrentAgent.ACS.Parameters.PERFORM_RER_REFINEMENT = false; // Estabelece a forma de seleção: probabilística CurrentAgent.ACS.Parameters.LEVEL_SELECTION_METHOD = ActionCenteredSubsystem.LevelSelectionMethods.STOCHASTIC; // A seleção da ação é fixa, definida acima. CurrentAgent.ACS.Parameters.LEVEL_SELECTION_OPTION = ActionCenteredSubsystem.LevelSelectionOptions.FIXED; // Estabelece os valores probabilísticos CurrentAgent.ACS.Parameters.FIXED_FR_LEVEL_SELECTION_MEASURE = 1; CurrentAgent.ACS.Parameters.FIXED_IRL_LEVEL_SELECTION_MEASURE = 0; CurrentAgent.ACS.Parameters.FIXED_BL_LEVEL_SELECTION_MEASURE = 0; CurrentAgent.ACS.Parameters.FIXED_RER_LEVEL_SELECTION_MEASURE = 0; } // O agente interpreta os dados sensoriais em informação (conhecimento) // <param name="sensorialInformation"> Informação fornecida pelo mundo /// <returns> Informação sensória private SensoryInformation MakePerceptionFromSensorialInput(IList<Thing> sensorialInformation) { // Informação sensorial corrente SensoryInformation si = World.NewSensoryInformation(CurrentAgent); // Detecta se há uma parede à frente Boolean wallAhead = sensorialInformation.Where(item => (item.CategoryId == Thing.CATEGORY_BRICK && item.DistanceToCreature <= 61)).Any(); double wallAheadActivationValue = wallAhead ? CurrentAgent.Parameters.MAX_ACTIVATION : CurrentAgent.Parameters.MIN_ACTIVATION; si.Add(InputWallAhead, wallAheadActivationValue); return si; } #endregion . . . }
Grosso modo, é esse o esquema do agente CLARION: começa na classe SensoryInput
(pega o estado do mundo via OnNewVisualSensorialInformation()
) e cria objetos que funcionam como sensory input (a SensoryInformation
: entrada do ciclo cognitivo via MakePerceptionFromSensorialInput()
). Os objetos correspondem aos DimensionValuePair
, por exemplo, o InputWallAhead
cuja ativação é definida pelo MakePerceptionFromSensorialInput()
. A percepção do SensoryInformation
(o entendimento), que ocorre via CurrentAgent.Perceive(si)
, permite ao agente buscar uma ação externa (via CurrenteAgent.GetChosenExternalAction(si)
) e convertê-la em comando para a performance do agente no ambiente WS3D (via OnNewExternalActionSelected()
, isto é, termina na classe ExternalActionChunk
que cria um objeto para cada ação possível). Esse esquema está resumido na Figura 3, já apresentada na Aula 8.
Figura 3: Estrutura de uma aplicação básica do CLARION: |
A seguir, expomos de modo muito breve um trecho do código do WorldServer.cs
que mostra uma parte da interface do agente com o WS3D. A codificação abaixo exibe dois exemplos do esquema de troca de mensagens: uma via comandos (Creature Command Methods
, por exemplo o setGoTo
) e outra pelo estado corrente do agente (via SendGetCreatureState
).
. . . namespace WorldServerLibrary { public class WorldServer:IDisposable{ . . . #region Creature Command Methods // Esta estrutura está associada ao delegate declarado no ClarionSimulation public string SendSetGoTo(string creatureId, double vr, double vl, double x, double y) { String response = String.Empty; try { // Prepara a mensagem StringBuilder builder = new StringBuilder(); builder.Append("setGoTo "); builder.Append(creatureId); builder.Append(" "); builder.Append(vr); builder.Append(" "); builder.Append(vl); builder.Append(" "); builder.Append(x); builder.Append(" "); builder.Append(y); // Envia a mensagem SendMessage(builder.ToString()); // Lê a resposta response = ReadMessage(); } . . . // Envia o status do agente -- veja no MainClass do ClarionDEMO // Esta estrutura está associada ao delegate declarado no ClarionSimulation public List<Thing> SendGetCreatureState(string creatureId) { List<Thing> returnDic = null; try { // Prepara a mensagem StringBuilder builder = new StringBuilder(); builder.Append("getcreaturestate "); builder.Append(creatureId); // Envia a mensagem SendMessage(builder.ToString()); // Lê a resposta String response = ReadMessage(); // Parser da resposta returnDic = ParseGetCreatureStateResponse(response, new String[]{"||"} ); } . . . } }
Utilizamos o DemoCLARION como base para o desenvolvimento do Teste 1.
Conforme discussões no laboratório, é necessário efetuar alguns ajustes no WS3D para o desenvolviemtno da Atividade: Teste 1. O Eduardo Jucá fez esses ajustes e disponibilizou uma versão jnlp
funcional do WS3D [ aqui ] com seu respectivo código fonte [ aqui ]. Utilizamos nesta atividade a versão do Eduardo Jucá.
Neste teste, o agente (a criatura no WS3D) deve:
Assim como no experimento do Soar-WS3D (Aula 7), o agente CLARION deve coletar jóias da arena de acordo com os leaflets que recebe. Como o agente gasta energia ao longo do tempo, ele deve fazer recargas de energia (consumir alimentos) sempre que o nível de energia chegar a um determinado limite. A estrutura do bot é como segue:
A partir dessa descrição do bot estabelecemos uma estrutura CLARION cujo comportamento satisfaça o comports desejado.
Na estrutura aqui proposta, o bot possui duas características que podem ser consideradas primárias:
Nessa implementação, o bot "nasce sabendo" identificar os objetos que compõem o ambiente: comida, parede e jóias. O comportamento referente à coleta de jóias, de acordo com os leaflets, está associado a uma forma de conhecimento explícito, representado por regras e chunks. Nesse experimento, os módulos meta-cognitivos estão associados somente aos drives relacionados às características primárias.
O comportamento referente à captura de jóias está associado ao conhecimento explítico mantido no nível superior (top level) de cada subsistema que compõe a estrutura do bot CLARION, formado por regras e chunks. As regras incluem as action rules (ACS) e as associative rules (NACS). Os chunks estão envolvidos na representação dessas regras, descrevendo as condições e as conclusões das regras, são coleções de DV-pares que representam ou condições ou ações (no top level). Desse modo, a partir das entradas sensoriais e das ações são criadas estruturas internas do ACS que serão tratadas no topo-level (por regras), isto é, as ações do agente são determinadas por FixedRules
, veja [ aqui ].
A seguir expomos trechos das codificações das duas partes: da que controla o comportamento do agente em relação às suas necessidades primária e da que determina as ações do agente em relação à coleta das jóias.
Esquema do controle do comportamento em relação às necessidades primárias:
Para esta parte seguimos o tutorial Intermediate MS and MCS Setup, com especial atenção ao uso efetivo de DRIVES
:
"Drives use factors from both the internal and external state information (located within the SensoryInformation object) to transform them into a “drive strength” (i.e., the amount of activation for a drive). However, without mechanisms to process these drive strengths and make decisions based upon them, the drives alone will have little effect on the overall operation of an agent. Therefore, we rely on meta-cognitive modules to make decisions based upon these drives strengths (as well as other factors) and to initiate a variety of internally-directed meta-cognitive actions."
Iniciamos declarando um agente cuja estrutura subjacente é a do framework CLARION:
. . . #region Agent // The agent private Clarion.Framework.Agent CurrentAgent; // For each cognitive cycle, this event will be called in order to the agent receives the // current sensorial information public event InputVisualSensorialInformationEventHandler OnNewVisualSensorialInformation; // For each cognitive cycle, this event will be called when the agent selects one action public event OutputActionChunkEventHandler OnNewExternalActionSelected; private Creature creature = null; #endregion Agent . . .
Definimos alguns elementos básicos (constantes e pares DV) e seguimos com a construção do agente:
. . . public class ClarionAgent { #region Constants // Constants: represents the "visual sensor dimension" and objects ahead private String SENSOR_VISUAL_DIMENSION = "VisualSensor"; private String DIMENSION_FOOD_AHEAD = "FoodAhead"; private String DIMENSION_WALL_AHEAD = "WallAhead"; // Food stimulus: minimum fuel level private double FUEL_MIN = 300.0; // Wall avoidance stimulus: minimum distance private double DIST_MIN = 60.0; . . . #endregion Constants . . . } . . .
. . . #region Simulation . . . //Environment Information about food: Input/Output DimensionValuePair InputFood; DimensionValuePair InputWall; ExternalActionChunk OutputEatFood; ExternalActionChunk OutputAvoidWall; // Goal Chunk GoalChunk GoalEatFood = World.NewGoalChunk(EAT); // Vide ações do agente em ClarionAgentActionType GoalChunk GoalAvoidWall = World.NewGoalChunk(ROTATE_CLOCKWISE); // Idem #endregion Simulation . . .
Aqui fazemos uma observação, em parte exposta na Aula 8, cada drive no MS está associado a metas. Os drive strengths inflenciam na determinação dos goal strengths, cada drive strenght i é uma função linear: dsi = (ai )(stimulusi)(deficiti) + (bi ), com ai e bi parâmetros de influência sobre o estímulo corrente e o déficit percebido. Esse mecanismo está embutido no GoalSelectionEquation
.
. . . #region Constructor public ClarionAgent() { // Initialize the agent CurrentAgent = World.NewAgent("Marvin The Martian"); . . . // ACS Module: Goals SimplifiedQBPNetwork net = AgentInitializer.InitializeImplicitDecisionNetwork(CurrentAgent, SimplifiedQBPNetwork.Factory); // Add inputs and output to QBPNet net.Input.Add(InputFood); net.Input.Add(GoalEatFood); net.Input.Add(InputWall); net.Input.Add(GoalAvoidWall); net.Output.Add(OutputEatFood); net.Output.Add(OutputAvoidWall); // Learning rate, agent commit with QBPNet and rule refinament for action rule net.Parameters.LEARNING_RATE = 1; CurrentAgent.Commit(net); RefineableActionRule.GlobalParameters.INFORMATION_GAIN_OPTION = RefineableActionRule.IGOptions.PERFECT; // MS Module: Drives and Drive Equation:: Food and Wall drive. Also, drive equation. // FoodDrive type: BAS drive, WallDrive type: Bis drive FoodDrive foodDrive = AgentInitializer.InitializeDrive(CurrentAgent, FoodDrive.Factory, .5); AvoidingPhysicalDangerDrive wallDrive = AgentInitializer.InitializeDrive(CurrentAgent, AvoidingPhysicalDangerDrive.Factory, .5); DriveEquation foodEquation = AgentInitializer.InitializeDriveComponent(foodDrive, DriveEquation.Factory); DriveEquation wallEquation = AgentInitializer.InitializeDriveComponent(wallDrive, DriveEquation.Factory); foodDrive.Commit(foodEquation); CurrentAgent.Commit(foodDrive); wallDrive.Commit(wallEquation); CurrentAgent.Commit(wallDrive); // MCS Module: Goal selection module GoalSelectionModule gsm = AgentInitializer.InitializeMetaCognitiveModule(CurrentAgent, GoalSelectionModule.Factory); // Goal Selection: combine goal strengths GoalSelectionEquation gse = AgentInitializer.InitializeMetaCognitiveDecisionNetwork(gsm, GoalSelectionEquation.Factory); // Make goal recommendations for the goal structure based gse.Input.Add(foodDrive.GetDriveStrength()); gse.Input.Add(wallDrive.GetDriveStrength()); // Goal Selection Equation: provide information to GoalSelectionModule GoalStructureUpdateActionChunk goalActFood = World.NewGoalStructureUpdateActionChunk(); GoalStructureUpdateActionChunk goalActWall = World.NewGoalStructureUpdateActionChunk(); // update the goals in MS subsystem goalActFood.Add(GoalStructure.RecognizedActions.SET_RESET, GoalEatFood); goalActWall.Add(GoalStructure.RecognizedActions.SET_RESET, GoalAvoidWall); //Add output, set relevance and commit gse.Output.Add(goalActFood); gse.Output.Add(goalActWall); gsm.SetRelevance(goalActFood, foodDrive, 1); gsm.SetRelevance(goalActWall, wallDrive, 1); gsm.Commit(gse); CurrentAgent.Commit(gsm); CurrentAgent.MS.Parameters.CURRENT_GOAL_ACTIVATION_OPTION = MotivationalSubsystem.CurrentGoalActivationOptions.FULL; . . . } . . .
O próximo trecho refere-se à construção da percepção do agente referente aos objetos food e wall: conversão dos dados sensoriais em informação:
. . . private SensoryInformation MakePerceptionFromSensorialInput(IList<Thing> sensorialInformation) { // New sensory information SensoryInformation si = World.NewSensoryInformation(CurrentAgent); // Stimulus for foodDrive and wallDrive si[typeof(FoodDrive), FoodDrive.MetaInfoReservations.STIMULUS] = creature.Fuel < FUEL_MIN ? 1 : 0; Boolean wallAhead = sensorialInformation.Where(item => (item.CategoryId == Thing.CATEGORY_BRICK && item.DistanceToCreature <= DIST_MIN)).Any(); si[typeof(AvoidingPhysicalDangerDrive), AvoidingPhysicalDangerDrive.MetaInfoReservations.STIMULUS] = wallAhead ? 1 : 0; //creature.Fuel<300?CurrentAgent.Parameters.MAX_ACTIVATION:CurrentAgent.Parameters.MIN_ACTIVATION; double foodActivationValue = creature.Fuel < FUEL_MIN ? CurrentAgent.Parameters.MAX_ACTIVATION : CurrentAgent.Parameters.MIN_ACTIVATION; double wallActivationValue = wallAhead ? CurrentAgent.Parameters.MAX_ACTIVATION : CurrentAgent.Parameters.MIN_ACTIVATION; si.Add(InputFood, foodActivationValue); si.Add(InputWall, wallActivationValue); return si; } . . .
Finalmente, o método para executar a thread. O trecho abaixo contém somente a parte referente às ações (EAT
e ROTATE_CLOCKWISE
) sobre fome e evitar colisões:
. . . namespace ClarionSimulation { // As informações visuais (na forma de lista) são fornecidas no início de cada ciclo cognitivo. // Armazena (recebe) o estado atual do agente CLARION public delegate IList<Thing> InputVisualSensorialInformationEventHandler(); // As ações externas escolhidas são disparadas ao fim de cada ciclo cognitivo // Este delegate está associado ao envio de comandos: o agete o cria para envio de comandos public delegate void OutputActionChunkEventHandler(ClarionAgentActionType externalAction); // Abaixo estão todas as ações que o agente pode executar (similar ao tratamento feito no Soar). public enum ClarionAgentActionType { DO_NOTHING, ROTATE_CLOCKWISE, // Assosiado ao GoalChunk - avoid wall EAT, // Assosiado ao GoalChunk - eat food GO_AHEAD, // Associado ao esquema de controle análogo ao do DemoCLARION GET, // Idem DELIVER, // Idem DIE // Idem } . . . #region Run Thread Method private void RunThread(object obj) { // Set environment (initialization) and output chunk InputFood = World.NewDimensionValuePair(SENSOR_VISUAL_DIMENSION, "Food"); OutputEatFood = World.NewExternalActionChunk(ClarionAgentActionType.EAT.ToString()); OutputEatFood.Add (World.NewDimensionValuePair("type", ClarionAgentActionType.EAT.ToString())); InputWall = World.NewDimensionValuePair(SENSOR_VISUAL_DIMENSION, "Wall"); OutputAvoidWall = World.NewExternalActionChunk(ClarionAgentActionType.ROTATE_CLOCKWISE.ToString()); OutputAvoidWall.Add (World.NewDimensionValuePair("type", ClarionAgentActionType.ROTATE_CLOCKWISE.ToString())); // Cognitive Cycle starts here getting sensorial information Console.WriteLine("Starting Cognitive Cycle ... press CTRL-C to finish!\n"); while (CurrentCognitiveCycle != MaxNumberOfCognitiveCycles) { // Get current sensorial information IList<Thing> sensorialInformation = OnNewVisualSensorialInformation(); // Make the perception SensoryInformation si = MakePerceptionFromSensorialInput(sensorialInformation); //Perceive the sensory information CurrentAgent.Perceive(si); //Choose an action ExternalActionChunk chosen = CurrentAgent.GetChosenExternalAction(si); . . . String actionLabel = chosen.LabelAsIComparable.ToString(); ClarionAgentActionType actionType = (ClarionAgentActionType)Enum.Parse(typeof(ClarionAgentActionType), actionLabel, true); if (OnNewExternalActionSelected != null) { switch (actionType) { case ClarionAgentActionType.EAT: if (si[InputFood] == CurrentAgent.Parameters.MAX_ACTIVATION && CurrentAgent.CurrentGoal == GoalEatFood) { OnNewExternalActionSelected(actionType); CurrentAgent.ReceiveFeedback(si, 1.0); } else { CurrentAgent.ReceiveFeedback(si, 0.0); } break; case ClarionAgentActionType.ROTATE_CLOCKWISE: if (si[InputWall] == CurrentAgent.Parameters.MAX_ACTIVATION && CurrentAgent.CurrentGoal == GoalAvoidWall) { OnNewExternalActionSelected(actionType); CurrentAgent.ReceiveFeedback(si, 1.0); } else { CurrentAgent.ReceiveFeedback(si, 0.0); } break; . . . } } // Increment the number of cognitive cycles CurrentCognitiveCycle++; // Wait to the agent accomplish his job if (TimeBetweenCognitiveCycles > 0) { Thread.Sleep(TimeBetweenCognitiveCycles); } } } #endregion Run Thread Method . . . }
A seguir expomos a parte que trata do controle das ações para a coleta de jóias de acordo com os leaflets. São ações que não estão diretamente associadas às necessidades primárias do agente. Disponibilizamos a codificação de um agente CLARION em que a ação "desviar da parede" está associada a uma característica primária do agente (medo de colisão), isto é, este agente não segue o design do agente no DemoCLARION - veja [ aqui ].
Esquema do controle das ações para a coleta das jóias:
O esquema do controle das ações sobre a captura de jóias é análogo ao sistema de controle de navegação fornecido no DemoCLARION. O conjunto de regras FixedRule
não sofre muitas alterações:
// Se o alimento está a uma distância inferior a trinta unidades, então recomenda-se a ação de captura // (comer). Caso contrário, a ação não é recomendada. A condição da regra é dada pelo método delegate. // Em pseudo-código: public double Delegate_FixedRule_ToEatFood(SensoryInformation si, Rule target) { return 1.0 if, {distancia, d} is activated and {d <= 30} Otherwise, 0.0 }
A classe FixedRules
fornece os mecanismos necessários para codificar uma regra. Para inicializar uma regra basta especificar um método delegate. Ou seja, definir o método que será usado para calcular o suporte para a regra , isto é feito via SupportCalculator
delegate. Essa medida do suporte determina se uma regra é elegível para ser recomendar uma dada ação num dado momento, baseado num "partial match threshold", capturado pelo PARTIAL_MATCH_THRESHOLD
parameter. O input para o suporte é um elemento da classe SensoryInformation
, cuja base é o ActivationColection
do Clarion.Framework namespace
. Desse modo, podemos reescrever a regra acima usando o seguinte esquema (é somente um esquema, a estrutura sintática do código é a mesma do DemoCLARION):
// Perception input
private DimensionValuePair InputFoodAhead;
// O agente interpreta os dados do sensor visual
private SensoryInformation MakePerceptionFromSensorialInput(IList<Thing> sensorialInformation) {
// Dados sensoriais
SensoryInformation si = World.NewSensoryInformation(CurrentAgent);
// Detect if we have a wall ahead
Boolean foodAhead = sensorialInformation.Where(item => (item.CategoryId == Thing.CATEGORY_BRICK &&
item.DistanceToCreature <= 30)).Any();
double foodAheadActivationValue =
foodAhead ? CurrentAgent.Parameters.MAX_ACTIVATION : CurrentAgent.Parameters.MIN_ACTIVATION;
si.Add(InpuFoodAhead, foodAheadActivationValue);
return si;
}
private double Delegate_FixedRule_ToEatFood(ActivationCollection currentInput, Rule target) {
return ((currentInput.Contains(InputFoodAhead, CurrentAgent.Parameters.MAX_ACTIVATION))) ? 1.0 : 0.0;
}
// Configuração do ACS
private void SetupACS() {
SupportCalculator avoidCollisionWallSupportCalculator = FixedRuleDelegateToAvoidColissionWall;
}
// Configuração do ACS
private void SetupACS() {
// Cria as regras para "Colission-Wall" e "Go Ahead"
SupportCalculator avoidCollisionWallSupportCalculator = FixedRuleDelegateToAvoidColissionWall;
SupportCalculator goAheadSupportCalculator = FixedRuleDelegateToGoAhead;
FixedRule ruleAvoidCollisionWall = AgentInitializer.InitializeActionRule(CurrentAgent,
FixedRule.Factory, OutputRotateClockwise,
avoidCollisionWallSupportCalculator);
FixedRule ruleGoAhead = AgentInitializer.InitializeActionRule(CurrentAgent, FixedRule.Factory,
OutputGoAhead, goAheadSupportCalculator);
// Agrega as regras ao agente (no ACS)
CurrentAgent.Commit(ruleAvoidCollisionWall);
CurrentAgent.Commit(ruleGoAhead);
// Desativa a regras de refinamento
CurrentAgent.ACS.Parameters.PERFORM_RER_REFINEMENT = false;
// Estabelece a forma de seleção: probabilística
CurrentAgent.ACS.Parameters.LEVEL_SELECTION_METHOD =
ActionCenteredSubsystem.LevelSelectionMethods.STOCHASTIC;
// A seleção da ação é fixa, definida acima.
CurrentAgent.ACS.Parameters.LEVEL_SELECTION_OPTION = ActionCenteredSubsystem.LevelSelectionOptions.FIXED;
// Estabelece os valores probabilísticos
CurrentAgent.ACS.Parameters.FIXED_FR_LEVEL_SELECTION_MEASURE = 1;
CurrentAgent.ACS.Parameters.FIXED_IRL_LEVEL_SELECTION_MEASURE = 0;
CurrentAgent.ACS.Parameters.FIXED_BL_LEVEL_SELECTION_MEASURE = 0;
CurrentAgent.ACS.Parameters.FIXED_RER_LEVEL_SELECTION_MEASURE = 0;
}
Como mencionamos no início desta seção, conforme as discussões com colegas, foram feitos alguns ajustes no WS3D para o desenvolviemtno da Atividade: Teste 1. A implementação que o Eduardo Jucá disponibilizou contém esses ajustes. Utilizamos nesta atividade a versão do Eduardo Jucá: versão jnlp
funcional do WS3D [ aqui ], o código fonte [ aqui ] e comentários sobre as alterações [ aqui ].
A proposta de modelo de arquitetura cognitiva CLARION toma como base a distinção entre processos (e de representação de conhecimento, parte da cognição) explícitos (via regras e chunks) e implícitos (via redes neurais) associados à cognição humana. Nesta atividade exploramos o uso desses processos nas tomadas de decisões referentes às necessidades primárias e à tarefa de coletar jóias de acordo com leaflets. O ACS cuida das decisões sobre as ações a serem executadas, com suporte do NACS que auxilia tratando o conhecimento declarativo. O MS estabelece o direcionamento (determinado pelos níveis dos drives em relação às necessidades básicas do agente) das decisões em relação às metas. O MCS cuida do auto-monitoramento e a configuração dos parâmetros que atuam no ACS e NACS. O MCS também pode interferir no MS ajustando o nível dos drives.
Não realizamos esta parte da atividade.
Theme by Danetsoft and Danang Probo Sayekti inspired by Maksimer