Skip to content
Snippets Groups Projects
Commit 5766e981 authored by Maxime MORGE's avatar Maxime MORGE :construction_worker:
Browse files

Start VDS refactoring

parent ffb0eb45
No related branches found
No related tags found
No related merge requests found
Showing
with 248 additions and 52 deletions
// Copyright (C) Maxime MORGE 2020, 2022 // Copyright (C) Maxime MORGE 2020, 2022, 2023, 2024
package org.smastaplus.balancer.local package org.smastaplus.balancer.local
import org.smastaplus.core._ import org.smastaplus.core._
import org.smastaplus.process.{SingleDelegation, SingleSwap} import org.smastaplus.process.{SingleDelegation, SingleSwap, Swap}
/** /**
* Hill-climbing balancer * Hill-climbing balancer
...@@ -20,6 +20,7 @@ class HillClimbingBalancer(stap: STAP, rule: SocialRule, name: String = "HillCli ...@@ -20,6 +20,7 @@ class HillClimbingBalancer(stap: STAP, rule: SocialRule, name: String = "HillCli
*/ */
def highValueSuccessor(current: Allocation): Allocation = { def highValueSuccessor(current: Allocation): Allocation = {
var bestAllocation = new Allocation(stap) var bestAllocation = new Allocation(stap)
var bestSwap : Option[Swap] = None
var bestValue = Double.MaxValue var bestValue = Double.MaxValue
stap.ds.computingNodes.foreach { initiator => // Foreach initiator stap.ds.computingNodes.foreach { initiator => // Foreach initiator
current.bundle(initiator).foreach { task => // Foreach task in its bundle current.bundle(initiator).foreach { task => // Foreach task in its bundle
...@@ -34,6 +35,7 @@ class HillClimbingBalancer(stap: STAP, rule: SocialRule, name: String = "HillCli ...@@ -34,6 +35,7 @@ class HillClimbingBalancer(stap: STAP, rule: SocialRule, name: String = "HillCli
} }
if (nextValue <= bestValue) { if (nextValue <= bestValue) {
nbSuccessfulDelegation += 1 nbSuccessfulDelegation += 1
bestSwap = Some(delegation)
bestAllocation = nextAllocation bestAllocation = nextAllocation
bestValue = nextValue bestValue = nextValue
} }
...@@ -49,6 +51,7 @@ class HillClimbingBalancer(stap: STAP, rule: SocialRule, name: String = "HillCli ...@@ -49,6 +51,7 @@ class HillClimbingBalancer(stap: STAP, rule: SocialRule, name: String = "HillCli
} }
if (nextValue <= bestValue) { if (nextValue <= bestValue) {
nbSuccessfulSwap += 1 nbSuccessfulSwap += 1
bestSwap = Some(swap)
bestAllocation = nextAllocation bestAllocation = nextAllocation
bestValue = nextValue bestValue = nextValue
} }
...@@ -57,6 +60,7 @@ class HillClimbingBalancer(stap: STAP, rule: SocialRule, name: String = "HillCli ...@@ -57,6 +60,7 @@ class HillClimbingBalancer(stap: STAP, rule: SocialRule, name: String = "HillCli
} }
} }
} }
if (trace && bestSwap.nonEmpty) println(bestSwap.get)
bestAllocation bestAllocation
} }
......
...@@ -17,6 +17,7 @@ abstract class LocalBalancer(stap: STAP, rule: SocialRule, name: String = "Local ...@@ -17,6 +17,7 @@ abstract class LocalBalancer(stap: STAP, rule: SocialRule, name: String = "Local
withSwap: Boolean = false) withSwap: Boolean = false)
extends Balancer(stap,rule, name) { extends Balancer(stap,rule, name) {
var trace = false
// Specific metrics // Specific metrics
var initializationTime : Long = 0 var initializationTime : Long = 0
var initialLocalRatio = 0.0 var initialLocalRatio = 0.0
......
// Copyright (C) Anne-Cécile CARON, Maxime MORGE 2023, 2024
package org.smastaplus.balancer.local package org.smastaplus.balancer.local
import org.smastaplus.core.{Allocation, GlobalFlowtime, LocalFlowtime, Makespan, STAP, SocialRule} import org.smastaplus.core.{Allocation, GlobalFlowtime, STAP, SocialRule}
import org.smastaplus.process.{Deal, SingleDelegation, SingleSwap} import org.smastaplus.process.{Deal, SingleDelegation, SingleSwap}
import scala.annotation.tailrec
/** /**
* * VDS (variable depth search) is a generalization of the local search
* method which adaptively change the size of neighborhood
* @param stap instance to tackle * @param stap instance to tackle
* @param rule is the social rule to be applied * @param rule is the social rule to be applied
* @param name of the balancer * @param name of the balancer
* @param withSwap is true if swap are allowed * @param withSwap is true if swap are allowed
* @param alpha
* See Mutsunori Yagiura, Takashi Yamaguchi and Toshihide Ibaraki.
* "A variable depth search algorithm for the generalized assignment problem"
* Proc. of 2nd International Conference on Metaheuristics, 1997
* *
* Inspired by Algo VDS in MIC97 "A variable depth search algorithm for the generalized assignment problem" * The best feasible solution is estimated with the global flowtime
* Authors : Mutsunori Yagiura, Takashi Yamaguchi and Toshihide Ibaraki
*
* best feasible solution is estimated with Global Flowtime
* cost(alloc) = local flowtime, so needs to know the 2 contractors * cost(alloc) = local flowtime, so needs to know the 2 contractors
* pcost(alloc) = cost(alloc) + alpha * global flowtime * pcost(alloc) = cost(alloc) + alpha * global flowtime
* *
...@@ -22,16 +27,16 @@ class VDSBalancer (stap: STAP, rule: SocialRule = GlobalFlowtime, name: String = ...@@ -22,16 +27,16 @@ class VDSBalancer (stap: STAP, rule: SocialRule = GlobalFlowtime, name: String =
withSwap: Boolean = false, alpha: Double = 0.5) withSwap: Boolean = false, alpha: Double = 0.5)
extends LocalBalancer(stap, rule, name, withSwap) { extends LocalBalancer(stap, rule, name, withSwap) {
var newBestAlloc: Boolean = false private var newBestAllocation: Boolean = false //
var bestAllocForCost : Allocation = null private var bestAllocationForCost : Allocation = null
var bestCost : Double = Double.MaxValue private var bestCost : Double = Double.MaxValue
/** /**
* *
* compute the cost of an allocation, i.e. the local flowtime between two contractors of a deal * Compute the cost of an allocation, i.e. the local flowtime between two contractors of a deal
*/ */
def cost(allocation: Allocation, deal: Deal): Double = { def cost(allocation: Allocation, deal: Deal): Double = {
val node1 = deal.contractors(0) val node1 = deal.contractors.head
val node2 = deal.contractors(1) val node2 = deal.contractors(1)
// local flowtime between node1 and node2 // local flowtime between node1 and node2
allocation.jobs.foldLeft(0.0) { (sum, job) => sum + Math.max(allocation.completionTime(job, node1), allocation.completionTime(job, node2)) } allocation.jobs.foldLeft(0.0) { (sum, job) => sum + Math.max(allocation.completionTime(job, node1), allocation.completionTime(job, node2)) }
...@@ -41,7 +46,7 @@ class VDSBalancer (stap: STAP, rule: SocialRule = GlobalFlowtime, name: String = ...@@ -41,7 +46,7 @@ class VDSBalancer (stap: STAP, rule: SocialRule = GlobalFlowtime, name: String =
* *
* compute the "penalized" cost of an allocation, i.e. the local flowtime between two contractors of a deal, penalized by global flowtime * compute the "penalized" cost of an allocation, i.e. the local flowtime between two contractors of a deal, penalized by global flowtime
*/ */
def pcost(allocation: Allocation, deal: Deal): Double = def penalizedCost(allocation: Allocation, deal: Deal): Double =
cost(allocation, deal) + alpha * allocation.globalFlowtime cost(allocation, deal) + alpha * allocation.globalFlowtime
/** /**
...@@ -55,7 +60,7 @@ class VDSBalancer (stap: STAP, rule: SocialRule = GlobalFlowtime, name: String = ...@@ -55,7 +60,7 @@ class VDSBalancer (stap: STAP, rule: SocialRule = GlobalFlowtime, name: String =
* returns a neighbor better than the current allocation (the first encountered) * returns a neighbor better than the current allocation (the first encountered)
*/ */
def firstBetterNeighbor(current: Allocation, mycost: (Allocation, Deal) => Double, withSwap: Boolean, alreadyVisited : Set[Allocation]): Option[(Allocation, Deal)] = { def firstBetterNeighbor(current: Allocation, mycost: (Allocation, Deal) => Double, withSwap: Boolean, alreadyVisited : Set[Allocation]): Option[(Allocation, Deal)] = {
newBestAlloc = false newBestAllocation = false
stap.ds.computingNodes.foreach { initiator => // Foreach initiator stap.ds.computingNodes.foreach { initiator => // Foreach initiator
current.bundle(initiator).foreach { task => // Foreach task in its bundle current.bundle(initiator).foreach { task => // Foreach task in its bundle
(stap.ds.computingNodes diff Set(initiator)).foreach { responder => // Foreach responder (stap.ds.computingNodes diff Set(initiator)).foreach { responder => // Foreach responder
...@@ -66,9 +71,9 @@ class VDSBalancer (stap: STAP, rule: SocialRule = GlobalFlowtime, name: String = ...@@ -66,9 +71,9 @@ class VDSBalancer (stap: STAP, rule: SocialRule = GlobalFlowtime, name: String =
val currentValue = mycost(current, swap) val currentValue = mycost(current, swap)
val nextValue = mycost(nextAllocation, swap) val nextValue = mycost(nextAllocation, swap)
if (nextValue < currentValue && !alreadyVisited.contains(nextAllocation)) { if (nextValue < currentValue && !alreadyVisited.contains(nextAllocation)) {
bestAllocForCost = bestBetween(current, nextAllocation) bestAllocationForCost = bestBetween(current, nextAllocation)
bestCost = bestAllocForCost.globalFlowtime bestCost = bestAllocationForCost.globalFlowtime
if (bestCost > current.globalFlowtime) newBestAlloc = true else newBestAlloc = false if (bestCost > current.globalFlowtime) newBestAllocation = true else newBestAllocation = false
return Some((nextAllocation, swap)) return Some((nextAllocation, swap))
} }
} }
...@@ -78,9 +83,9 @@ class VDSBalancer (stap: STAP, rule: SocialRule = GlobalFlowtime, name: String = ...@@ -78,9 +83,9 @@ class VDSBalancer (stap: STAP, rule: SocialRule = GlobalFlowtime, name: String =
val nextValue = mycost(nextAllocation, gift) val nextValue = mycost(nextAllocation, gift)
val currentValue = mycost(current, gift) val currentValue = mycost(current, gift)
if (nextValue < currentValue && !alreadyVisited.contains(nextAllocation)) { if (nextValue < currentValue && !alreadyVisited.contains(nextAllocation)) {
bestAllocForCost = bestBetween(current, nextAllocation) bestAllocationForCost = bestBetween(current, nextAllocation)
bestCost = bestAllocForCost.globalFlowtime bestCost = bestAllocationForCost.globalFlowtime
if (bestCost > current.globalFlowtime) newBestAlloc = true else newBestAlloc = false if (bestCost > current.globalFlowtime) newBestAllocation = true else newBestAllocation = false
return Some((nextAllocation, gift)) return Some((nextAllocation, gift))
} }
} }
...@@ -95,7 +100,7 @@ class VDSBalancer (stap: STAP, rule: SocialRule = GlobalFlowtime, name: String = ...@@ -95,7 +100,7 @@ class VDSBalancer (stap: STAP, rule: SocialRule = GlobalFlowtime, name: String =
* returns the best neighbor of the current allocation w.r.t. mycost * returns the best neighbor of the current allocation w.r.t. mycost
*/ */
def bestNeighbor(current: Allocation, mycost: (Allocation, Deal) => Double, withSwap: Boolean, alreadyVisited : Set[Allocation]): Option[(Allocation, Deal)] = { def bestNeighbor(current: Allocation, mycost: (Allocation, Deal) => Double, withSwap: Boolean, alreadyVisited : Set[Allocation]): Option[(Allocation, Deal)] = {
newBestAlloc = false newBestAllocation = false
var bestAllocation : Allocation = null var bestAllocation : Allocation = null
var bestValue : Double = Double.MaxValue var bestValue : Double = Double.MaxValue
var bestDeal : Deal = null var bestDeal : Deal = null
...@@ -130,9 +135,9 @@ class VDSBalancer (stap: STAP, rule: SocialRule = GlobalFlowtime, name: String = ...@@ -130,9 +135,9 @@ class VDSBalancer (stap: STAP, rule: SocialRule = GlobalFlowtime, name: String =
} }
if (bestAllocation == null) None if (bestAllocation == null) None
else { else {
bestAllocForCost = bestBetween(current, bestAllocation) bestAllocationForCost = bestBetween(current, bestAllocation)
bestCost = bestAllocForCost.globalFlowtime bestCost = bestAllocationForCost.globalFlowtime
if (bestCost > current.globalFlowtime) newBestAlloc = true else newBestAlloc = false if (bestCost > current.globalFlowtime) newBestAllocation = true else newBestAllocation = false
Some((bestAllocation, bestDeal)) Some((bestAllocation, bestDeal))
} }
} }
...@@ -155,34 +160,35 @@ class VDSBalancer (stap: STAP, rule: SocialRule = GlobalFlowtime, name: String = ...@@ -155,34 +160,35 @@ class VDSBalancer (stap: STAP, rule: SocialRule = GlobalFlowtime, name: String =
} }
} }
def step2b(allocation: Allocation, alreadyVisited : Set[Allocation]): (Allocation, Set[Allocation]) = { private def step2b(allocation: Allocation, alreadyVisited : Set[Allocation]): (Allocation, Set[Allocation]) = {
val result1 = bestNeighbor(allocation, pcost, true, alreadyVisited) val result1 = bestNeighbor(allocation, penalizedCost, withSwap = true, alreadyVisited)
result1 match{ result1 match{
case Some((allocbis, _)) => (allocbis, alreadyVisited+allocbis) case Some((allocbis, _)) => (allocbis, alreadyVisited+allocbis)
case None => (allocation, alreadyVisited) case None => (allocation, alreadyVisited)
} }
} }
def variable_depth_search_step2(allocation: Allocation, alreadyVisited : Set[Allocation]): (Allocation, Set[Allocation]) ={ @tailrec
private def variable_depth_search_step2(allocation: Allocation, alreadyVisited : Set[Allocation]): (Allocation, Set[Allocation]) ={
// step 2a = a shift move // step 2a = a shift move
val step2a = bestNeighbor(allocation, pcost, false, alreadyVisited) val step2a = bestNeighbor(allocation, penalizedCost, withSwap = false, alreadyVisited)
step2a match { step2a match {
case Some((alloc, _)) => // step2b = sequence of swap moves case Some((alloc, _)) => // step2b = sequence of swap moves
if (newBestAlloc) //exit to step3 if (newBestAllocation) //exit to step3
variable_depth_search_step2(bestAllocForCost, alreadyVisited+bestAllocForCost+alloc) variable_depth_search_step2(bestAllocationForCost, alreadyVisited+bestAllocationForCost+alloc)
else { else {
var result1 = step2b(allocation, alreadyVisited+alloc) val result1 = step2b(allocation, alreadyVisited + alloc)
//val nextstep = step2b(alloc, alreadyVisited+alloc) //val nextstep = step2b(alloc, alreadyVisited+alloc)
result1 match { result1 match {
case (allocbis, visited) => case (allocBis, visited) =>
if (newBestAlloc) //step3 if (newBestAllocation) //step3
variable_depth_search_step2(bestAllocForCost, visited + bestAllocForCost) variable_depth_search_step2(bestAllocationForCost, visited + bestAllocationForCost)
else if (allocbis.equals(alloc) ) // return to step2a (i.e. try shif) else if (allocBis.equals(alloc) ) // return to step2a (i.e. try shift)
variable_depth_search_step2(allocbis, visited) variable_depth_search_step2(allocBis, visited)
else step2b(allocbis, visited+allocbis) else step2b(allocBis, visited+allocBis)
} }
} }
case None => (bestAllocForCost, alreadyVisited) // exit to step 3 ? case None => (bestAllocationForCost, alreadyVisited) // exit to step 3 ?
} }
} }
...@@ -197,24 +203,22 @@ class VDSBalancer (stap: STAP, rule: SocialRule = GlobalFlowtime, name: String = ...@@ -197,24 +203,22 @@ class VDSBalancer (stap: STAP, rule: SocialRule = GlobalFlowtime, name: String =
} }
/** /**
* step 1 : Generation of an initial solution * Returns an initial allocation
* * @note why we do not use a random one
* @param allocation
* @return
*/ */
override def init(allocation: Allocation): Allocation = { override def init(allocation: Allocation): Allocation = {
val initialAllocation = super.init(allocation) val initialAllocation = super.init(allocation)
bestCost = initialAllocation.globalFlowtime bestCost = initialAllocation.globalFlowtime
bestAllocForCost = initialAllocation bestAllocationForCost = initialAllocation
// LS modifies bestGF and bestAlloc : // LS modifies bestGF and bestAlloc :
val allocbisWithPath = LS(initialAllocation, pcost, false, Set[Allocation]()+initialAllocation) val allocbisWithPath = LS(initialAllocation, penalizedCost, withSwap = false, Set[Allocation]()+initialAllocation)
LS(allocbisWithPath._1, pcost, true,allocbisWithPath._2) LS(allocbisWithPath._1, penalizedCost, withSwap = true, allocbisWithPath._2)
bestAllocForCost bestAllocationForCost
} }
} }
/** /**
* companion object, for testing * Companion object for testing
*/ */
object VDSBalancer extends App { object VDSBalancer extends App {
val debug = false val debug = false
......
// Copyright (C) Maxime MORGE 2020, 2021 // Copyright (C) Maxime MORGE 2020, 2021, 2022, 2023, 2024
package org.smastaplus.process package org.smastaplus.process
import org.smastaplus.core._ import org.smastaplus.core._
......
...@@ -13,7 +13,7 @@ import org.smastaplus.strategy.deal.proposal.multi.ConcreteMultiProposalStrategy ...@@ -13,7 +13,7 @@ import org.smastaplus.strategy.deal.proposal.multi.ConcreteMultiProposalStrategy
*/ */
class CentralizedBalancerSpec extends AnyFlatSpec { class CentralizedBalancerSpec extends AnyFlatSpec {
behavior of "Decentralized balancer" behavior of "Centralized balancer"
"Reallocation should be" should "Reallocation should be" should
"be sound" in { "be sound" in {
......
// Copyright (C) Maxime MORGE 2020, 2021, 2022, 2023, 2024
package org.smastaplus.balancer.local
import akka.actor.ActorSystem
import org.scalatest.flatspec.AnyFlatSpec
import org.smastaplus.core._
import org.smastaplus.strategy.deal.counterproposal.single.NoneSingleCounterProposalStrategy
import org.smastaplus.strategy.deal.proposal.single.ConcreteConservativeProposalStrategy
/**
* Unit test for the hill climbing balancer with the first stap example
*/
class HillClimbingBalancerEx1Spec extends AnyFlatSpec {
import org.smastaplus.example.allocation.stap1.ex1lcjf._
import org.smastaplus.example.stap.ex1._
behavior of "Example 1 with the hill climbing balancer with swap"
"HillClimbingBalancer" should
"perform the delegation by the donor #3 to the recipient #2 of the task t3 and" +
" the delegation by the donor #1 to the recipient #3 of the task t7 and" in {
val balancer = new HillClimbingBalancer(stap, GlobalFlowtime, withSwap = true)
balancer.trace = true
//println(a)
val outcome = balancer.reallocate(a)
//println(outcome)
assert(
(outcome.bundle(cn1) == List(t7, t4, t1) &&
outcome.bundle(cn2) == List(t8, t5, t3, t2) &&
outcome.bundle(cn3) == List(t6, t9))
)
assert(outcome.globalFlowtime <= a.globalFlowtime)
}
}
\ No newline at end of file
// Copyright (C) Maxime MORGE 2020, 2021, 2022, 2023, 2024
package org.smastaplus.balancer.local
import org.scalatest.flatspec.AnyFlatSpec
import org.smastaplus.core._
/**
* Unit test for the hill climbing balancer with the first stap example
*/
class HillClimbingBalancerEx2Spec extends AnyFlatSpec {
import org.smastaplus.example.allocation.stap2.ex2lcjf._
import org.smastaplus.example.stap.ex2._
behavior of "Example 2 with the hill climbing balancer with swap"
"HillClimbingBalancer" should
"perform the swap by the donor #2 to the recipient #1 of the task t5 with the counterpart t1 and" +
"the delegation by the donor #2 to the recipient #3 of the task t8 and" +
"the delegation by the donor #3 to the recipient #2 of the task t3" in {
val balancer = new HillClimbingBalancer(stap, GlobalFlowtime, withSwap = true)
balancer.trace = true
println(a)
val outcome = balancer.reallocate(a)
println(outcome)
assert(
(outcome.bundle(cn1) == List(t7, t5, t4) &&
outcome.bundle(cn2) == List(t1, t2) &&
outcome.bundle(cn3) == List(t3, t8, t9, t6))
)
assert(outcome.globalFlowtime <= a.globalFlowtime)
}
}
\ No newline at end of file
// Copyright (C) Maxime MORGE 2020, 2021, 2022, 2023, 2024
package org.smastaplus.balancer.local
import org.scalatest.flatspec.AnyFlatSpec
import org.smastaplus.core._
/**
* Unit test for the hill climbing balancer
*/
class HillClimbingBalancerSpec extends AnyFlatSpec {
behavior of "HillClimbing balancer with swap"
"Reallocation should be" should
"be sound" in {
val l = 4 // with l jobs
val m = 4 // with m nodes
val n = 3 * l * m // with n tasks
val o = 1 // with o resources per tasks
val d = 3 // with d duplicated instances per resource
val pb = STAP.randomProblem(l = l, m = m, n = n, o, d , Uncorrelated)
val a = Allocation.randomAllocation(pb)
val balancer = new HillClimbingBalancer(pb, GlobalFlowtime, withSwap = true)
balancer.trace = false
val outcome = balancer.reallocate(a)
assert(outcome.isSound)
}
}
\ No newline at end of file
// Copyright (C) Maxime MORGE 2020, 2021, 2022, 2023, 2024
package org.smastaplus.balancer.local
import org.scalatest.flatspec.AnyFlatSpec
import org.smastaplus.core._
/**
* Unit test for the hill climbing balancer with the first stap example
*/
class VDSBalancerEx1Spec extends AnyFlatSpec {
import org.smastaplus.example.allocation.stap1.ex1lcjf._
import org.smastaplus.example.stap.ex1._
behavior of "Example 1 with the VDS balancer with swap"
"VDSBalancer" should
"perform TODO" in {
val balancer = new VDSBalancer(stap, GlobalFlowtime, withSwap = true)
balancer.trace = true
//println(a)
val outcome = balancer.reallocate(a)
//println(outcome)
assert(
(outcome.bundle(cn1) == List(t4, t3, t1) &&
outcome.bundle(cn2) == List(t8, t5, t2) &&
outcome.bundle(cn3) == List(t6, t7, t9))
)
assert(outcome.globalFlowtime <= a.globalFlowtime)
}
}
\ No newline at end of file
// Copyright (C) Maxime MORGE 2020, 2021, 2022, 2023, 2024
package org.smastaplus.balancer.local
import org.scalatest.flatspec.AnyFlatSpec
import org.smastaplus.core._
/**
* Unit test for the hill climbing balancer with the first stap example
*/
class VDSBalancerEx2Spec extends AnyFlatSpec {
import org.smastaplus.example.allocation.stap2.ex2lcjf._
import org.smastaplus.example.stap.ex2._
behavior of "Example 2 with the VDS balancer with swap"
"VDS" should
"perform TODO" in {
val balancer = new VDSBalancer(stap, GlobalFlowtime, withSwap = true)
balancer.trace = true
println(a)
val outcome = balancer.reallocate(a)
println(outcome)
assert(
(outcome.bundle(cn1) == List(t1, t4, t7) &&
outcome.bundle(cn2) == List(t8, t3, t2) &&
outcome.bundle(cn3) == List(t9, t5, t6))
)
assert(outcome.globalFlowtime <= a.globalFlowtime)
}
}
\ No newline at end of file
// Copyright (C) Maxime MORGE 2020, 2021, 2022, 2023, 2024
package org.smastaplus.balancer.local
import org.scalatest.flatspec.AnyFlatSpec
import org.smastaplus.core._
/**
* Unit test for the VDS balancer
*/
class VDSBalancerSpec extends AnyFlatSpec {
behavior of "VDS balancer with swap"
"Reallocation should be" should
"be sound" in {
val l = 4 // with l jobs
val m = 4 // with m nodes
val n = 3 * l * m // with n tasks
val o = 1 // with o resources per tasks
val d = 3 // with d duplicated instances per resource
val pb = STAP.randomProblem(l = l, m = m, n = n, o, d , Uncorrelated)
val a = Allocation.randomAllocation(pb)
val balancer = new VDSBalancer(pb, GlobalFlowtime, withSwap = true)
balancer.trace = false
val outcome = balancer.reallocate(a)
assert(outcome.isSound)
}
}
\ No newline at end of file
// Copyright (C) Anne-Cécile CARON, 2023 2024
package org.smastaplus.core package org.smastaplus.core
import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.flatspec.AnyFlatSpec
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment