jadex.bdi.planlib.protocols.contractnet.CNPInitiatorPlan Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jadex-applications-applib-bdi Show documentation
Show all versions of jadex-applications-applib-bdi Show documentation
The Jadex applib BDI package contains ready to use functionalities for BDI agents mostly in form of modules called capabilities.
The newest version!
package jadex.bdi.planlib.protocols.contractnet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import jadex.bdi.planlib.protocols.AbstractInitiatorPlan;
import jadex.bdi.planlib.protocols.NegotiationRecord;
import jadex.bdi.planlib.protocols.ParticipantProposal;
import jadex.bdiv3.runtime.IGoal;
import jadex.bdiv3.runtime.impl.GoalFailureException;
import jadex.bdiv3x.runtime.IMessageEvent;
import jadex.bridge.IComponentIdentifier;
import jadex.bridge.fipa.SFipa;
import jadex.bridge.service.annotation.Timeout;
import jadex.commons.SUtil;
import jadex.commons.TimeoutException;
/**
* Handles the initiator side of a contract-net protocol.
*/
public class CNPInitiatorPlan extends AbstractInitiatorPlan
{
//-------- attributes --------
/** Last sent message with convid for receiving answer messages. */
// todo: hack, must save at least one message for being able to wait for replies.
// Otherwise gc would cleanup all messages.
protected IMessageEvent me;
//-------- constructors --------
/**
* The body method is called on the
* instatiated plan instance from the scheduler.
*/
public void body()
{
super.body(); // Hack???
// Start negotiations.
String convid;
if(getParameter("conversation_id").getValue()!=null)
{
convid = (String)getParameter("conversation_id").getValue();
}
else
{
convid = SUtil.createUniqueId(getComponentName());
}
NegotiationRecord nr = new NegotiationRecord(getParameter("cfp").getValue(),
getParameter("cfp_info").getValue(), (IComponentIdentifier[])getParameterSet("receivers").getValues(), getTime());
getParameterSet("history").addValue(nr);
// Perform negotiation rounds.
boolean finished = false;
Map proposalmessages = null;
ParticipantProposal[] acceptables = null;
while(!finished)
{
// Send cfp.
sendCFP(nr, convid);
// Collect proposals from participants.
proposalmessages = new HashMap();
collectProposals(nr, proposalmessages);
// Evaluate proposals and determine acceptables (if any).
acceptables = evaluateProposals(nr, proposalmessages);
nr.setEndtime(getTime());
// Iterated contract net may start another round.
if(isIterated())
{
// Compute next round participants and next round refined cfp.
NegotiationRecord newnr = queryNextroundInfo(nr);
// End if no new regotiation record was produced
if(newnr!=null)
{
// Immediately reject excluded participants.
rejectExcludedProposals(nr, newnr.getParticipants(), proposalmessages);
nr = newnr;
proposalmessages = null;
}
else
{
finished = true;
}
}
else
{
finished = true;
}
}
// Result of completation phase is also stored as negotiation record.
NegotiationRecord newnr;
// Protocol completion depends on executall flag.
if(((Boolean)getParameter("executeall").getValue()).booleanValue())
{
newnr = acceptAllProposals(nr, acceptables, proposalmessages);
}
else
{
newnr = acceptOneProposal(nr, acceptables, proposalmessages);
}
// Reject remaining proposals, which were not accepted.
rejectExcludedProposals(nr, newnr.getParticipants(), proposalmessages);
proposalmessages = null;
nr = newnr;
nr.setEndtime(getTime());
// Determine failure.
determineFailure(nr, acceptables);//, convid);
// Store results.
for(int i=0; i message event).
*/
protected void collectProposals(NegotiationRecord nr, Map proposalmessages)
{
List rec = SUtil.arrayToList(nr.getParticipants());
long time = getTime();
try
{
while(rec.size() > 0)
{
// Wait for the replies.
long wait_time;
if(getTimeout()==Timeout.NONE)
{
wait_time = Timeout.NONE;
}
else
{
wait_time = getTimeout() + time - getTime();
if(wait_time <= 0)
{
break;
}
}
getLogger().info(getComponentName()+" (I)CNPPlan: waiting: "+wait_time);
IMessageEvent reply = (IMessageEvent)waitForReply(me, wait_time);
IComponentIdentifier sender = (IComponentIdentifier)reply.getParameter(SFipa.SENDER).getValue();
rec.remove(sender);
// Other messages than proposals will be ignored and
// lead to exclusion in this negotiation round (as no proposal is available).
// The determination of participants for the next round depends
// on the handling of the query icnp_nextround_info goal.
if(reply.getType().equals(getShortProtocolName()+"_propose"))
{
getLogger().info(getComponentName()+" (I)CNPPlan received a proposal reply: "+reply.getParameter(SFipa.CONTENT).getValue());
ParticipantProposal proposal = nr.getProposal(sender);
if(proposal!=null && proposal.getProposal()==null)
{
proposal.setProposal(reply.getParameter(SFipa.CONTENT).getValue());
proposalmessages.put(proposal, reply);
}
else
{
getLogger().warning(getComponentName()+" (I)CNPPlan received an unexpected proposal reply: "+reply);
}
}
}
}
catch(TimeoutException e)
{
// Timeout can occur when some of the participants do not answer at all.
// In this case protocol proceeds normally.
}
}
/**
* Determine acceptable proposals.
* @param nr The negotiation record.
* @param proposalmessages The received proposal messages (required to detect null proposals).
* @return The acceptable proposals.
*/
protected ParticipantProposal[] evaluateProposals(NegotiationRecord nr, Map proposalmessages)
{
// default: no acceptables
ParticipantProposal[] acceptables = new ParticipantProposal[0];
if(nr.getProposals().length>0)
{
// Determine acceptables.
IGoal sel = createGoal(getShortProtocolName()+"_evaluate_proposals");
sel.getParameter("cfp").setValue(nr.getCFP());
sel.getParameter("cfp_info").setValue(nr.getCFPInfo());
sel.getParameterSet("history").addValues(getParameterSet("history").getValues());
// Add only actual proposals (agents which didn't answer can still be acessed from history)
for(int i=0; i0)
{
try
{
dispatchSubgoalAndWait(sel);
acceptables = (ParticipantProposal[])sel.getParameterSet("acceptables").getValues();
nr.setCFPInfo(sel.getParameter("cfp_info").getValue());
getLogger().info(getComponentName()+" (I)CNPPlan determined acceptables: "+SUtil.arrayToString(acceptables));
}
catch(GoalFailureException e)
{
getLogger().info("(I)CNP: determination of acceptables failed: "+e);
// e.printStackTrace();
}
}
// When no proposals are available no winners are determined (leading to failure if no more negotiation round is performed).
else
{
getLogger().info("(I)CNP: determination of acceptables failed due to no proposals.");
}
}
return acceptables;
}
/**
* Decide if a new iteration should be performed.
* @param nr The negotiation record of the current round.
* @return The negotiation record for the next round (or null, if no further iteration should be performed).
*/
protected NegotiationRecord queryNextroundInfo(NegotiationRecord nr)
{
NegotiationRecord ret = null;
IGoal sel = createGoal(getShortProtocolName()+"_nextround_info");
sel.getParameter("cfp").setValue(nr.getCFP());
sel.getParameter("cfp_info").setValue(nr.getCFPInfo());
sel.getParameterSet("participants").addValues(nr.getParticipants());
sel.getParameterSet("proposals").addValues(nr.getProposals());
sel.getParameterSet("history").addValues(getParameterSet("history").getValues());
try
{
dispatchSubgoalAndWait(sel);
if(((Boolean)sel.getParameter("iterate").getValue()).booleanValue())
{
Object cfp = sel.getParameter("cfp").getValue();
Object cfp_info = sel.getParameter("cfp_info").getValue();
IComponentIdentifier[] participants = (IComponentIdentifier[])sel.getParameterSet("participants").getValues();
ret = new NegotiationRecord(cfp, cfp_info, participants, getTime());
getParameterSet("history").addValue(ret);
getLogger().info("ICNP: perform further negotiation round");
}
else
{
getLogger().info("ICNP: perform no further negotiation round");
}
}
catch(GoalFailureException e)
{
getLogger().info("ICNP: perform no further negotiation round");
// If goal does not succeed no new round will be executed.
//e.printStackTrace();
}
return ret;
}
/**
* Reject all proposals, which are not part of the next round.
* @param nr The current negotiation record.
* @param newparticipants The remaining participants of the next round, which should not be rejected.
*/
protected void rejectExcludedProposals(NegotiationRecord nr, IComponentIdentifier[] newparticipants, Map proposalmessages)
{
// Determine proposals to reject.
// Todo: allow for an agent to participate more than once?
Set proposals = SUtil.arrayToSet(nr.getProposals());
Set remaining = SUtil.arrayToSet(newparticipants);
for(Iterator it=proposals.iterator(); it.hasNext(); )
{
ParticipantProposal proposal = (ParticipantProposal)it.next();
if(remaining.contains(proposal.getParticipant()))
it.remove();
}
ParticipantProposal[] reject_proposals = (ParticipantProposal[])proposals.toArray(new ParticipantProposal[proposals.size()]);
// Send reject proposal message as reply to earlier proposal of participant.
for(int i=0; i
© 2015 - 2025 Weber Informatics LLC | Privacy Policy