-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchoquet-integral.go
108 lines (93 loc) · 2.98 KB
/
choquet-integral.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package choquet
import (
"github.com/Azbesciak/RealDecisionMaker/lib/model"
"github.com/Azbesciak/RealDecisionMaker/lib/utils"
"sort"
)
const methodName = "choquetIntegral"
type ChoquetIntegralPreferenceFunc struct {
}
func (c *ChoquetIntegralPreferenceFunc) Identifier() string {
return methodName
}
func (c *ChoquetIntegralPreferenceFunc) MethodParameters() interface{} {
return model.WeightsParamOnly()
}
func (c *ChoquetIntegralPreferenceFunc) Evaluate(dmp *model.DecisionMakingParams) *model.AlternativesRanking {
params := dmp.MethodParameters.(choquetParams)
prefFunc := func(alternative *model.AlternativeWithCriteria) *model.AlternativeResult {
return choquetIntegral(alternative, params.weights)
}
return model.Rank(dmp, prefFunc)
}
func ChoquetIntegral(
alternative model.AlternativeWithCriteria,
criteria model.Criteria,
weights model.Weights,
) *model.AlternativeResult {
resultWeights := parse(&criteria, &weights)
return choquetIntegral(&alternative, resultWeights)
}
func choquetIntegral(
alternative *model.AlternativeWithCriteria,
weights *model.Weights,
) *model.AlternativeResult {
sortedCriteria := prepareCriteriaInAscendingOrder(alternative)
result, _ := computeTotalWeight(sortedCriteria, weights)
return model.ValueAlternativeResult(alternative, result)
}
type weightComponent struct {
criteria []string
valueAdded model.Weight
}
func computeTotalWeight(sortedCriteria *criteriaWeights, weights *model.Weights) (model.Weight, []weightComponent) {
var result model.Weight = 0
var previousWeight model.Weight = 0
var components []weightComponent
totalElements := len(*sortedCriteria)
for i := 0; i < totalElements; {
commonWeightCriteria := make([]string, totalElements-i)
for x := 0; x < totalElements-i; x++ {
commonWeightCriteria[x] = (*sortedCriteria)[i+x].criterion
}
var current = (*sortedCriteria)[i]
var j int
for j = i + 1; j < totalElements; j++ {
var nextValue = (*sortedCriteria)[j]
if !utils.FloatsAreEqual(current.weight, nextValue.weight, 0.00001) {
break
}
}
criteriaUnionWeight := getWeightForCriteriaUnion(&commonWeightCriteria, weights)
valueAdded := criteriaUnionWeight * (current.weight - previousWeight)
result += valueAdded
components = append(components, weightComponent{commonWeightCriteria, valueAdded})
previousWeight = current.weight
i = j
}
return result, components
}
func prepareCriteriaInAscendingOrder(alternative *model.AlternativeWithCriteria) *criteriaWeights {
var sorted = make(criteriaWeights, len(alternative.Criteria))
i := 0
for k, v := range alternative.Criteria {
sorted[i] = criterionWeight{k, v}
i++
}
sort.Sort(&sorted)
return &sorted
}
type criterionWeight struct {
criterion string
weight model.Weight
}
type criteriaWeights []criterionWeight
func (c *criteriaWeights) Len() int {
return len(*c)
}
func (c *criteriaWeights) Less(i, j int) bool {
return (*c)[i].weight < (*c)[j].weight
}
func (c *criteriaWeights) Swap(i, j int) {
(*c)[i], (*c)[j] = (*c)[j], (*c)[i]
}