Skip to content

Commit 985be18

Browse files
committed
implement Saw
1 parent 31270fc commit 985be18

File tree

4 files changed

+107
-0
lines changed

4 files changed

+107
-0
lines changed

src/main/scala/normalization.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,18 @@ object Normalization:
3737
then (decmat(i)(j) - columnmins(j)) / (columnmaxs(j) - columnmins(j))
3838
else (columnmaxs(j) - decmat(i)(j)) / (columnmaxs(j) - columnmins(j))
3939
)
40+
41+
def DivideByColumnMaxMinNormalization(
42+
decmat: Mat,
43+
weights: Vec,
44+
directions: Array[Direction]
45+
): Mat =
46+
val (n, m) = Matrix.size(decmat)
47+
val columnmins = Matrix.colmins(decmat)
48+
val columnmaxs = Matrix.colmaxs(decmat)
49+
50+
Array.tabulate(n, m)((i, j) =>
51+
if directions(j) == Direction.Maximize
52+
then decmat(i)(j) / columnmaxs(j)
53+
else columnmins(j) / decmat(i)(j)
54+
)

src/main/scala/saw.scala

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.expr.mcdm
2+
3+
import org.expr.mcdm.Direction
4+
5+
case class SawResult(
6+
normalizedDecisionMat: Mat,
7+
weightedNormalizedDecMat: Mat,
8+
scores: Vec,
9+
orderings: VecInt,
10+
bestIndex: Int
11+
) extends MCDMResult
12+
13+
def saw(
14+
mat: Mat,
15+
weights: Vec,
16+
directions: Array[Direction],
17+
normalization: NormalizationFunction = Normalization.DivideByColumnMaxMinNormalization
18+
): SawResult =
19+
20+
val (n, p) = Matrix.size(mat)
21+
22+
val normalizedDecisionMat = normalization(mat, weights, directions)
23+
24+
val weightedNormalizedDecMat = Matrix.weightizeColumns(normalizedDecisionMat, weights)
25+
26+
val scores = Matrix.rowsums(weightedNormalizedDecMat)
27+
28+
val orderings = scores.zipWithIndex.sortBy(_._1).map(_._2)
29+
30+
val bestIndex = orderings.last
31+
32+
SawResult(
33+
normalizedDecisionMat,
34+
weightedNormalizedDecMat,
35+
scores,
36+
orderings,
37+
bestIndex
38+
)

src/test/scala/testnormalization.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import scala.math as math
44
import org.expr.mcdm.Matrix
55
import org.expr.mcdm.Direction._
66
import org.expr.mcdm.Normalization._
7+
import org.expr.mcdm.Normalization
78

89
class TestNormalizations extends munit.FunSuite {
910

@@ -61,5 +62,23 @@ class TestNormalizations extends munit.FunSuite {
6162

6263
A.assert(Matrix.elementwise_equal(normalizedMatrix, expected, 1e-5))
6364
}
65+
66+
test("Divide by column max min normalization"){
67+
val mat = Array(
68+
Array(0.0264859, 0.0565293, 0.960557, 0.765195, 0.135447),
69+
Array(0.31746 , 0.631628 , 0.142819, 0.94584 , 0.553917),
70+
Array(0.166361 , 0.197306 , 0.725104, 0.334121, 0.202895))
71+
72+
val directions = Array(Maximize, Minimize, Maximize, Minimize, Maximize)
73+
74+
val result = Normalization.DivideByColumnMaxMinNormalization(mat, Array.emptyDoubleArray, directions)
75+
76+
val expected = Array(
77+
Array(0.0834308, 1.0 , 1.0 , 0.436648, 0.244525),
78+
Array(1.0 , 0.0894977, 0.148684, 0.353253, 1.0),
79+
Array(0.524038 , 0.286505 , 0.75488 , 1.0 , 0.366291))
80+
81+
A.assert(Matrix.elementwise_equal(result, expected, 1e-5))
82+
}
6483

6584
}

src/test/scala/testsaw.scala

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import munit.Assertions as A
2+
3+
import org.expr.mcdm.Matrix
4+
import org.expr.mcdm.Direction
5+
import org.expr.mcdm.saw
6+
7+
class TestSaw extends munit.FunSuite {
8+
9+
test("Saw Example - 1"){
10+
val decmat = Array(
11+
Array(25.0, 21, 19, 22),
12+
Array(65.0, 78, 53, 25),
13+
Array(7.0 , 6, 5 , 2),
14+
Array(20.0, 24, 33, 31)).transpose
15+
16+
val weights = Array(0.25, 0.25, 0.25, 0.25)
17+
18+
val directions = Array(
19+
Direction.Maximize,
20+
Direction.Maximize,
21+
Direction.Minimize,
22+
Direction.Maximize
23+
)
24+
25+
val result = saw(decmat, weights, directions)
26+
27+
val expectedScores = Array(0.681277, 0.725151, 0.709871, 0.784976)
28+
29+
A.assert(Matrix.elementwise_equal(result.scores, expectedScores))
30+
31+
A.assertEquals(result.bestIndex, 3)
32+
}
33+
34+
}
35+

0 commit comments

Comments
 (0)