Skip to content

Commit

Permalink
Vector.apply is not slower than ArraySeq.apply
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Marte committed Feb 10, 2024
1 parent a0ab800 commit 555e489
Show file tree
Hide file tree
Showing 27 changed files with 108 additions and 109 deletions.
4 changes: 2 additions & 2 deletions src/main/yuck/constraints/AlldistinctNeighbourhood.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ final class AlldistinctNeighbourhood
private val probabilityOfSwappingInValues = moveSizeDistribution.probability(1)
private val variablesHaveTheSameDomain = xs.forall(x => x.domain == xs.head.domain)
private val swappingInValuesIsPossible = xs.iterator.flatMap(_.domain.valuesIterator).toSet.size > n
private val effects = Vector.fill(3){new ReusableMoveEffect[V]}
private val swaps = for (n <- 1 to 3) yield effects.take(n)
private val effects = Vector.fill(3)(new ReusableMoveEffect[V])
private val swaps = Vector.tabulate(3)(i => effects.take(i + 1))
private def succeed(n: Int): Move = new ChangeValues[V](space.nextMoveId(), swaps(n - 1))
private def fail: Move = new ChangeValues[V](space.nextMoveId(), Nil)

Expand Down
6 changes: 2 additions & 4 deletions src/main/yuck/constraints/BinPacking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,10 @@ final class BinPacking
override def inVariables = items.view.filter(_.weight > valueTraits.zero).map(_.bin)
override def outVariables = loads.view.values

private val x2Item =
(for (item <- items) yield item.bin -> item).toMap[AnyVariable, BinPackingItem[Load]]
private val x2Item = (for (item <- items) yield item.bin -> item).toMap[AnyVariable, BinPackingItem[Load]]
private val currentLoads = new mutable.HashMap[Int, Load] // bin -> load
private val loadDeltas = new mutable.HashMap[Int, Load] // bin -> load delta
private val effects = // bin -> effect
(for ((i, load) <- loads) yield i -> load.reuseableEffect).toMap
private val effects = for ((i, load) <- loads) yield i -> load.reuseableEffect // bin -> effect

override def initialize(now: SearchState) = {
currentLoads.clear()
Expand Down
4 changes: 2 additions & 2 deletions src/main/yuck/constraints/CircuitTracker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ abstract class CircuitTracker
val indexRange = IntegerRange(offset, offset + succ.size - 1)
NoPropagationOccurred
.pruneDomains(
for (i <- succ.indices) yield {
for (i <- succ.indices.iterator) yield {
val a = IntegerValue(offset + i)
(succ(i), succ(i).domain.intersect(indexRange).diff(IntegerRange(a, a)))
}
Expand Down Expand Up @@ -132,4 +132,4 @@ object CircuitTracker {
cycles
}

}
}
2 changes: 1 addition & 1 deletion src/main/yuck/constraints/Cumulative.scala
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ final class Cumulative
buf += i
map
}
.map{case (x, buf) => (x, buf.toIndexedSeq)}
.map{case (x, buf) => (x, buf.toVector)}
.toMap

private val effect = costs.reuseableEffect
Expand Down
2 changes: 1 addition & 1 deletion src/main/yuck/constraints/Disjoint.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ abstract class Disjoint
buf += i
map
}
.map{case (x, buf) => (x, buf.toIndexedSeq)}
.map{case (x, buf) => (x, buf.toVector)}
.toMap

private val effect = costs.reuseableEffect
Expand Down
5 changes: 3 additions & 2 deletions src/main/yuck/constraints/GeneralInverseNeighbourhood.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ final class GeneralInverseNeighbourhood

private val effects = Vector.fill(4){new ReusableMoveEffect[IntegerValue]}
private val candidates1 =
f.xs.indices
f.xs.indices.iterator
.filter(i => f.xs(i).domain.size > 1 && g.xs(rawValue(f.xs(i)) - g.offset).domain.size > 1)
.toVector

