Skip to content

Commit 756f768

Browse files
committed
implement Aras
1 parent 635699b commit 756f768

File tree

4 files changed

+126
-21
lines changed

4 files changed

+126
-21
lines changed

src/main/scala/aras.scala

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package org.expr.mcdm
2+
3+
case class ArasResult(
4+
referenceRow: Vec,
5+
extendMat: Mat,
6+
normalizedMat: Mat,
7+
optimality_degrees: Vec,
8+
scores: Vec,
9+
orderings: VecInt,
10+
bestIndex: Int
11+
) extends MCDMResult
12+
13+
def aras(
14+
decmat: Mat,
15+
weights: Vec,
16+
directions: Array[Direction],
17+
normalization: NormalizationFunction =
18+
Normalization.DivideByColumnnsSumNormalization
19+
): ArasResult =
20+
val (nrows, ncols) = Matrix.size(decmat)
21+
22+
val referenceRow = Matrix.colminmax(decmat, directions)
23+
24+
val extendMat = Matrix
25+
.appendrow(decmat, referenceRow)
26+
.transpose
27+
.zip(directions)
28+
.map((col, dir) =>
29+
dir match
30+
case Direction.Minimize => col.map(value => 1.0 / value)
31+
case Direction.Maximize => col
32+
)
33+
.transpose
34+
35+
val normalized = normalization(extendMat, weights, directions)
36+
37+
var optimalityDegrees = Array.fill(nrows + 1)(0.0)
38+
for i <- 0 until (nrows + 1) do
39+
optimalityDegrees(i) =
40+
weights.zip(Matrix.getrowat(normalized, i)).map((w, x) => w * x).sum
41+
42+
var utilityDegrees = Array.fill(nrows)(0.0)
43+
for i <- 0 until nrows do
44+
utilityDegrees(i) = optimalityDegrees(i) / optimalityDegrees(nrows)
45+
46+
val orderings = utilityDegrees.zipWithIndex.sortBy(-_._1).map(_._2)
47+
val bestIndex = orderings.last
48+
49+
ArasResult(
50+
referenceRow,
51+
extendMat,
52+
normalized,
53+
optimalityDegrees,
54+
utilityDegrees,
55+
orderings,
56+
bestIndex
57+
)

src/main/scala/matrix.scala

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,6 @@ object Matrix:
9494

9595
def size(a: Mat): (Int, Int) = (a.length, a(0).length)
9696

97-
def appendColumnVec(a: Mat, b: Vec): Mat = a :+ b
98-
99-
def appendRowVec(a: Mat, b: Vec): Mat = (a.transpose :+ b).transpose
100-
10197
def inverse(a: Array[Array[Double]]): Array[Array[Double]] =
10298
val n = a.length
10399
val m = a(0).length
@@ -132,5 +128,3 @@ object Matrix:
132128
case Direction.Maximize => Direction.Minimize
133129
}
134130

135-
def weightise(a: Mat, w: Vec): Mat =
136-
a.transpose.zip(w).map((row, weight) => row.map(value => value * weight)).transpose

