// Distributed Decision making system framework // Copyright (c) 2014, Jordi Coll Corbilla // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // - Neither the name of this library nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. package ddm.behaviours; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import jade.content.Concept; import jade.content.ContentElement; import jade.content.lang.Codec; import jade.content.lang.sl.SLCodec; import jade.content.onto.Ontology; import jade.content.onto.basic.Action; import jade.core.AID; import jade.core.behaviours.Behaviour; import jade.lang.acl.ACLMessage; import jade.lang.acl.MessageTemplate; import ddm.agents.ManagerAgent; import ddm.data.DatasetManager; import ddm.decision.DecisionMaker; import ddm.decision.DecisionType; import ddm.jade.JadeAgents; import ddm.logging.ShowMessage; import ddm.ontology.ClassificationResult; import ddm.ontology.ClassifierOntology; import ddm.ontology.DataInstance; /** * * @author jordi Corbilla * Behaviour that manages the communication between manager and agents. This class sends the information * to each individual classifier and it waits until the response is back from the server. * It's using a bespoke behaviour with three different steps. */ @SuppressWarnings("serial") public class SendDataBehaviour extends Behaviour { private ManagerAgent myAgent; private ShowMessage sm; private Codec codec = new SLCodec(); private Ontology ontology = ClassifierOntology.getInstance(); private int step = 0; private int repliesCnt = 0; private int DataSize = 0; private int index = 0; private ArrayList<DataInstance> data; private MessageTemplate mt = MessageTemplate.MatchPerformative(ACLMessage.PROPOSE); private jade.util.leap.List Classifiers; private HashMap<String, ClassificationResult> decisionResult = new HashMap<String, ClassificationResult>(); private DataInstance dataToPredict; private DecisionMaker decisionMaker; private int TrainingSize; // Get the user command public SendDataBehaviour(ManagerAgent a) { super(a); myAgent = a; sm = a.getSM(); } public void action() { sm.Log("SendDataBehaviour - start"); switch (step) { case 0: //Prepare the data DatasetManager datasetManager = myAgent.getDatasetManager(); this.data = datasetManager.getDatasetsData(); this.DataSize = data.size(); this.TrainingSize = datasetManager.getPartitionList().getTrainingSize(); decisionMaker = new DecisionMaker(myAgent.getConfiguration()); Classifiers = JadeAgents.SearchAgents(myAgent, "Classifier Agent", null); sm.Log("Agents found: " + Classifiers.size()); System.out.println("Data size" + this.DataSize); System.out.println("GOING TO STEP 1"); step = 1; break; case 1: //Send the data to classify to every agent repliesCnt = 0; this.dataToPredict = null; decisionResult.clear(); sm.Log("Looking for agents online"); Iterator<?> classifiers = Classifiers.iterator(); ACLMessage msg = new ACLMessage(ACLMessage.REQUEST); while (classifiers.hasNext()) { AID server = (AID) classifiers.next(); System.out.println("Sending to: " + server.getName()); msg.setLanguage(codec.getName()); msg.setOntology(ontology.getName()); try { DataInstance dataInstance = data.get(index); this.dataToPredict = dataInstance; System.out.println("Data to send " + dataInstance.toString()); myAgent.getContentManager().fillContent(msg, new Action(server, dataInstance)); msg.addReceiver(server); myAgent.send(msg); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //System.out.println("Contacting client... Please wait!"); } catch (Exception ex) { ex.printStackTrace(); } } if (index < DataSize) { index++; System.out.println("GOING TO STEP 2 - Decision"); step = 2; } break; case 2: //This property is set to the number of agents + 1 as the framework is sending duplicated messages. //http://jade.17737.x6.nabble.com/Receiving-duplicate-messages-td5002566.html int number = myAgent.getNumberOfAgents() + 1; //Receive all the proposals from every agent ACLMessage reply = myAgent.receive(mt); if (reply != null) { if (reply.getPerformative() == ACLMessage.PROPOSE) { //System.out.println("Propose!!!"); ContentElement content = null; try { content = myAgent.getContentManager().extractContent(reply); } catch (Exception ex) { ex.printStackTrace(); } Concept action = ((Action) content).getAction(); if (action instanceof ClassificationResult) { ClassificationResult cr = (ClassificationResult) action; System.out.println("*****" + cr.getName() + " " + cr.getType() + " " + cr.getDuration() + "ms NumCorrect: " + cr.getNumCorrect() + " Value:" + cr.getInstanceValue() + " TrainingSize:" + cr.getTrainingSize() + " Total:" + this.TrainingSize + " Val:" + cr.getInstanceClassification() + " Pred:" + cr.getInstancePredictedValue() + " Value:" + cr.getPredictedInstanceValue()); repliesCnt++; decisionResult.put(cr.getName(), cr); if (repliesCnt >= (number*myAgent.getNumberOfAgents()) && (index < DataSize)) { decisionMaker.Make(DecisionType.OrderedWeightedAggregation, dataToPredict, decisionResult, TrainingSize); step = 1; try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("GOING TO STEP 1 - Communications"); } else if (repliesCnt >= (number*myAgent.getNumberOfAgents()) && (index == DataSize)) { System.out.println("GOING TO STEP 3 - evaluation"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } step = 3; } } } } else { block(); } break; case 3: decisionMaker.CloseFile(); myAgent.addBehaviour(new WaitUserCommandBehaviour(myAgent)); step = 4; break; } sm.Log("SendDataBehaviour - end"); } @Override public boolean done() { return step == 4; } }