package pikater.agents.computing; //import java.io.BufferedReader; import jade.content.ContentElement; import jade.content.lang.Codec; import jade.content.lang.Codec.CodecException; import jade.content.lang.sl.SLCodec; import jade.content.onto.Ontology; import jade.content.onto.OntologyException; import jade.content.onto.UngroundedException; import jade.content.onto.basic.Action; import jade.content.onto.basic.Result; import jade.core.AID; import jade.core.Agent; import jade.core.behaviours.Behaviour; import jade.core.behaviours.CyclicBehaviour; import jade.core.behaviours.FSMBehaviour; import jade.core.behaviours.OneShotBehaviour; import jade.domain.DFService; import jade.domain.FIPAException; import jade.domain.FIPANames; import jade.domain.FIPAService; import jade.domain.FIPAAgentManagement.DFAgentDescription; import jade.domain.FIPAAgentManagement.ServiceDescription; import jade.lang.acl.ACLMessage; import jade.lang.acl.MessageTemplate; import jade.proto.AchieveREInitiator; import jade.util.leap.List; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.util.Date; import java.util.LinkedList; import pikater.ontology.messages.Data; import pikater.ontology.messages.DataInstances; import pikater.ontology.messages.Execute; import pikater.ontology.messages.GetData; import pikater.ontology.messages.GetOptions; import pikater.ontology.messages.MessagesOntology; import pikater.ontology.messages.PartialResults; import pikater.ontology.messages.Task; import weka.core.Instances; public abstract class Agent_ComputingAgent extends Agent { /** * */ private static final long serialVersionUID = -7927583436579620995L; protected Codec codec = new SLCodec(); private Ontology ontology = MessagesOntology.getInstance(); public enum states { NEW, TRAINED } /* common properties for all computing agents */ public String trainFileName; public String testFileName; public states state = states.NEW; public boolean hasGotRightData = false; // protected Vector<MyWekaOption> Options; protected pikater.ontology.messages.Agent agent_options = null; protected Instances data; // data read from fileName file Instances train; DataInstances onto_train; Instances test; DataInstances onto_test; int convId = 0; protected String[] OPTIONS; protected pikater.ontology.messages.Task current_task = null; // protected String[] OPTIONS_; protected String[] OPTIONS_ARGS; protected Object[] args; boolean working = false; // TODO -> state? LinkedList<ACLMessage> taskFIFO = new LinkedList<ACLMessage>(); private Behaviour execution_behaviour = null; private Behaviour send_options_behaviour = null; private boolean newAgent = true; private boolean resurrected = false; protected abstract void train() throws Exception; protected abstract pikater.ontology.messages.Evaluation evaluateCA(); protected abstract DataInstances getPredictions(Instances test, DataInstances onto_test); public abstract String getAgentType(); // public boolean loadAgent(String agentName); protected abstract void getParameters(); protected boolean registerWithDF() { // register with the DF DFAgentDescription description = new DFAgentDescription(); // the description is the root description for each agent // and how we prefer to communicate. // description.addLanguages(language.getName()); // description.addOntologies(ontology.getName()); // description.addProtocols(InteractionProtocol.FIPA_REQUEST); description.setName(getAID()); // the service description describes a particular service we // provide. ServiceDescription servicedesc = new ServiceDescription(); // the name of the service provided (we just re-use our agent name) servicedesc.setName(getLocalName()); // The service type should be a unique string associated with // the service.s String typeDesc; if (state == states.TRAINED) { // add fileName to service description typeDesc = getAgentType() + " trained on " + trainFileName; } else { typeDesc = getAgentType(); } servicedesc.setType(typeDesc); // the service has a list of supported languages, ontologies // and protocols for this service. // servicedesc.addLanguages(language.getName()); // servicedesc.addOntologies(ontology.getName()); // servicedesc.addProtocols(InteractionProtocol.FIPA_REQUEST); description.addServices(servicedesc); // add "computing agent service" ServiceDescription servicedesc_g = new ServiceDescription(); servicedesc_g.setName(getLocalName()); servicedesc_g.setType("ComputingAgent"); description.addServices(servicedesc_g); // register synchronously registers us with the DF, we may // prefer to do this asynchronously using a behaviour. // System.out.println("DF: "+DFService.); try { DFService.register(this, description); System.out.println(getLocalName() + ": successfully registered with DF; service type: " + typeDesc); return true; } catch (FIPAException e) { System.err.println(getLocalName() + ": error registering with DF, exiting:" + e); // doDelete(); return false; } } // end registerWithDF protected void deregisterWithDF() { try { DFService.deregister(this); } catch (FIPAException e) { System.err.println(getLocalName() + " failed to deregister with DF."); // doDelete(); } } // end deregisterWithDF protected ACLMessage sendOptions(ACLMessage request) { ACLMessage msgOut = request.createReply(); msgOut.setPerformative(ACLMessage.INFORM); try { // Prepare the content ContentElement content = getContentManager() .extractContent(request); // TODO exception block? Result result = new Result((Action) content, agent_options); // result.setValue(options); try { // Let JADE convert from Java objects to string getContentManager().fillContent(msgOut, result); // send(msgOut); } catch (CodecException ce) { ce.printStackTrace(); } catch (OntologyException oe) { oe.printStackTrace(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return msgOut; } // end SendOptions @Override protected void setup() { getContentManager().registerLanguage(codec); getContentManager().registerOntology(ontology); if (!newAgent){ resurrected = true; System.out.println(getLocalName() + " resurrected."); taskFIFO = new LinkedList<ACLMessage>(); execution_behaviour.reset(); return; } newAgent = false; System.out.println(getAgentType() + " " + getLocalName() + " is alive..."); args = getArguments(); OPTIONS_ARGS = new String[args.length]; if (args != null && args.length > 0) { if (args[0].equals("load")) { // loadAgent(getLocalName()); args = new String[0]; } else { // parameters of the network for (int i = 0; i < args.length; i++) { OPTIONS_ARGS[i] = (String) args[i]; } // write out parameters for (String s : OPTIONS_ARGS) { System.out.print(s + " "); } } } registerWithDF(); getParameters(); addBehaviour(send_options_behaviour = new RequestServer(this)); addBehaviour(execution_behaviour = new ProcessAction(this)); } // end setup public boolean setOptions(pikater.ontology.messages.Task task) { /* * INPUT: task with weka options Fills the OPTIONS array and * current_task. */ current_task = task; OPTIONS = task.getAgent().optionsToString().split("[ ]+"); return true; } // end loadConfiguration public String getOptions() { // write out OPTIONS String strOPTIONS = ""; strOPTIONS += "OPTIONS:"; for (int i = 0; i < OPTIONS.length; i++) { strOPTIONS += " " + OPTIONS[i]; } return strOPTIONS; } protected ACLMessage sendGetDataReq(String fileName) { AID[] ARFFReaders; AID reader; ACLMessage msgOut = null; // Make the list of reader agents DFAgentDescription template = new DFAgentDescription(); ServiceDescription sd = new ServiceDescription(); sd.setType("ARFFReader"); template.addServices(sd); try { DFAgentDescription[] result = DFService.search(this, template); System.out.println("Found the following ARFFReader agents:"); ARFFReaders = new AID[result.length]; for (int i = 0; i < result.length; ++i) { ARFFReaders[i] = result[i].getName(); System.out.println(ARFFReaders[i].getName()); } // choose one reader = ARFFReaders[0]; // request msgOut = new ACLMessage(ACLMessage.REQUEST); msgOut.setProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST); msgOut.setReplyByDate(new Date(System.currentTimeMillis() + 10000)); msgOut.setLanguage(codec.getName()); msgOut.setOntology(ontology.getName()); msgOut.addReceiver(reader); msgOut.setConversationId("get-data_" + convId++); // content GetData get_data = new GetData(); get_data.setFile_name(fileName); Action a = new Action(); a.setAction(get_data); a.setActor(this.getAID()); getContentManager().fillContent(msgOut, a); } catch (FIPAException fe) { fe.printStackTrace(); return null; } catch (CodecException e) { e.printStackTrace(); return null; } catch (OntologyException e) { e.printStackTrace(); return null; } return msgOut; } // end sendGetDataReq public static byte[] toBytes(Object object) throws Exception { java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream(); java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(baos); oos.writeObject(object); return baos.toByteArray(); } public static Object toObject(byte[] data) throws Exception { Object object = new java.io.ObjectInputStream( new java.io.ByteArrayInputStream(data)).readObject(); return object; } /* * Send partial results to the GUI Agent(s) call it after training or during * training? */ protected void sendResultsToGUI(Boolean first_time, Task _task, List _evaluations) { ACLMessage msgOut = new ACLMessage(ACLMessage.INFORM); DFAgentDescription template = new DFAgentDescription(); ServiceDescription sd = new ServiceDescription(); sd.setType("GUIAgent"); template.addServices(sd); try { DFAgentDescription[] gui_agents = DFService.search(this, template); for (int i = 0; i < gui_agents.length; ++i) { msgOut.addReceiver(gui_agents[i].getName()); } } catch (FIPAException fe) { fe.printStackTrace(); } msgOut.setConversationId("partial-results"); PartialResults content = new PartialResults(); content.setResults(_evaluations); content.setTask_id(_task.getId()); if (first_time) { content.setTask(_task); } try { getContentManager().fillContent(msgOut, content); } catch (CodecException e) { e.printStackTrace(); } catch (OntologyException e) { e.printStackTrace(); } send(msgOut); } protected class RequestServer extends CyclicBehaviour { /** * */ private static final long serialVersionUID = 1074564968341084444L; private MessageTemplate resMsgTemplate = MessageTemplate .and( MessageTemplate .MatchProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST), MessageTemplate.and(MessageTemplate .MatchPerformative(ACLMessage.REQUEST), MessageTemplate.and(MessageTemplate .MatchLanguage(codec.getName()), MessageTemplate.MatchOntology(ontology .getName())))); public RequestServer(Agent agent) { super(agent); } // TODO: will we accept or refuse the request? (working, size of // taksFIFO, latency time...) boolean acceptTask() { return true/* taskFIFO.size()<=MAX_TASKS */; } ACLMessage processExecute(ACLMessage req) { ACLMessage result_msg = req.createReply(); if (acceptTask()) { result_msg.setPerformative(ACLMessage.AGREE); taskFIFO.addLast(req); if (!execution_behaviour.isRunnable()) { execution_behaviour.restart(); } } else { result_msg.setPerformative(ACLMessage.REFUSE); result_msg.setContent("(Computing agent overloaded)"); } return result_msg; } @Override public void action() { ACLMessage req = receive(resMsgTemplate); if (req != null) { try { ContentElement content = getContentManager() .extractContent(req); if (((Action) content).getAction() instanceof GetOptions) { ACLMessage result_msg = sendOptions(req); send(result_msg); return; } if (((Action) content).getAction() instanceof Execute) { send(processExecute(req)); // refuse/accept return; } } catch (CodecException ce) { ce.printStackTrace(); } catch (OntologyException oe) { oe.printStackTrace(); } ACLMessage result_msg = req.createReply(); result_msg.setPerformative(ACLMessage.NOT_UNDERSTOOD); send(result_msg); return; } else { block(); } } } private class ProcessAction extends FSMBehaviour { /** * */ private static final long serialVersionUID = 7417933314402310322L; private static final String INIT_STATE = "Init"; private static final String GETTRAINDATA_STATE = "GetTrainingData"; private static final String GETTESTDATA_STATE = "GetTestData"; private static final String TRAINTEST_STATE = "TrainTest"; private static final String SENDRESULTS_STATE = "SendResults"; private static final int NEXT_JMP = 0; private static final int LAST_JMP = 1; ACLMessage incoming_request; ACLMessage result_msg; Execute execute_action; boolean success; pikater.ontology.messages.Evaluation eval; String train_fn; String test_fn; String output; String mode; /* Resulting message: FAILURE */ void failureMsg(String desc) { result_msg = incoming_request.createReply(); result_msg.setPerformative(ACLMessage.FAILURE); result_msg.setContent(desc); } /* Get a message from the FIFO of tasks */ boolean getRequest() { if (taskFIFO.size() > 0) { incoming_request = taskFIFO.removeFirst(); try { ContentElement content = getContentManager() .extractContent(incoming_request); execute_action = (Execute) ((Action) content).getAction(); return true; } catch (CodecException ce) { ce.printStackTrace(); } catch (OntologyException oe) { oe.printStackTrace(); } } else { block(); } return false; } /* Extract data from INFORM message (ARFF reader) */ pikater.ontology.messages.DataInstances processGetData(ACLMessage inform) { ContentElement content; try { content = getContentManager().extractContent(inform); if (content instanceof Result) { Result result = (Result) content; if (result.getValue() instanceof pikater.ontology.messages.DataInstances) { return (pikater.ontology.messages.DataInstances) result .getValue(); } } } catch (UngroundedException e) { e.printStackTrace(); } catch (CodecException e) { e.printStackTrace(); } catch (OntologyException e) { e.printStackTrace(); } return null; } ProcessAction(Agent a) { super(a); /* FSM: register states */ // init state registerFirstState(new Behaviour(a) { int next; boolean cont; @Override public void action() { result_msg = null; execute_action = null; if (!getRequest()) { // no task to execute cont = true; // block(); return; } cont = false; state = states.NEW; // Set options setOptions(execute_action.getTask()); eval = null; success = true; Data data = execute_action.getTask().getData(); output = data.getOutput(); mode = data.getMode(); train_fn = data.getTrain_file_name(); AchieveREInitiator get_train_behaviour = (AchieveREInitiator) ((ProcessAction) parent) .getState(GETTRAINDATA_STATE); if (!train_fn.equals(trainFileName)) { get_train_behaviour.reset(sendGetDataReq(train_fn)); } else { // We have already the right data get_train_behaviour.reset(null); } test_fn = data.getTest_file_name(); AchieveREInitiator get_test_behaviour = (AchieveREInitiator) ((ProcessAction) parent) .getState(GETTESTDATA_STATE); if (!test_fn.equals(testFileName)) { get_test_behaviour.reset(sendGetDataReq(test_fn)); } else { // We have already the right data get_test_behaviour.reset(null); } } @Override public boolean done() { return !cont; } }, INIT_STATE); // get train data state registerState(new AchieveREInitiator(a, null) { public int next = NEXT_JMP; @Override protected void handleInform(ACLMessage inform) { pikater.ontology.messages.DataInstances _train = processGetData(inform); if (_train != null) { trainFileName = train_fn; onto_train = _train; train = onto_train.toWekaInstances(); train.setClassIndex(train.numAttributes() - 1); next = NEXT_JMP; return; } else { next = LAST_JMP; failureMsg("No train data received from the reader agent: Wrong content."); return; } } @Override protected void handleFailure(ACLMessage failure) { failureMsg("No train data received from the reader agent: Reader Failed."); next = LAST_JMP; } @Override public int onEnd() { int next_val = next; next = NEXT_JMP; return next; } }, GETTRAINDATA_STATE); // get test data state registerState(new AchieveREInitiator(a, null) { public int next = NEXT_JMP; @Override protected void handleInform(ACLMessage inform) { pikater.ontology.messages.DataInstances _test = processGetData(inform); if (_test != null) { testFileName = test_fn; onto_test = _test; test = onto_test.toWekaInstances(); test.setClassIndex(test.numAttributes() - 1); next = NEXT_JMP; return; } else { next = LAST_JMP; failureMsg("No test data received from the reader agent: Wrong content."); return; } } @Override protected void handleFailure(ACLMessage failure) { failureMsg("No test data received from the reader agent: Reader Failed."); next = LAST_JMP; } @Override public int onEnd() { int next_val = next; next = NEXT_JMP; return next; } }, GETTESTDATA_STATE); // Train&test state registerState(new Behaviour(a) { @Override public void action() { try { if (state != states.TRAINED) { train(); } else{ if (! mode.equals("test_only")){ train(); } } eval = evaluateCA(); if (output.equals("predictions")){ eval.setData_table(getPredictions(test, onto_test)); } } catch (Exception e) { success = false; working = false; failureMsg(e.getMessage()); System.out.println("Error: " + e.getMessage() + " "); e.printStackTrace(); } } @Override public boolean done() { return (state == states.TRAINED) || !success; } }, TRAINTEST_STATE); // send results state registerState(new OneShotBehaviour(a) { @Override public void action() { if (success && (result_msg == null)) { // save agent every time it executes a task /*String objectFilename = null; try { // resurrected = false; objectFilename = save(); } catch (CodecException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (OntologyException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (FIPAException e) { // TODO Auto-generated catch block e.printStackTrace(); } */ if (( current_task.getSave_mode() != null && current_task.getSave_mode().equals("file")) && !resurrected){ try { String objectFilename = saveAgentToFile(); eval.setObject_filename(objectFilename); } catch (CodecException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (OntologyException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (FIPAException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // eval.setDuration(duration); if (( current_task.getSave_mode() != null && current_task.getSave_mode().equals("message"))){ try { eval.setObject(getAgentObject()); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } result_msg = incoming_request.createReply(); result_msg.setPerformative(ACLMessage.INFORM); try { // Prepare the content - Result with Evaluation // instead of MyWekaEvaluation is sent!!! ContentElement content = getContentManager() .extractContent(incoming_request); Result result = new Result((Action) content, eval); getContentManager().fillContent(result_msg, result); } catch (UngroundedException e) { e.printStackTrace(); } catch (CodecException e) { e.printStackTrace(); } catch (OntologyException e) { e.printStackTrace(); } } send(result_msg); } }, SENDRESULTS_STATE); /* FSM: register transitions */ // init state transition registerDefaultTransition(INIT_STATE, GETTRAINDATA_STATE); // get train data transitions registerTransition(GETTRAINDATA_STATE, GETTESTDATA_STATE, NEXT_JMP); registerTransition(GETTRAINDATA_STATE, SENDRESULTS_STATE, LAST_JMP); // get test data transitions registerTransition(GETTESTDATA_STATE, TRAINTEST_STATE, NEXT_JMP); registerTransition(GETTESTDATA_STATE, SENDRESULTS_STATE, LAST_JMP); // train&test state transition registerDefaultTransition(TRAINTEST_STATE, SENDRESULTS_STATE); // backward transition: reset all states registerDefaultTransition(SENDRESULTS_STATE, INIT_STATE, new String[] { INIT_STATE, GETTRAINDATA_STATE, GETTESTDATA_STATE, TRAINTEST_STATE, SENDRESULTS_STATE }); } } private byte [] getAgentObject() throws IOException{ ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this); oos.flush(); oos.close(); byte [] data = bos.toByteArray(); return data; } private pikater.ontology.messages.Agent getAgentWithFilledObject() throws IOException{ pikater.ontology.messages.Agent savedAgent = current_task.getAgent(); savedAgent.setObject(getAgentObject()); return savedAgent; } private String saveAgentToFile() throws IOException, CodecException, OntologyException, FIPAException { pikater.ontology.messages.SaveAgent saveAgent = new pikater.ontology.messages.SaveAgent(); saveAgent.setAgent(getAgentWithFilledObject()); ACLMessage request = new ACLMessage(ACLMessage.REQUEST); request.addReceiver(new AID("agentManager", false)); request.setOntology(MessagesOntology.getInstance().getName()); request.setLanguage(codec.getName()); request.setProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST); Action a = new Action(); a.setActor(this.getAID()); a.setAction(saveAgent); getContentManager().fillContent(request, a); ACLMessage reply = FIPAService.doFipaRequestClient(this, request); String objectFilename = reply.getContent(); return objectFilename; } };