src/test/scala/testaras.scala

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import munit.Assertions as A
2+
3+
import org.expr.mcdm.aras
4+
import org.expr.mcdm.Direction.{Maximize, Minimize}
5+
import org.expr.mcdm.Matrix
6+
7+
class TestAras extends munit.FunSuite {
8+
test("Aras Example - 1") {
9+
val decmat = Array(
10+
Array(105000.0, 120000.0, 150000.0, 115000.0, 135000.0),
11+
Array(105.0, 110.0, 120.0, 105.0, 115.0),
12+
Array(10.0, 15.0, 12.0, 20.0, 15.0),
13+
Array(4.0, 4.0, 3.0, 4.0, 5.0),
14+
Array(300.0, 500.0, 550.0, 600.0, 400.0),
15+
Array(10.0, 8.0, 12.0, 9.0, 9.0)
16+
).transpose
17+
18+
val functionlist =
19+
Array(Minimize, Maximize, Minimize, Maximize, Maximize, Minimize)
20+
21+
val w = Array(0.05, 0.20, 0.10, 0.15, 0.10, 0.40)
22+
23+
val result = aras(decmat, w, functionlist)
24+
25+
val expectedExtendMat = Array(
26+
Array(9.52381e-6, 105.0, 0.1, 4.0, 300.0, 0.1),
27+
Array(8.33333e-6, 110.0, 0.0666667, 4.0, 500.0, 0.125),
28+
Array(6.66667e-6, 120.0, 0.0833333, 3.0, 550.0, 0.0833333),
29+
Array(8.69565e-6, 105.0, 0.05, 4.0, 600.0, 0.111111),
30+
Array(7.40741e-6, 115.0, 0.0666667, 5.0, 400.0, 0.111111),
31+
Array(9.52381e-6, 120.0, 0.1, 5.0, 600.0, 0.125)
32+
)
33+
34+
val expectedNormalized = Array(
35+
Array(0.189904, 0.155556, 0.214286, 0.16, 0.101695, 0.152542),
36+
Array(0.166166, 0.162963, 0.142857, 0.16, 0.169492, 0.190678),
37+
Array(0.132933, 0.177778, 0.178571, 0.12, 0.186441, 0.127119),
38+
Array(0.173391, 0.155556, 0.107143, 0.16, 0.20339, 0.169492),
39+
Array(0.147703, 0.17037, 0.142857, 0.2, 0.135593, 0.169492),
40+
Array(0.189904, 0.177778, 0.214286, 0.2, 0.20339, 0.190678)
41+
)
42+
43+
val expectedOptimalityDegrees =
44+
Array(0.15722131828198205, 0.17240694154264946, 0.1475508603814606,
45+
0.1626305159740402, 0.16710087227988196, 0.19308949153998578)
46+
47+
val expectedScores =
48+
Array(0.81424068, 0.89288620, 0.76415790, 0.84225462, 0.86540635)
49+
50+
val expectedOrdering = Array(1, 4, 3, 0, 2)
51+
52+
A.assert(
53+
Matrix.elementwise_equal(result.extendMat, expectedExtendMat, 1e-5)
54+
)
55+
A.assert(
56+
Matrix.elementwise_equal(result.normalizedMat, expectedNormalized, 1e-5)
57+
)
58+
A.assert(
59+
Matrix.elementwise_equal(
60+
result.optimality_degrees,
61+
expectedOptimalityDegrees,
62+
1e-5
63+
)
64+
)
65+
A.assert(Matrix.elementwise_equal(result.scores, expectedScores, 1e-5))
66+
A.assert(expectedOrdering.zip(result.orderings).forall((x, y) => x == y))
67+
A.assertEquals(result.bestIndex, 2)
68+
}
69+
}

src/test/scala/testmatrix.scala

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -352,21 +352,6 @@ class TestMatrix extends munit.FunSuite {
352352
Direction.Maximize)
353353
direction.zip(expected).foreach{case (a, b) => A.assertNotEquals(a, b)}
354354
}
355-
test("Weightise"){
356-
val mat = Array(
357-
Array(1.0, 5.0, 6.0, 10.0, 10.0),
358-
Array(-1.0, 10.0, 9.0, 11.0, 11.0),
359-
Array(9.0, 17.0, 12.0, 12.0, 12.0)
360-
)
361-
val weights = Array(0.1, 0.2, 0.3, 0.3, 0.1)
362-
val weighted = Matrix.weightise(mat, weights)
363-
val expected = Array(
364-
Array( 0.1, 1.0, 1.8, 3.0, 1.0),
365-
Array(-0.1, 2.0, 2.7, 3.3, 1.1),
366-
Array( 0.9, 3.4, 3.6, 3.6, 1.2)
367-
)
368-
A.assert(Matrix.elementwise_equal(weighted, expected, 1e-3))
369-
}
370355

371356
}
372357

0 commit comments

Comments
 (0)