Skip to content

Commit d4884a0

Browse files
committed
implement rov
1 parent 135c168 commit d4884a0

File tree

3 files changed

+99
-0
lines changed

3 files changed

+99
-0
lines changed

src/main/scala/matrix.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,19 @@ object Matrix:
3737

3838
def getrowat(a: Mat, i: Int): Vec = a(i)
3939

40+
def getrowsat(a: Mat, indices: Array[Int]): Mat =
41+
indices.map(i => a(i))
42+
43+
def getcolsat(a: Mat, indices: Array[Int]): Mat =
44+
indices.map(i => a.transpose.apply(i)).transpose
45+
4046
def getcolat(a: Mat, j: Int): Vec = a.map(row => row(j))
4147

4248
def elementat(a: Mat, i: Int, j: Int): Double = a(i)(j)
4349

50+
def elementsat(a: Vec, indices: Array[Int]): Vec =
51+
indices.map(i => a(i))
52+
4453
def setrowat(a: Mat, i: Int, row: Vec): Mat = a.updated(i, row)
4554

4655
def setcolat(a: Mat, j: Int, col: Vec): Mat =

src/main/scala/rov.scala

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package org.expr.mcdm
2+
3+
import org.expr.mcdm.Direction.{Maximize, Minimize}
4+
5+
case class RovResult(
6+
normalizedMat: Mat,
7+
uplus: Vec,
8+
uminus: Vec,
9+
scores: Vec
10+
) extends MCDMResult
11+
12+
13+
def rov(
14+
decmat: Mat,
15+
weights: Vec,
16+
directions: Array[Direction],
17+
normalization: NormalizationFunction =
18+
Normalization.MaxMinRangeNormalization,
19+
options: Map[String, Any] = Map.empty
20+
): RovResult =
21+
22+
val (n, p) = Matrix.size(decmat)
23+
24+
val normalizedMat = normalization(decmat, weights, directions)
25+
26+
val uplus = Matrix.zeros(n)
27+
28+
val uminus = Matrix.zeros(n)
29+
30+
val u = Matrix.zeros(n)
31+
32+
val maxindices = directions.zipWithIndex.filter(_._1 == Maximize).map(_._2)
33+
34+
val minindices = directions.zipWithIndex.filter(_._1 == Minimize).map(_._2)
35+
36+
if maxindices.nonEmpty then
37+
for i <- 0 until n do
38+
uplus(i) =
39+
Matrix.sumproduct(
40+
Matrix.elementsat(Matrix.getrowat(normalizedMat, i), maxindices),
41+
Matrix.elementsat(weights, maxindices))
42+
43+
if minindices.nonEmpty then
44+
for i <- 0 until n do
45+
uminus(i) =
46+
Matrix.sumproduct(
47+
Matrix.elementsat(Matrix.getrowat(normalizedMat, i), minindices),
48+
Matrix.elementsat(weights, minindices))
49+
50+
51+
// U values are scores
52+
for i <- 0 until n do
53+
u(i) = (uminus(i) + uplus(i)) / 2.0
54+
55+
56+
RovResult(
57+
normalizedMat,
58+
uplus,
59+
uminus,
60+
scores = u
61+
)

src/test/scala/testrov.scala

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import munit.Assertions as A
2+
3+
import org.expr.mcdm.rov
4+
import org.expr.mcdm.Direction.{Maximize, Minimize}
5+
import org.expr.mcdm.Matrix
6+
7+
class TestRov extends munit.FunSuite {
8+
test("Rov Example - 1") {
9+
val mat = Array(
10+
Array(0.035, 34.5, 847, 1.76, 0.335, 0.5, 0.59, 0.59),
11+
Array(0.027, 36.8, 834, 1.68, 0.335, 0.665, 0.665, 0.665),
12+
Array(0.037, 38.6, 808, 2.4, 0.59, 0.59, 0.41, 0.5),
13+
Array(0.028, 32.6, 821, 1.59, 0.5, 0.59, 0.59, 0.41))
14+
15+
val w = Array(0.3306, 0.0718, 0.1808, 0.0718, 0.0459, 0.126, 0.126, 0.0472)
16+
17+
val fns = Array(Minimize, Minimize, Minimize, Minimize, Maximize, Minimize, Minimize, Maximize)
18+
19+
val expected_scores = Array(
20+
0.1841453340595497,
21+
0.26171444444444447,
22+
0.21331577540106955,
23+
0.34285244206773624)
24+
25+
val result1 = rov(mat, w, fns)
26+
27+
A.assert(Matrix.elementwise_equal(result1.scores, expected_scores, 1e-6), "Rov scores do not match expected values")
28+
}
29+
}

0 commit comments

Comments
 (0)