From 156dc60e6e2445f029f708c6ac490a2f7dca6564 Mon Sep 17 00:00:00 2001 From: Maxime MORGE <maxime.morge@univ-lille1.fr> Date: Mon, 29 Jun 2020 11:33:07 +0200 Subject: [PATCH] Move rejectOffers from MGM2Mind to AgentBehaviour --- .../decentralized/mgm2/AgentBehaviour.scala | 118 ++++++++++-------- .../solver/decentralized/mgm2/MGM2Mind.scala | 24 +--- 2 files changed, 70 insertions(+), 72 deletions(-) diff --git a/src/main/scala/org/scadcop/solver/decentralized/mgm2/AgentBehaviour.scala b/src/main/scala/org/scadcop/solver/decentralized/mgm2/AgentBehaviour.scala index d5f98e3..5dea133 100644 --- a/src/main/scala/org/scadcop/solver/decentralized/mgm2/AgentBehaviour.scala +++ b/src/main/scala/org/scadcop/solver/decentralized/mgm2/AgentBehaviour.scala @@ -26,12 +26,22 @@ class AgentBehaviour(variable: Variable, debug = true - /** * Initially the agent has no task in the bundle */ startWith(Init, new MGM2Mind()) + /** + * Reject some offers + */ + def rejectOffers(offers: List[Offer]): Unit = + offers.foreach{ offer: Offer => + val neighbour: Variable = offer.offererVariable + if (trace) println(s"$variable -> $neighbour : Reject($offer)") + directory.addressOf(neighbour) ! Reject(offer) + } + + /** * Either the agent is in the initial state */ @@ -57,14 +67,14 @@ class AgentBehaviour(variable: Variable, */ when(Continue) { - //when the supervisor tells it to stop - case Event(StopAlgo, mind) => { + //When the supervisor tells it to stop + case Event(StopAlgo, mind) => if (debug) println(s"$variable in $stateName has StopAlgo") goto(Final) using mind - } - //when the supervisor tells it to continue - case Event(ContinueAlgo, mind) => { + + //When the supervisor tells it to continue + case Event(ContinueAlgo, mind) => if (debug) println(s"$variable in $stateName has received ContinueAlgo") val updatedMind = mind.reset(variable) // performing a reset if (trace) println(s"$variable -> All : InformValue(${updatedMind.context.getValue(variable).get})") @@ -74,33 +84,29 @@ class AgentBehaviour(variable: Variable, directory.addressOf(variable) ! ChooseSubset(b) unstashAll goto(WaitingForRole) using updatedMind - } - //when the partner from previous round tells it to Go - case Event(GiveGo(_), mind) => { + // When the partner from previous round tells it to Go + case Event(GiveGo(_), mind) => if (debug) println(s"$variable in $stateName has received GiveGo") stay using mind - } - //when the partner from previous round tells it to not Go - case Event(GiveNoGo, mind) => { + // When the partner from previous round tells it to not Go + case Event(GiveNoGo, mind) => if (debug) println(s"$variable in $stateName has received GiveNoGo") stay using mind - } - //when the partner gets an informValue - case Event(InformValue(_), mind) => { + // When the partner gets an informValue + case Event(InformValue(_), mind) => if (debug) println(s"$variable in $stateName has received InformValue") stash stay using mind - } - } /** * Either the agent is in the WaitingForRole state */ when(WaitingForRole){ + // When it receives an InformValue case Event(InformValue(_),mind) => if (debug) println(s"$variable in $stateName has received InformValue") @@ -142,7 +148,7 @@ class AgentBehaviour(variable: Variable, if (debug) println(s"$variable: the value of $peerVariable is $peerValue " + s"(${updatedMind.context.size-1}/${neighbours.size})") val potentialPartner: Variable = updatedMind.choosePartner(neighbours) - updatedMind = updatedMind.setPartner(variable, peerVariable) + updatedMind = updatedMind.setPartner(peerVariable) if (debug) println(s"$variable> context before computing the joint offer=${updatedMind.currentContext}") val moves: List[BilateralMove] = updatedMind.computeJointOffer(potentialPartner, neighbours, constraints) val offer: Offer = new Offer(variable, moves) @@ -185,27 +191,31 @@ class AgentBehaviour(variable: Variable, if (debug) println(s"$variable in $stateName has received Accept") val newPartner: Variable = directory.variableOf(sender) val move : Move = offer.moves.head - val updatedMind: MGM2Mind = mind.fullyCommit(variable, newPartner, offer) + val updatedMind: MGM2Mind = mind.commitFully(newPartner, offer) if (trace) println(s"$variable -> All : InformDelta(${updatedMind.deltas(variable)})") broadcast(InformDelta(updatedMind.deltas(variable))) unstashAll goto(Committed) using updatedMind - //when it receives a refusal from its potential partner - case Event(Reject(_), mind) => //TODO check sender partner + // When it receives a refusal from its potential partner + case Event(Reject(_), mind) if directory.variableOf(sender) == mind.partner.get => //TODO check sender partner if (debug) println(s"$variable in $stateName has received Reject") - var updatedMind = mind.uncommit(variable) + var updatedMind = mind.uncommit() val (bestMove, bestDelta) = updatedMind.bestUnilateralMove(variable, constraints) val bestOffer = bestMove match { case Some(m) => Some(new Offer(variable, List(m))) case None => None } updatedMind = updatedMind.updateDeltas(variable: Variable, bestDelta) - updatedMind = updatedMind.setCurrBestOffer(variable, bestOffer) + updatedMind = updatedMind.setCurrBestOffer(bestOffer) if (trace) println(s"$variable -> All : InformDelta(${updatedMind.deltas(variable)})") broadcast(InformDelta(updatedMind.deltas(variable))) unstashAll goto(Uncommitted) using updatedMind + + // TODO When it receives a refusal from a peer which is not a potential partner + case Event(Reject(_), mind) if directory.variableOf(sender) != mind.partner.get => + stay using mind } /** @@ -225,7 +235,7 @@ class AgentBehaviour(variable: Variable, if (debug) println(s"$variable in $stateName has received InformValue and the context is full.") val peerVariable = directory.variableOf(sender) var updatedMind: MGM2Mind = mind.updateContext(variable, peerVariable, peerValue) - updatedMind = updatedMind.setPartner(variable, updatedMind.choosePartner(neighbours) ) + updatedMind = updatedMind.setPartner(updatedMind.choosePartner(neighbours)) if (debug) println(s"$variable: the value of $peerVariable is $peerValue (${updatedMind.context.size-1}/${neighbours.size})") unstashAll goto(ReceiverWaitingOffers) using updatedMind @@ -245,20 +255,20 @@ class AgentBehaviour(variable: Variable, // When offers are still missing case Event(MakeOffer(eventualOffer), mind) if mind.nbReceivedOffers < neighbours.size-1 => if (debug) println(s"$variable in $stateName has received MakeOffer and the context is partial.") - val updatedMind: MGM2Mind = mind.addOffer(variable, eventualOffer) + val updatedMind: MGM2Mind = mind.addOffer(eventualOffer) stay using updatedMind // When the last offer is received case Event(MakeOffer(eventualOffer), mind) if mind.nbReceivedOffers == neighbours.size-1 => if (debug) println(s"$variable in $stateName has received MakeOffer and the context is full.") - var updatedMind: MGM2Mind = mind.addOffer(variable, eventualOffer) + var updatedMind: MGM2Mind = mind.addOffer(eventualOffer) val (bestOffer, bestDelta) = updatedMind.chooseBestSingleOffer(variable, neighbours, constraints) updatedMind = updatedMind.updateDeltas(variable, bestDelta) val partner : Option[Variable]= bestOffer match { case Some(o) => Some(o.offererVariable) case None => None } - updatedMind = updatedMind.setCurrBestOffer(variable, bestOffer) + updatedMind = updatedMind.setCurrBestOffer(bestOffer) if (trace) println(s"$variable -> $variable : BestOffer($bestOffer)") self ! BestOffer(bestOffer) unstashAll @@ -287,9 +297,8 @@ class AgentBehaviour(variable: Variable, if (debug) println(s"$variable in $stateName has received BestOffer") if (trace) println(s"$variable -> ${bestOffer.offererVariable} : Accept($bestOffer)") directory.addressOf(bestOffer.offererVariable) ! Accept(bestOffer) - val updatedMind: MGM2Mind = mind.fullyCommit(variable, bestOffer.offererVariable, bestOffer) - if (trace) println(s"$variable -> All except ${updatedMind.partner} : Reject(someOffer)") - updatedMind.rejectAllUselessOffers(directory, Some(bestOffer)) //decline all other offers + val updatedMind: MGM2Mind = mind.commitFully(bestOffer.offererVariable, bestOffer) + rejectOffers(updatedMind.receivedOffers.filterNot(_ == bestOffer))//decline all other offers if (trace) println(s"$variable -> All : InformDelta(${updatedMind.deltas(variable)})") broadcast(InformDelta(updatedMind.deltas(variable))) //inform all neighbours unstashAll @@ -298,9 +307,9 @@ class AgentBehaviour(variable: Variable, // When there is no coordinated move a unilateral move is performed case Event(BestOffer(None), mind) => if (debug) println(s"$variable in $stateName has received BestOffer(empty)") - val updatedMind: MGM2Mind = mind.uncommit(variable) + val updatedMind: MGM2Mind = mind.uncommit() if (trace) println(s"$variable -> All : Reject(someOffer)") - updatedMind.rejectAllUselessOffers(directory, None) //decline all offers + rejectOffers(updatedMind.receivedOffers) //decline all offers if (trace) println(s"$variable -> All : InformDelta(${updatedMind.deltas(variable)})") broadcast(InformDelta(updatedMind.deltas(variable))) //inform all neighbours unstashAll @@ -329,7 +338,7 @@ class AgentBehaviour(variable: Variable, val neighbour: Variable = directory.variableOf(sender) val updatedMind: MGM2Mind = mind.updateDeltas(neighbour: Variable, delta: Double) val shouldIact: Boolean = updatedMind.amIBest(variable) - var bestOffer: Option[Offer] = updatedMind.currBestOffer match { + val bestOffer: Option[Offer] = updatedMind.currBestOffer match { case Some(o) => Some(o) case None => throw new RuntimeException(s"Error $variable should have a best offer in $stateName") } @@ -354,14 +363,14 @@ class AgentBehaviour(variable: Variable, if (debug) println(s"$variable in $stateName has received MakeOffer") stay using mind - //when it receives a neighbour's delta and the neighbourDeltas is partial + // When it receives a neighbour's delta and the neighbourDeltas is partial case Event(InformDelta(delta), mind) if mind.deltas.size < neighbours.size => if (debug) println(s"$variable in $stateName has received InformDelta (${mind.deltas.size}/${neighbours.size}) and the context is partial.") val neighbour: Variable = directory.variableOf(sender) val updatedMind: MGM2Mind = mind.updateDeltas(neighbour: Variable, delta: Double) stay using updatedMind - //when it receves a neighbour's delta and the context is full + // When it receives a neighbour's delta and the context is full case Event(InformDelta(delta), mind) if mind.deltas.size == neighbours.size => if (debug) println(s"$variable in $stateName has received InformDelta (${mind.deltas.size}/${neighbours.size})and the context is full.") val neighbour: Variable = directory.variableOf(sender) @@ -387,7 +396,8 @@ class AgentBehaviour(variable: Variable, * Either the agent is in the ActSolo state */ when(ActSolo){ - //when it should act because it has the highest delta in the neighbourhood + + // When it should act because it has the highest delta in the neighbourhood case Event(Act(true, move), mind) => if (debug) println(s"$variable in $stateName has received Act(true)") val newVal: Value = mind.updateVal(variable, move) @@ -396,7 +406,7 @@ class AgentBehaviour(variable: Variable, //supervisor ! InformValue(updatedMind.context.getValue(variable).get) goto(Continue) using updatedMind - //when it should not act because it does not have the highest delta in the neighbourhood + // When it should not act because it does not have the highest delta in the neighbourhood case Event(Act(false, _), mind) => if (debug) println(s"$variable in $stateName has received Act(false)") if (trace) println(s"$variable -> $supervisor : I didn't change = InformValue(${mind.context.getValue(variable).get})") @@ -408,16 +418,16 @@ class AgentBehaviour(variable: Variable, * Either the agent is in the GivingPartnerGoNogo state */ when(GivingPartnerGoNogo){ - //when it receives its own acting decision and should not act - case Event(Act(false, _), mind) => { + + // When it receives its own acting decision and should not act + case Event(Act(false, _), mind) => if (debug) println(s"$variable in $stateName has received Act(false)") if (trace) println(s"$variable -> $supervisor : I didn't change = InformValue(${mind.context.getValue(variable).get})") supervisor ! InformValue(mind.context.getValue(variable).get) goto(Continue) using mind - } - //when it receives its own acting decision and should act - case Event(Act(true, move), mind) => { + // When it receives its own acting decision and should act + case Event(Act(true, move), mind) => if (debug) println(s"$variable in $stateName has received Act(true)") unstashAll val partner: Variable = mind.partner match { @@ -427,29 +437,27 @@ class AgentBehaviour(variable: Variable, if (trace) println(s"$variable -> ${directory.addressOf(partner)} : GiveGo($move)") directory.addressOf(partner) ! GiveGo(move) goto(HandlingPartnersGoNogo) using mind - } - //when its partner tells it to go - case Event(GiveGo(_), mind) => { + // When its partner tells it to go + case Event(GiveGo(_), mind) => if (debug) println(s"$variable in $stateName has received GiveGo") stash stay using mind - } - //when its partner tells it not to go - case Event(GiveNoGo, mind) => { + // When its partner tells it not to go + case Event(GiveNoGo, mind) => if (debug) println(s"$variable in $stateName has received GiveNoGo") stash stay using mind - } } /** * Either the agent is in the GivingPartnerGoNogo state */ when(HandlingPartnersGoNogo){ - //when it receives a Go from its partner - case Event(GiveGo(move), mind) => { + + // When it receives a Go from its partner + case Event(GiveGo(move), mind) => if (debug) println(s"$variable in $stateName has received Trigger") val newVal: Value = mind.updateVal(variable, move) val updatedMind: MGM2Mind = new MGM2Mind(context = mind.context.fix(variable, newVal), @@ -460,8 +468,8 @@ class AgentBehaviour(variable: Variable, if (trace) println(s"$variable -> $supervisor : I'm changing = InformValue(${updatedMind.context.getValue(variable).get})") supervisor ! InformValue(updatedMind.context.getValue(variable).get) goto(Continue) using updatedMind - } - //when it receives a NoGo from its partner + + // When it receives a NoGo from its partner case Event(GiveNoGo, mind) => { if (debug) println(s"$variable in $stateName has received GiveNoGo") if (trace) println(s"$variable -> $supervisor : I'm not changing = InformValue(${mind.context.getValue(variable).get})") @@ -475,22 +483,26 @@ class AgentBehaviour(variable: Variable, * Whatever the state is **/ whenUnhandled { + // If the agent is killed case Event(Query, mind) => sender ! Inform(mind.metric) context.stop(self) stay using mind + // If the agent is enlightened with the acquaintances it is no more blind case Event(Light(directory), mind) => supervisor = sender this.directory = directory sender ! Ready stay using mind + // If the agent must trace the protocol case Event(Trace, mind) => if (debug) println("Agent receives Trace") this.trace = true stay using mind + // Other case Event(msg @ _, _) => throw new RuntimeException(s"Error $variable was not expected message $msg in state $stateName") diff --git a/src/main/scala/org/scadcop/solver/decentralized/mgm2/MGM2Mind.scala b/src/main/scala/org/scadcop/solver/decentralized/mgm2/MGM2Mind.scala index 6eecb11..3a1b53d 100644 --- a/src/main/scala/org/scadcop/solver/decentralized/mgm2/MGM2Mind.scala +++ b/src/main/scala/org/scadcop/solver/decentralized/mgm2/MGM2Mind.scala @@ -223,7 +223,7 @@ class MGM2Mind(val context : Context = new Context(), /* * Add an offer */ - def addOffer(variable: Variable, newOffer: Offer): MGM2Mind = { + def addOffer(newOffer: Offer): MGM2Mind = { new MGM2Mind(context, isCommitted, partner, @@ -238,7 +238,7 @@ class MGM2Mind(val context : Context = new Context(), /** * Set partner */ - def setPartner(variable: Variable, newPartner: Variable) : MGM2Mind = { + def setPartner(newPartner: Variable): MGM2Mind = { new MGM2Mind(context, isCommitted, Some(newPartner), @@ -252,7 +252,7 @@ class MGM2Mind(val context : Context = new Context(), /** * Set current best offer */ - def setCurrBestOffer(variable: Variable, newOffer: Option[Offer]) : MGM2Mind = { + def setCurrBestOffer(newOffer: Option[Offer]): MGM2Mind = { new MGM2Mind(context, isCommitted, partner, @@ -266,7 +266,7 @@ class MGM2Mind(val context : Context = new Context(), /** * Set commitment */ - def uncommit(variable: Variable) : MGM2Mind = { + def uncommit(): MGM2Mind = { new MGM2Mind(context, isCommitted = false, partner = None, @@ -280,7 +280,7 @@ class MGM2Mind(val context : Context = new Context(), /** * Set commitment */ - def fullyCommit(variable: Variable, newPartner: Variable, newOffer: Offer): MGM2Mind = { + def commitFully(newPartner: Variable, newOffer: Offer): MGM2Mind = { new MGM2Mind(context, isCommitted = true, partner = Some(newPartner), @@ -291,18 +291,4 @@ class MGM2Mind(val context : Context = new Context(), currBestOffer = Some(newOffer)) } - /** - * Reject all the offers from a set of received offers except maybe one (or none) - */ - //??? type - def rejectAllUselessOffers(directory: Directory, acceptedOffer: Option[Offer]): Unit = { - val rejectedOffers = acceptedOffer match { - case Some(o) => receivedOffers.filter(_ != o) - case None => receivedOffers - } - rejectedOffers.foreach{ offer: Offer => - val neighbour: Variable = offer.offererVariable - directory.addressOf(neighbour) ! Reject(offer) - } - } } -- GitLab