Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
### 0.5.3 (Upcoming release)
- Add tests for GreyNumber type
- methods now accept Matrix (in addition to DataFrame)

- PIV (Proximity Indexed Value) method implemented

### 0.5.2
- Implement MEREC
Expand Down
5 changes: 5 additions & 0 deletions src/JMcDM.jl
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ include("mcdm.jl")
include("copeland.jl")
include("sd.jl")
include("rov.jl")
include("piv.jl")



Expand Down Expand Up @@ -136,6 +137,7 @@ import .DEMATEL: dematel, DematelResult
import .Entropy: entropy, EntropyResult
import .AHP: ahp, ahp_consistency, ahp_RI, AHPResult, AHPConsistencyResult
import .MEREC: merec, MERECResult, MERECMethod
import .PIV: piv, PIVResult, PIVMethod

import .SCDM: LaplaceResult, MaximinResult, MaximaxResult, MinimaxResult, MiniminResult
import .SCDM: SavageResult, HurwiczResult, MLEResult, ExpectedRegretResult
Expand Down Expand Up @@ -174,6 +176,7 @@ export PSIMethod
export MoosraMethod
export ROVMethod
export MERECMethod
export PIVMethod

export MCDMSetting

Expand Down Expand Up @@ -206,6 +209,7 @@ export ROVResult
export PSIResult
export MoosraResult
export MERECResult
export PIVResult

# export game type
export GameResult
Expand Down Expand Up @@ -264,6 +268,7 @@ export rov
export psi
export moosra
export merec
export piv

#  export SCDM tools
export laplace
Expand Down
2 changes: 2 additions & 0 deletions src/codas.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ function Base.show(io::IO, result::CODASResult)
println(io, "Best indices:")
println(io, result.bestIndex)
end


"""
codas(decisionMat, weights, fs)
Apply CODAS (COmbinative Distance-based ASsessment) method for a given matrix, weights and, type of criteria.
Expand Down
91 changes: 91 additions & 0 deletions src/piv.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
module PIV

export piv, PIVResult, PIVMethod

import ..MCDMMethod, ..MCDMResult, ..MCDMSetting
using ..Utilities

using DataFrames

struct PIVResult <: MCDMResult
decisionMatrix::DataFrame
normalizedMatrix::DataFrame
weightedNormalizedMatrix::DataFrame
w::Array{Float64,1}
scores::Vector
ranking::Array{Int64,1}
bestIndex::Int64
end

struct PIVMethod <: MCDMMethod
end

function Base.show(io::IO, result::PIVResult)
println(io, "Scores:")
println(io, result.scores)
println(io, "Ordering: ")
println(io, result.ranking)
println(io, "Best index:")
println(io, result.bestIndex)
end

"""
piv(decisionMat, weights, fs)
Apply PIV (Proximity Indexed Value) method for a given matrix, weights and, type of criteria.

# Arguments:
- `decisionMat::DataFrame`: n × m matrix of objective values for n alternatives and m criteria
- `weights::Array{Float64, 1}`: m-vector of weights that sum up to 1.0. If the sum of weights is not 1.0, it is automatically normalized.
- `fs::Array{Function,1}`: m-vector of type of criteria. The benefit criteria shown with "maximum", and the cost criteria shown with "minimum".

# Description
piv() applies the PIV method to rank n alternatives subject to m criteria and criteria type vector. Alternatives
with lesser scores values (u_i values in the original article) are better as they represent the deviation
from the ideal values.


# Output
- `::PIVResult`: PIVResult object that holds multiple outputs including scores, rankings, and best index.

# References
Sameera Mufazzal, S.M. Muzakkir, A new multi-criterion decision making (MCDM) method based on proximity indexed value for minimizing rank reversals,
Computers & Industrial Engineering, Volume 119, 2018, Pages 427-438, ISSN 0360-8352,
https://doi.org/10.1016/j.cie.2018.03.045.
"""
function piv(decisionMat::DataFrame, weights::Array{Float64,1}, fns::Array{Function,1})::PIVResult

normalized_dec_mat = Utilities.normalize(decisionMat)
weighted_norm_mat = weights * normalized_dec_mat

nrow, ncol = size(weighted_norm_mat)

desiredvalues = Utilities.apply_columns(fns, weighted_norm_mat)

finalmat = similar(weighted_norm_mat)

@inbounds for i in 1:nrow
for j in 1:ncol
if fns[j] == maximum
finalmat[i,j] = desiredvalues[j] - weighted_norm_mat[i,j]
elseif fns[j] == minimum
finalmat[i,j] = weighted_norm_mat[i,j] - desiredvalues[j]
end
end
end

di = Utilities.apply_rows(sum, finalmat)

ranks = di |> sortperm
bestIndex = ranks |> first

return PIVResult(
decisionMat,
normalized_dec_mat,
weighted_norm_mat,
weights,
di,
ranks,
bestIndex)
end

end # End of Module PIV
15 changes: 0 additions & 15 deletions test.jl
Original file line number Diff line number Diff line change
@@ -1,18 +1,3 @@
using JMcDM

df = DataFrame(
:K1 => [105000.0, 120000, 150000, 115000, 135000],
:K2 => [105.0, 110, 120, 105, 115],
:K3 => [10.0, 15, 12, 20, 15],
:K4 => [4.0, 4, 3, 4, 5],
:K5 => [300.0, 500, 550, 600, 400],
:K6 => [10.0, 8, 12, 9, 9],
)
functionlist = [minimum, maximum, minimum, maximum, maximum, minimum]

w = [0.05, 0.20, 0.10, 0.15, 0.10, 0.40]

gdf = makegrey(Matrix(df))
result = aras(makeDecisionMatrix(gdf), w, functionlist)

@show result
28 changes: 28 additions & 0 deletions test/testmcdm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1343,5 +1343,33 @@
@test result2 isa MERECResult
@test result2.w == result.w
end

@testset "PIV" begin
tol = 0.0001

decmat = [
60 2.5 2540 500 990
6.35 6.667 1016 3000 1041
6.8 10 1727 1500 1676
10 5 1000 2000 965
2.5 9.8 560 500 915
4.5 12.5 1016 350 508
3 10 1778 1000 920]

w = [0.1761, 0.2042, 0.2668, 0.1243, 0.2286]

fns = [maximum, maximum, maximum, maximum, maximum]

result = piv(makeDecisionMatrix(decmat), w, makeminmax(fns))

@test result isa PIVResult
@test isapprox(
result.scores,
[0.22086675609968962, 0.35854940101222144, 0.2734184099704686, 0.4005382183676046, 0.4581157878699193, 0.43595371718873477, 0.3580651803072459],
atol = tol,
)
@test result.bestIndex == 1
@test result.ranking == [1, 3, 7, 2, 4, 6, 5]
end
end