/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to you under * the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may * obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. * * See the License for the specific language governing permissions * and limitations under the License. */ package siebog.agents.xjaf.pso; import java.util.logging.Logger; import javax.ejb.Remote; import javax.ejb.Stateful; import siebog.agents.AID; import siebog.agents.Agent; import siebog.agents.AgentClass; import siebog.agents.AgentInitArgs; import siebog.agents.XjafAgent; import siebog.interaction.ACLMessage; import siebog.interaction.Performative; /** * * Implementation of an PSO starter agent. It initializes all the Particles, and keeps track of the * results. * * @author <a href="mailto:simic.dragan@hotmail.com">Dragan Simic</a> */ @Stateful @Remote(Agent.class) public class Swarm extends XjafAgent { private static final long serialVersionUID = -7864076456995372014L; private static final Logger logger = Logger.getLogger(Swarm.class.getName()); // TODO - Do we need to use 'args' to load values dynamically? Using // hard-coded values for testing int numberParticles = 10; int numberIterations = 1000; int dimension = 2; // range for X values double minX = -100.0; double maxX = 100.0; // iteration counter int iteration = 0; int iteratedParticles = 0; // best results double[] bestGlobalPosition = new double[dimension]; double bestGlobalFitness = Double.MAX_VALUE; /** * * @see xjaf2x.server.agm().XjafAgent#onInit(java.io.Serializable[]) */ @Override protected void onInit(AgentInitArgs args) { logger.info("PsoStarter agent running."); logger.fine("Begin Particle Swarm Optimization demonstration"); logger.fine("Objective function to minimize has dimension = " + dimension); // TODO - load arguments? (numberParticles?, numberIterations?, minX?, // maxX?, dimension? ) logger.fine("Range for all X values is " + minX + " <= x <= " + maxX); logger.fine("Number of iterations = " + numberIterations); logger.fine("Number of particles in swarm = " + numberParticles); logger.fine("Initializing swarm with random positions/solutions."); for (int i = 0; i < numberParticles; ++i) { AgentInitArgs mapArgs = new AgentInitArgs("dimension->" + dimension, "minx->" + minX, "maxx->" + maxX); agm().startServerAgent(new AgentClass(Agent.SIEBOG_MODULE, "Particle"), "Particle" + i, mapArgs); } logger.info("Entering main PSO processing loop"); iterate(); } /** * One iteration of the whole swarm. Finishes execution if numberIterations is reached. */ private void iterate() { if (iteration < numberIterations) { iteration++; iteratedParticles = 0; // request iteration from all particles for (int i = 0; i < numberParticles; ++i) { // find particle AID particleAID = agm().getAIDByRuntimeName("Particle" + i); // compose message ACLMessage message = new ACLMessage(); message.performative = Performative.REQUEST; PsoMessage psoMessage = new PsoMessage(PsoMessage.ITERATE_PARTICLE, bestGlobalFitness, bestGlobalPosition); message.content = psoMessage.toString(); message.sender = myAid; message.receivers.add(particleAID); msm().post(message); } } else { finish(); } } /** * Handles incoming messages. * * @see xjaf2x.server.agm().XjafAgent#onMessage(xjaf2x.server.msm().fipa.acl.ACLMessage) */ @Override protected void onMessage(ACLMessage message) { PsoMessage psoMessage = PsoMessage.valueOf(message.content); if (message.performative == Performative.REQUEST) { if (psoMessage.getAction().equals(PsoMessage.UPDATE_GLOBAL_SOLUTION)) { if (psoMessage.getFitness() < bestGlobalFitness) { // logger.info("Updated best result. AID: " + message.getSender() + // " , fitness: " // + psoMessage.getFitness()); bestGlobalFitness = psoMessage.getFitness(); bestGlobalPosition = psoMessage.getPosition(); } } } else if (message.performative == Performative.INFORM) { // count responses from articles, so that we know when to proceed to next iteration iteratedParticles++; if (iteratedParticles == numberParticles) { iterate(); } } } /** * Prints results and terminates all agents (particles and swarm) */ private void finish() { // print results logger.info("Processing complete"); logger.info("Final best fitness = " + bestGlobalFitness); logger.info("Best position/solution: "); for (int i = 0; i < bestGlobalPosition.length; ++i) { logger.info("x" + i + " = " + String.format("%.16f", bestGlobalPosition[i])); } // stop all particles for (int i = 0; i < numberParticles; ++i) { // find particle AID particleAID = agm().getAIDByRuntimeName("Particle" + i); // Looks like 'stop' is not yet implemented, so it is not working yet // All particles should be stopped/terminated at this point agm().stopAgent(particleAID); } // do we need to terminate swarm? agm().stopAgent(myAid); } }