Example 05: Intuitionistic pipeline¶
Seven-term IF ratings from three experts are aggregated into a decision matrix, criteria are weighted with IF-SWARA and the plans are ranked with VIKOR.
Source¶
examples/05_intuitionistic_pipeline.py
"""Intuitionistic pipeline: IF expert ratings, IF-SWARA weights, VIKOR ranking."""
from bulanik.mcdm import DecisionMatrix, rank_fuzzy, swara
from bulanik.scales import EXAMPLE_IFN_7
alternatives = ["Plan A", "Plan B", "Plan C"]
criteria = ["cost", "risk", "benefit"]
types = ["cost", "cost", "benefit"]
# three experts rate [alternative][criterion] with 7-term IF words
experts = [
[["M", "L", "H"], ["H", "M", "VH"], ["L", "VL", "M"]],
[["M", "M", "H"], ["VH", "M", "H"], ["L", "L", "M"]],
[["L", "L", "VH"], ["H", "H", "VH"], ["M", "VL", "H"]],
]
matrix = DecisionMatrix.from_terms(
EXAMPLE_IFN_7, alternatives, criteria, experts, expert_weights=[0.4, 0.3, 0.3]
)
# criteria listed most important first; comparative importances are IF numbers,
# mapped to [0, 1] with the "normalized" score (1 + mu - nu) / 2
importance = [EXAMPLE_IFN_7["L"], EXAMPLE_IFN_7["M"]]
weights = swara(importance, criteria, score="normalized")
print("weights:", {k: round(v, 4) for k, v in weights.weights.items()})
result = rank_fuzzy(
matrix, weights, types, method="vikor", aggregation="wa", ops="algebraic"
)
print("ranking:", " > ".join(result.ranking))
print("operators:", result.operators)
for name in result.ranking:
print(f"{name}: Q {result.scores[name]:.4f}")
# VIKOR ranks by ascending Q: Plans A and C are close, Plan B is clearly worst (Q = 1)
assert result.ranking == ("Plan A", "Plan C", "Plan B")
expected_q = {"Plan A": 0.0889, "Plan C": 0.0905, "Plan B": 1.0}
assert all(abs(result.scores[k] - v) < 5e-5 for k, v in expected_q.items())
expected_w = {"cost": 0.4507, "risk": 0.3339, "benefit": 0.2154}
assert all(abs(weights.weights[k] - v) < 5e-5 for k, v in expected_w.items())
assert result.operators["score"] == "difference" and result.operators["aggregation"] == "wa"
assert abs(sum(weights.weights.values()) - 1.0) < 1e-9
Output¶
Run when this page is built:
weights: {'cost': 0.4507, 'risk': 0.3339, 'benefit': 0.2154}
ranking: Plan A > Plan C > Plan B
operators: {'normalization': 'linear_range', 'v': '0.5', 'aggregation': 'wa', 'ops': 'algebraic', 'score': 'difference'}
Plan A: Q 0.0889
Plan C: Q 0.0905
Plan B: Q 1.0000
What to notice¶
- The whole pipeline stays intuitionistic until the final score; nothing is defuzzified early.
- The
operatorsline records the normalisation, aggregation, operator family and score the ranking used. - VIKOR ranks by Q, lower is better, so Plan A (smallest Q) comes first.
Go further¶
- Guide: Aggregation
- Guide: Weighting
- Guide: Ranking
- API:
bulanik.mcdm
Run it yourself: python examples/05_intuitionistic_pipeline.py.