Skip to content
Snippets Groups Projects
Commit 4404221f authored by Maxime Morge's avatar Maxime Morge :construction_worker:
Browse files

Add MultiAssignement

parent d088dc44
No related branches found
No related tags found
No related merge requests found
// Copyright (C) Maxime MORGE 2024
import org.scata.core.SingleAssignmentProblem
import org.scata.core.AssignmentProblem
import org.scata.algorithm.CBAA
import org.scata.patrol.Environment
......@@ -7,7 +7,7 @@ object Main {
def main(args: Array[String]): Unit = {
val nbRobots= 4
val nbTargets = 3
val nbTargets = 4
val env = Environment.randomEnvironment(nbRobots, nbTargets)
println(env)
val pb = env.toSAP()
......
......@@ -6,7 +6,7 @@ import org.scata.core._
* The Consensus-Based Auction Algorithm (CBAA) is
* a single-assignment strategy
*/
class CBAA(pb : SingleAssignmentProblem) {
class CBAA(pb : AssignmentProblem) {
private val debug = true
// Generate a fully connected communication network
......
......@@ -10,9 +10,9 @@ import org.scata.utils.RandomUtils
* @param workers are the workers
* @param tasks are the tasks
*/
class SingleAssignmentProblem(val workers: SortedSet[Worker],
val tasks : SortedSet[Task],
val cost : Map[(Worker,Task), Int]) {
class AssignmentProblem(val workers: SortedSet[Worker],
val tasks : SortedSet[Task],
val cost : Map[(Worker,Task), Int]) {
/**
* Returns a string describing the MASTAPlus problem
......@@ -47,7 +47,7 @@ class SingleAssignmentProblem(val workers: SortedSet[Worker],
/**
* Factory for SingleAssignmentProblem
*/
object SingleAssignmentProblem{
object AssignmentProblem{
implicit val order : Ordering[Double] = Ordering.Double.TotalOrdering
// eventually Ordering.Double.IeeeOrdering
......@@ -59,7 +59,7 @@ object SingleAssignmentProblem{
* @param m nodes
* @param n tasks
*/
def randomProblem(m: Int, n: Int): SingleAssignmentProblem = {
def randomProblem(m: Int, n: Int): AssignmentProblem = {
// Workers
val workers: SortedSet[Worker] = collection.immutable.SortedSet[Worker]() ++
(for (i <- 1 to m) yield new Worker(name = "w%02d".format(i)))
......@@ -75,6 +75,6 @@ object SingleAssignmentProblem{
cost = cost.updated((worker, task), RandomUtils.random(1, MAX_COST))
}
}
new SingleAssignmentProblem(workers, tasks, cost)
new AssignmentProblem(workers, tasks, cost)
}
}
// Copyright (C) Maxime MORGE, 2024
package org.scata.core
import scala.math.Ordering.Implicits.seqOrdering
/**
* Class representing an allocation as
* a multi-assignment of tasks to workers.
*
* @param pb is a multiple-assignment instance
*/
class MultipleAssignment(val pb: AssignmentProblem) {
var bundle: Map[Worker, List[Task]] = pb.workers.map(w => w -> List.empty[Task]).toMap
override def toString: String =
pb.workers.toList.map(worker => s"$worker: ${bundle(worker).mkString(", ")}").mkString("\n")
override def equals(that: Any): Boolean =
that match {
case that: MultipleAssignment => that.canEqual(this) && this.bundle == that.bundle
case _ => false
}
override def hashCode(): Int = this.bundle.hashCode()
def canEqual(a: Any): Boolean = a.isInstanceOf[MultipleAssignment]
/**
* Returns a deep copy
*/
@throws(classOf[RuntimeException])
private def copy(): MultipleAssignment = {
val assignment = new MultipleAssignment(pb)
this.bundle.foreach {
case (worker: Worker, tasks: List[Task]) =>
assignment.bundle = assignment.bundle.updated(worker, tasks)
case _ => throw new RuntimeException("Not able to copy bundle")
}
assignment
}
/**
* Adds a task to the list assigned to a worker
*/
def update(worker: Worker, task: Task): MultipleAssignment = {
val allocation = this.copy()
val updatedTasks = allocation.bundle(worker) :+ task
allocation.bundle = allocation.bundle.updated(worker, updatedTasks)
allocation
}
/**
* Returns true if each task is assigned to no more than one worker
*/
private def isPartition: Boolean = {
val allTasks = bundle.values.flatten.toList
allTasks.distinct.size == allTasks.size
}
/**
* Returns true if the assignment is complete, i.e., every task is assigned to a worker
*/
private def isComplete: Boolean = {
val assignedTasks = bundle.values.flatten.toSet
pb.tasks.forall(assignedTasks.contains)
}
/**
* Returns true if the allocation is sound, i.e., a complete partition of the tasks
*/
def isSound: Boolean = isPartition && isComplete
/**
* Returns the worker which has the task in its bundle
*/
def worker(task: Task): Option[Worker] = {
bundle.find {
case (_, tasks) => tasks.contains(task)
}.map(_._1)
}
}
\ No newline at end of file
......@@ -8,7 +8,7 @@ import scala.collection.SortedSet
* a single-assignment of the tasks to some workers.
* @param pb is a single-assignment instance
*/
class SingleAssignment(val pb: SingleAssignmentProblem) {
class SingleAssignment(val pb: AssignmentProblem) {
var bundle: Map[Worker, Task] = Map[Worker, Task]()
......
// Copyright (C) Maxime MORGE, 2024
package org.scata.patrol
import org.scata.core.{SingleAssignmentProblem, Task, Worker}
import org.scata.core.SingleAssignmentProblem.MAX_COST
import org.scata.core.{AssignmentProblem, Task, Worker}
import org.scata.core.AssignmentProblem.MAX_COST
import scala.collection.SortedSet
import org.scata.utils.RandomUtils
......@@ -39,7 +39,7 @@ class Environment(val robots: SortedSet[Robot],
/**
* Generate a single assignment problem
*/
def toSAP(): SingleAssignmentProblem = {
def toSAP(): AssignmentProblem = {
if (n > m)
throw new RuntimeException("Cannot generate a single assignment problem since there are more targets than robots")
......@@ -62,7 +62,7 @@ class Environment(val robots: SortedSet[Robot],
((worker, task), distance.toInt)
}).toMap
new SingleAssignmentProblem(workers, tasks, cost)
new AssignmentProblem(workers, tasks, cost)
}
}
......@@ -74,8 +74,8 @@ object Environment{
implicit val order : Ordering[Double] = Ordering.Double.TotalOrdering
// eventually Ordering.Double.IeeeOrdering
private val MAX_X : Int = 10 // Maximum width
private val MAX_Y : Int = 10 // Maximum height
private val MAX_X : Int = 20 // Maximum width
private val MAX_Y : Int = 20 // Maximum height
/**
* Returns a random single-assignment problem instance with
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment