From f666539d28a1208c9b82134e4d5f915b2e2c2846 Mon Sep 17 00:00:00 2001
From: Maxime MORGE <maxime.morge@univ-lille.fr>
Date: Thu, 24 Oct 2024 16:24:00 +0200
Subject: [PATCH] Start implementing CBAA

---
 README.md                                     |  2 +-
 src/main/scala/org/scata/algorithm/CBAA.scala | 49 ++++++++++---------
 src/main/scala/org/scata/core/Worker.scala    |  8 ++-
 3 files changed, 34 insertions(+), 25 deletions(-)

diff --git a/README.md b/README.md
index 53f0fb2..41e842c 100755
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-## What is SMASTA+ ?
+## What is SCATA ?
 
 SCATA is a Scala implementation of the Consensus-Based Algorithms for Task Allocation.
 
diff --git a/src/main/scala/org/scata/algorithm/CBAA.scala b/src/main/scala/org/scata/algorithm/CBAA.scala
index ad01422..b11eb46 100644
--- a/src/main/scala/org/scata/algorithm/CBAA.scala
+++ b/src/main/scala/org/scata/algorithm/CBAA.scala
@@ -1,7 +1,7 @@
 // Copyright (C) Maxime MORGE, 2024
 package org.scata.algorithm
 
-import org.scata.core.{SingleAssignmentProblem, Task, Worker}
+import org.scata.core._
 
 /**
  * The Consensus-Based Auction Algorithm (CBAA) is
@@ -9,28 +9,32 @@ import org.scata.core.{SingleAssignmentProblem, Task, Worker}
  */
 class CBAA(pb : SingleAssignmentProblem) {
 
-  var neighbours : Map[Worker, List[Worker]] = fullyConnected()
+  var neighbours : Map[Worker, List[Worker]] = Map[Worker, List[Worker]]()
+ /* pb.workers.foreach{ worker =>
+    neighbours = neighbours.updated(worker, pb.workers.toList)
+ }*/
 
-  var workerTaskList: Map[(Worker, Task), Boolean] = Map[(Worker, Task), Boolean]()
-  var winningBid : Map[(Worker, Task), Int] = Map[(Worker, Task), Int]()
+  private var workerTaskList: Map[Worker, Map[Task, Boolean]] = pb.workers.toList.map { worker =>
+    worker -> pb.tasks.toList.map { task =>
+      task -> false
+    }.toMap
+  }.toMap
 
-  pb.workers.foreach{ worker=>
-    pb.tasks.foreach{ task =>
-      workerTaskList = workerTaskList.updated((worker, task), false)
-      winningBid = winningBid.updated((worker, task), 0)
-    }
-  }
+  private var winningBid: Map[Worker, Map[Task, (Worker, Int)]] = pb.workers.toList.map { worker =>
+    worker -> pb.tasks.toList.map { task =>
+      task -> (NoWorker, 0)
+    }.toMap
+  }.toMap
 
   /**
    * Generate a fully connect communication network
    */
-  private def fullyConnected() :  Map[Worker, List[Worker]] = {
-    var neighbour = Map[Worker, List[Worker]]()
-    pb.workers.foreach{ worker =>
-      neighbour = neighbour.updated(worker, pb.workers.toList)
-    }
-    neighbour
-  }
+  //private def fullyConnected :  Map[Worker, List[Worker]] =
+
+  /**
+   * Returns true if the worker has no task assigned
+   */
+  private def isFree(worker : Worker) : Boolean = !pb.tasks.exists(task => workerTaskList(worker)(task))
 
   /**
    * Checks if two workers are neighbors
@@ -38,8 +42,7 @@ class CBAA(pb : SingleAssignmentProblem) {
    * @param worker2 the second worker
    * @return true if they are neighbors, false otherwise
    */
-  def isNeighbor(worker1: Worker, worker2: Worker): Boolean = neighbours(worker1).contains(worker2)
-
+  private def isNeighbor(worker1: Worker, worker2: Worker): Boolean = neighbours(worker1).contains(worker2)
 
   /**
    * CBAA Phase 1 for worker i
@@ -49,12 +52,12 @@ class CBAA(pb : SingleAssignmentProblem) {
   def selectTask(i : Int) : Unit = {
     val worker = pb.workers.toIndexedSeq(i)
     // Check if the worker has no tasks assigned
-    if (!pb.tasks.exists(task => workerTaskList((worker, task)))) {
+    if (isFree(worker)) {
 
       // Determine valid tasks based on cost comparison
       var validTasks: Map[Task, Boolean] = Map[Task, Boolean]()
       pb.tasks.foreach { task =>
-        if (pb.cost(worker, task) <= winningBid(worker, task)) {
+        if (pb.cost(worker, task) < winningBid(worker)(task)._2) {
           validTasks = validTasks.updated(task, true)
         } else {
           validTasks = validTasks.updated(task, false)
@@ -63,8 +66,8 @@ class CBAA(pb : SingleAssignmentProblem) {
       // If there are valid tasks, select the one with the minimum cost
       if (pb.tasks.exists(task => validTasks(task))) {
         val bestTask = validTasks.filter(_._2).keys.minBy(task => pb.cost(worker, task))
-        workerTaskList = workerTaskList.updated((worker, bestTask), true)
-        winningBid = winningBid.updated((worker, bestTask), pb.cost(worker, bestTask))
+        workerTaskList(worker) = workerTaskList(worker).updated(bestTask, true)
+        winningBid(worker) = winningBid(worker).updated(bestTask, (worker, pb.cost(worker, bestTask)))
       }
     }
   }
diff --git a/src/main/scala/org/scata/core/Worker.scala b/src/main/scala/org/scata/core/Worker.scala
index d05a470..5f73ebb 100644
--- a/src/main/scala/org/scata/core/Worker.scala
+++ b/src/main/scala/org/scata/core/Worker.scala
@@ -5,7 +5,7 @@ package org.scata.core
   * Class representing a worker
   * @param name of the worker
   */
-final class Worker(val name : String) extends Ordered[Worker]{
+class Worker(val name : String) extends Ordered[Worker]{
 
   override def toString: String = name
 
@@ -27,3 +27,9 @@ final class Worker(val name : String) extends Ordered[Worker]{
   }
 }
 
+/**
+ * The default worker
+ */
+object NoWorker extends Worker("NoWorker"){
+  override def toString: String = "NoWorker"
+}
-- 
GitLab