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