override def nextMove = {
if (candidates1.isEmpty) {
Expand Down Expand Up @@ -50,7 +51,7 @@ final class GeneralInverseNeighbourhood
x1.domain.contains(a2) && x2.domain.contains(a1) &&
y1.domain.contains(b2) && y2.domain.contains(b1)
})
.toIndexedSeq
.toVector
if (candidates2.isEmpty) {
new ChangeValues[IntegerValue](space.nextMoveId(), Nil)
} else {
Expand Down
12 changes: 6 additions & 6 deletions src/main/yuck/constraints/Inverse.scala
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ final class Inverse

private def propagate(effects: PropagationEffects, f: InverseFunction, g: InverseFunction): PropagationEffects = {
effects
.pruneDomains(for (x <- f.xs) yield (x, g.indexDomain))
.pruneDomains(for (x <- g.xs) yield (x, f.indexDomain))
.pruneDomains(for (x <- f.xs.iterator) yield (x, g.indexDomain))
.pruneDomains(for (x <- g.xs.iterator) yield (x, f.indexDomain))
.pruneDomains(
for (i <- f.indexRange.iterator;
x = f.xs(i - f.offset);
Expand Down Expand Up @@ -339,15 +339,15 @@ final class Inverse
fPartitionByDomain.keysIterator.foldLeft[IntegerDomain](EmptyIntegerRange){union}.size ==
fPartitionByDomain.keysIterator.map(_.size).sum
if (isDecomposable) {
for (domain <- fPartitionByDomain.keysIterator.toList) yield {
fPartitionByDomain.keysIterator.map(domain => {
val offset = domain.lb.toInt
val costs = new BooleanVariable(space.nextVariableId(), "", CompleteBooleanDomain)
new Inverse(
space.nextConstraintId(), maybeGoal,
new InverseFunction(fPartitionByDomain(domain).toIndexedSeq, offset),
new InverseFunction(gPartitionByDomain(domain).toIndexedSeq, offset),
new InverseFunction(fPartitionByDomain(domain).toVector, offset),
new InverseFunction(gPartitionByDomain(domain).toVector, offset),
costs)
}
}).toList
} else {
List(this)
}
Expand Down
6 changes: 3 additions & 3 deletions src/main/yuck/constraints/Regular.scala
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ final class Regular
for (j <- 0 until Q)
if (d(i)(k) < Int.MaxValue && d(k)(j) < Int.MaxValue && d(i)(j) > d(i)(k) + d(k)(j))
d(i)(j) = d(i)(k) + d(k)(j)
for (i <- 0 until Q) yield F.valuesIterator.map(f => d(i)(f.toInt - 1)).min
Vector.tabulate(Q)(i => F.valuesIterator.map(f => d(i)(f.toInt - 1)).min)
}

override def toString =
Expand All @@ -98,7 +98,7 @@ final class Regular
buf += i
map
}
.map{case (x, buf) => (x, buf.toIndexedSeq)}
.map{case (x, buf) => (x, buf.toVector)}
.toMap
} else {
null
Expand All @@ -116,7 +116,7 @@ final class Regular
private val effect = costs.reuseableEffect

override def initialize(now: SearchState) = {
currentStates = immutable.IndexedSeq[Int]() ++ (0 until n).map(i => 0)
currentStates = Vector.fill(n)(0)
var i = 0
var q = q0
while (i < n && q > 0) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/yuck/constraints/Table.scala
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ final class Table
buf += i
map
}
.map{case (x, buf) => (x, buf.toIndexedSeq)}
.map{case (x, buf) => (x, buf.toVector)}
.toMap
} else {
null
Expand Down
2 changes: 1 addition & 1 deletion src/main/yuck/core/IntegerDomain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ object IntegerDomain {
def apply(ranges: Iterable[IntegerRange]): IntegerDomain = {
if (ranges.isEmpty) EmptyIntegerRange
else if (ranges.size == 1) ranges.head
else new IntegerRangeList(ranges.toIndexedSeq)
else new IntegerRangeList(ranges.toVector)
}

/**
Expand Down
6 changes: 3 additions & 3 deletions src/main/yuck/core/IntegerRangeList.scala
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ final class IntegerRangeList

override def mirrored: IntegerRangeList =
if (isEmpty) this
else new IntegerRangeList(ranges.reverseIterator.map(_.mirrored).toIndexedSeq)
else new IntegerRangeList(ranges.reverseIterator.map(_.mirrored).toVector)

private def cannotIntersect(that: IntegerRangeList): Boolean =
this.isEmpty ||
Expand Down Expand Up @@ -263,7 +263,7 @@ object IntegerRangeList {
*/
def apply(range: IntegerRange) =
if (range.isEmpty) EmptyIntegerRangeList
else new IntegerRangeList(immutable.IndexedSeq(range))
else new IntegerRangeList(Vector(range))

/**
* Creates an IntegerRangeList instance from the given boundaries.
Expand All @@ -272,7 +272,7 @@ object IntegerRangeList {
*/
def apply(a: IntegerValue, b: IntegerValue) =
if (a.ne(null) && b.ne(null) && b < a) EmptyIntegerRangeList
else new IntegerRangeList(immutable.IndexedSeq(IntegerRange(a, b)))
else new IntegerRangeList(Vector(IntegerRange(a, b)))

// In the following methods we prefer indices and tail recursion over iterators and loops
// to avoid the overhead of creating ranges and iterators.
Expand Down
9 changes: 4 additions & 5 deletions src/main/yuck/core/RandomCircularSwapGenerator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,11 @@ final class RandomCircularSwapGenerator
require(moveSizeDistribution.frequency(0) == 0)
require(moveSizeDistribution.volume > 0)

private val uniformDistribution = Distribution(n)
(0 until n).foreach(i => uniformDistribution.setFrequency(i, 1))
private val uniformDistribution = Distribution(0, Vector.fill(n)(1))
private val s = moveSizeDistribution.size
private val effects = for (i <- 1 until s) yield new ReusableMoveEffect[V]
private val swaps = for (n <- 1 until s) yield effects.take(n)
private val frequencyRestorers = for (i <- 1 until s) yield new FrequencyRestorer
private val effects = Vector.fill(s)(new ReusableMoveEffect[V])
private val swaps = Vector.tabulate(s)(i => effects.take(i + 1))
private val frequencyRestorers = Vector.fill(s)(new FrequencyRestorer)
private def fillEffect(effect: ReusableMoveEffect[V], x: Variable[V]): Unit = {
effect.x = x
effect.a = space.searchState.value(x)
Expand Down
8 changes: 3 additions & 5 deletions src/main/yuck/core/RandomReassignmentGenerator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,10 @@ final class RandomReassignmentGenerator
require(moveSizeDistribution.frequency(0) == 0)
require(moveSizeDistribution.volume > 0)

private val uniformDistribution = Distribution(n)
(0 until n).foreach(i => uniformDistribution.setFrequency(i, 1))
require(uniformDistribution.volume > 0)
private val s = moveSizeDistribution.size
private val uniformDistribution = Distribution(0, Vector.fill(n)(1))
private val effects = new mutable.ArrayBuffer[AnyMoveEffect](n)
private val frequencyRestorers = for (i <- 1 until s) yield new FrequencyRestorer
private val s = moveSizeDistribution.size
private val frequencyRestorers = Vector.fill(s)(new FrequencyRestorer)
private def addEffect(x: AnyVariable): Unit = {
effects += x.nextRandomMoveEffect(space, randomGenerator)
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/yuck/flatzinc/compiler/CompilationPhase.scala
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ abstract class CompilationPhase extends Runnable {
case Term(_, Nil) =>
cc.arrays(expr)
case ArrayConst(elems) =>
val array = elems.iterator.map(elem => compileAnyExpr(elem)).to(immutable.ArraySeq)
val array = elems.iterator.map(elem => compileAnyExpr(elem)).toVector
cc.arrayConsts += expr -> array
array
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ final class ConstraintDrivenNeighbourhoodFactory
val xs0 = cc.space.involvedSearchVariables(constraint)
neighbourhoods ++=
neighbourhoodsFromImplicitConstraints.iterator.filter(_.searchVariables.intersect(xs0).nonEmpty)
val xs = xs0.diff(cc.implicitlyConstrainedVars).toBuffer.sorted.toIndexedSeq
val xs = xs0.diff(cc.implicitlyConstrainedVars).toBuffer.sorted.toVector
if (xs.isEmpty) {
// Either there are no variables or they are all managed by neighbourhoods from implicit constraints.
None
Expand All @@ -123,7 +123,7 @@ final class ConstraintDrivenNeighbourhoodFactory
if (neighbourhoods.size < 2) {
neighbourhoods.headOption
} else {
Some(new NeighbourhoodCollection(neighbourhoods.toIndexedSeq, randomGenerator, None, None))
Some(new NeighbourhoodCollection(neighbourhoods.toVector, randomGenerator, None, None))
}
}
}
Expand All @@ -143,7 +143,7 @@ final class ConstraintDrivenNeighbourhoodFactory
if (weights.isEmpty) {
None
} else {
val xs = weights.map(_.x).toIndexedSeq
val xs = weights.map(_.x).toVector
for (x <- xs if ! x.domain.isFinite) {
throw new VariableWithInfiniteDomainException(x)
}
Expand Down Expand Up @@ -181,7 +181,7 @@ final class ConstraintDrivenNeighbourhoodFactory
val (weights, neighbourhoods) = weightedNeighbourhoods.unzip
val hotSpotDistribution = createHotSpotDistribution(mode, weights)
Some(new NeighbourhoodCollection(
neighbourhoods.toIndexedSeq, randomGenerator, Some(hotSpotDistribution), None))
neighbourhoods.toVector, randomGenerator, Some(hotSpotDistribution), None))
}
maybeNeighbourhood.map(considerFairVariableChoiceRate(_, levelCfg))
}
Expand All @@ -194,7 +194,7 @@ final class ConstraintDrivenNeighbourhoodFactory
Distribution =
{
val hotSpotDistribution = Distribution(weights.size)
cc.space.post(new OptimizationGoalTracker(nextConstraintId(), None, mode, weights.toIndexedSeq, hotSpotDistribution))
cc.space.post(new OptimizationGoalTracker(nextConstraintId(), None, mode, weights.toVector, hotSpotDistribution))
hotSpotDistribution
}

Expand All @@ -204,7 +204,7 @@ final class ConstraintDrivenNeighbourhoodFactory
val rate = (levelCfg.maybeFairVariableChoiceRate.getOrElse(Probability(0)).value * 100).toInt
if (rate == 0) neighbourhood0
else {
val xs = neighbourhood0.searchVariables.diff(cc.implicitlyConstrainedVars).toBuffer.sorted.toIndexedSeq
val xs = neighbourhood0.searchVariables.diff(cc.implicitlyConstrainedVars).toBuffer.sorted.toVector
if (xs.isEmpty) neighbourhood0
else {
val neighbourhood1 =
Expand Down
Loading

0 comments on commit 555e489

Please sign in to comment.