Subjective Weights in Multi-Criteria Decision Making (MCDM)
Subjective weights determination represent the importance assigned to criteria based on the preferences, judgments, or knowledge of decision-makers. Unlike objective weighting methods, where the weights are derived from the intrinsic properties of the data (e.g., entropy or correlation), subjective weights rely on human input and are influenced by experience, priorities, or specific decision-making contexts.
Some common techniques for subjective weight determination include:
Direct Assignment: Decision-makers assign weights directly to criteria based on their judgment.
Pairwise Comparison (e.g., AHP): Decision-makers evaluate the relative importance of criteria in pairs to derive consistent weights.
Scoring Methods: A fixed number of points is distributed among criteria to reflect their importance.
Ranking Methods: Criteria are ranked in order of importance, and weights are assigned based on the ranks.
Subjective weight determination allows for flexibility and customization of the decision-making process, making it highly applicable in scenarios where decision-maker of expert input is vital.
Pairwise Comparison-Based methods
The pymcdm library currently provides implementations for two pairwise comparison-based methods for determining subjective weights: AHP (Analytic Hierarchy Process) and RANCOM (RANking COMparison). In this example, we will demonstrate how to use the pymcdm library to apply both AHP and RANCOM for subjective weight determination, providing practical guidance on their usage.
AHP
The implementation of AHP (Analytic Hierarchy Process) in the pymcdm library is designed with specific assumptions and features.
For now only a 1-layer structure, meaning that all criteria are evaluated at the same hierarchical level without incorporating sub-criteria.
Weights are calculated from the AHP pairwise maitrix using the eigenvector method.
Pairwise comparison matrix accepts values from a predefined scale of 1 to 9 and their reciprocals (1/9 to 1), where 1 indicates equal importance between two criteria, and values like 9 and 1/9 represent extreme importance of one criterion over another and vice versa. I.e. possible values in the matrix are following:
{1, 2, 3, 4, 5, 6, 7, 8, 9, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9}.
For both AHP and RANCOM methods, method’s object can be instantiated using:
Scores - provide scores for each criterion as
np.array(). Larger values indicates more important criteria.Ranking - provide ranking for each criterion as
np.array(). Smaller values indicates more important criteria.Comparison matrix - input complete matrix. Note, that matrix is validated to check if all values are fits in 1-9 Saaty scale.
Text file with comparison matrix, in
.csvformat. Same validation is applied as in case of comparison matrix.Manual comparison via command line interface.
[1]:
# Essential imports
import numpy as np
from pymcdm.weights.subjective import AHP, RANCOM
[2]:
# Suppose we have three criteria to evaluate. Define the scoring vector for them:
scores = np.array([10, 3, 5])
# You can use any positive numbers above zero to define scoring vector.
# Create AHP object:
ahp = AHP(scoring=scores) # Note that only one argument can be provided.
weights = ahp() # Call the object to get weights.
print(weights)
[0.44342911 0.16919987 0.38737101]
[3]:
# Suppose we have three criteria to evaluate. Define the ranking vector for them:
ranking = np.array([1, 3, 2])
# You can use any positive numbers above zero to define ranking vector.
ahp = AHP(ranking=ranking)
weights = ahp() # Call the object to get weights.
print(weights)
[0.54994561 0.20984352 0.24021087]
[4]:
# Sometimes you can want to use prepared matrix to instantiate AHP object:
a = np.array([
[ 1, 1/2, 7],
[ 2, 1, 3],
[1/7, 1/3, 1]
])
ahp = AHP(matrix=a)
weights = ahp()
print(weights)
[0.41058565 0.49139587 0.09801848]
[5]:
# And there are also command line interface to fill pairwise matrix step-by-step. See the output below.
criteria_names = ['Price', 'Mileage', 'Year']
ahp = AHP(object_names=criteria_names)
weights = ahp() # Command line interface for matrix filling starts here.
print(weights)
print(ahp.get_cr()) # To check CR use get_cr() method
ahp.to_csv('ahp_matrix.csv') # Don't forget to save your matrix for later usage.
Please compare two objects:
Choose values in scale from 1 to 9 where:
1: if "Price" is equally important to "Mileage";
3: if "Price" is weakly preferred than to "Mileage";
5: if "Price" is strongly preferred than to "Mileage";
7: if "Price" is very strongly preferred than to "Mileage";
9: if "Price" is extremely more important than "Mileage";
OR value in scale 1 to 1/9 where:
1: if "Mileage" is equally important to "Price";
1/3: if "Mileage" is weakly preferred than to "Price";
1/5: if "Mileage" is strongly preferred than to "Price";
1/7: if "Mileage" is very strongly preferred than to "Price";
1/9: if "Mileage" is extremely more important than "Price".
Your answer: 5
Please compare two objects:
Choose values in scale from 1 to 9 where:
1: if "Price" is equally important to "Year";
3: if "Price" is weakly preferred than to "Year";
5: if "Price" is strongly preferred than to "Year";
7: if "Price" is very strongly preferred than to "Year";
9: if "Price" is extremely more important than "Year";
OR value in scale 1 to 1/9 where:
1: if "Year" is equally important to "Price";
1/3: if "Year" is weakly preferred than to "Price";
1/5: if "Year" is strongly preferred than to "Price";
1/7: if "Year" is very strongly preferred than to "Price";
1/9: if "Year" is extremely more important than "Price".
Your answer: 1/2
Please compare two objects:
Choose values in scale from 1 to 9 where:
1: if "Mileage" is equally important to "Year";
3: if "Mileage" is weakly preferred than to "Year";
5: if "Mileage" is strongly preferred than to "Year";
7: if "Mileage" is very strongly preferred than to "Year";
9: if "Mileage" is extremely more important than "Year";
OR value in scale 1 to 1/9 where:
1: if "Year" is equally important to "Mileage";
1/3: if "Year" is weakly preferred than to "Mileage";
1/5: if "Year" is strongly preferred than to "Mileage";
1/7: if "Year" is very strongly preferred than to "Mileage";
1/9: if "Year" is extremely more important than "Mileage".
Your answer: 7
[0.43298618 0.35689191 0.21012191]
2.038220426046577
[6]:
# Now, with previously saved matrix you can skip questions if needed:
ahp = AHP(filename='ahp_matrix.csv')
print(ahp())
[0.43298618 0.35689191 0.21012191]
RANCOM
The implementation of the RANCOM (RANking COMparison) in the pymcdm library is designed with specific features.
For both AHP and RANCOM methods, method’s object can be instantiated using:
Scores - provide scores for each criterion as
np.array(). Larger values indicates more important criteria.Ranking - provide ranking for each criterion as
np.array(). Smaller values indicates more important criteria.Comparison matrix - input complete matrix. Note, that matrix is validated to check if all values are fits in 1-9 Saaty scale.
Text file with comparison matrix, in
.csvformat. Same validation is applied as in case of comparison matrix.Manual comparison via command line interface.
[7]:
# Suppose we have three criteria to evaluate. Define the scoring vector for them:
scores = np.array([10, 3, 5])
# You can use any positive numbers above zero to define scoring vector.
# Create RANCOM object:
rancom = RANCOM(scoring=scores) # Note that only one argument can be provided.
weights = rancom() # Call the object to get weights.
print(weights)
[0.55555556 0.11111111 0.33333333]
[8]:
# Suppose we have three criteria to evaluate. Define the ranking vector for them:
ranking = np.array([1, 3, 2])
# You can use any positive numbers above zero to define ranking vector.
rancom = RANCOM(ranking=ranking)
weights = rancom() # Call the object to get weights.
print(weights)
[0.55555556 0.11111111 0.33333333]
[9]:
# And there are also command line interface to fill pairwise matrix step-by-step. See the output below.
criteria_names = ['Price', 'Mileage', 'Year']
rancom = RANCOM(object_names=criteria_names)
weights = rancom() # Command line interface for matrix filling starts here.
print(weights)
rancom.to_csv('rancom_matrix.csv') # Don't forget to save your matrix for later usage.
Please compare two objects:
Choose:
1: if "Price" is more important than "Mileage";
1/2: if "Price" is equally important to "Mileage";
0: if "Mileage" is more important than "Price".
Your answer: 1
Please compare two objects:
Choose:
1: if "Price" is more important than "Year";
1/2: if "Price" is equally important to "Year";
0: if "Year" is more important than "Price".
Your answer: 1/2
Please compare two objects:
Choose:
1: if "Mileage" is more important than "Year";
1/2: if "Mileage" is equally important to "Year";
0: if "Year" is more important than "Mileage".
Your answer: 1
[0.44444444 0.33333333 0.22222222]
[10]:
# Now, with previously saved matrix you can skip questions if needed:
rancom = RANCOM(filename='rancom_matrix.csv')
print(rancom())
[0.44444444 0.33333333 0.22222222]