{ "cells": [ { "cell_type": "markdown", "id": "b022edca-32bc-4c00-afb5-4eaf28315233", "metadata": {}, "source": [ "# Verbose MCDA and output\n", "\n", "The `pymcdm` library provides a feature that enables users to generate and document all the internal steps of MCDA methods, offering insights into the intermediate calculations and processes. This functionality is particularly useful for understanding how the final results are derived, verifying the correctness of computations, or preparing detailed reports.\n", "\n", "In this example, we demonstrate how to use this functionality to output the intermediate steps of an MCDA method in either LaTeX or plain text format.\n", "\n", "## Decision problem definition\n", "\n", "First, we need to define the decision problem. There are also options to create pretty formatted table with criteria descriptions.\n", "\n", "Consider example, where we want to choose used car, based on mileage, price and manufacturing year." ] }, { "cell_type": "code", "execution_count": 1, "id": "e17c9e31-d4f9-4f23-a237-61706b6ba733", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Criteria description.\n", " $C_i$ Criterion Name Unit Weight Type\n", "$C_{1}$ Mileage k km 0.3333 Min\n", "$C_{2}$ Price k PLN 0.5556 Min\n", "$C_{3}$ Year Year 0.1111 Max \n", "\n", "\\begin{table}[h]\n", "\\caption{Criteria description.}\n", "\\label{crit_desc}\n", "\\begin{tabular}{lllrl}\n", "\\toprule\n", "$C_i$ & Criterion Name & Unit & Weight & Type \\\\\n", "\\midrule\n", "$C_{1}$ & Mileage & k km & 0.3333 & Min \\\\\n", "$C_{2}$ & Price & k PLN & 0.5556 & Min \\\\\n", "$C_{3}$ & Year & Year & 0.1111 & Max \\\\\n", "\\bottomrule\n", "\\end{tabular}\n", "\\end{table}\n", "\n" ] } ], "source": [ "import numpy as np\n", "import pymcdm as pm\n", "\n", "# This two are lists are optional, only for criteria description table\n", "# You don't neet to define them, if you don't want\n", "criteria_names = ['Mileage', 'Price', 'Year']\n", "criteria_units = ['k km', 'k PLN', 'Year']\n", "\n", "# Define the decision matrix or input it from the file\n", "matrix = np.array([\n", " [ 94.0, 69.9, 2017],\n", " [297.0, 42.0, 2013],\n", " [205.0, 68.9, 2015],\n", " [360.0, 36.9, 2014],\n", " [ 86.0, 59.9, 2017],\n", " [ 79.6, 63.8, 2017],\n", " [113.0, 56.9, 2015],\n", " [171.0, 58.0, 2016]\n", "])\n", "\n", "# We define criteria weights using RANCOM method:\n", "rancom = pm.weights.subjective.RANCOM(scoring=[3, 5, 1])\n", "weights = rancom()\n", "\n", "# We define types as min, min, max:\n", "types = [-1, -1, 1]\n", "\n", "# Next, use pymcdm.io module for genereting criteria description table and output it\n", "problem = pm.io.MCDA_problem(matrix=matrix,\n", " weights=weights,\n", " types=types,\n", " criteria_names=criteria_names,\n", " criteria_units=criteria_units)\n", "# Normal output as str\n", "print(problem, '\\n')\n", "\n", "# Output as LaTeX\n", "print(problem.to_latex())" ] }, { "cell_type": "markdown", "id": "22de2822-76e9-4ed7-82ef-657a02efa722", "metadata": {}, "source": [ "## Application of the MCDM methods with verbose argument\n", "\n", "Next, we can apply chosed decision method to create preference vector and then ranking. In this example we will use the TOPSIS method with default normalization (min-max)." ] }, { "cell_type": "code", "execution_count": 2, "id": "90674c63-03a4-406e-b55d-478dacd7bf55", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[7. 2. 8. 1. 4. 6. 3. 5.]\n" ] } ], "source": [ "topsis = pm.methods.TOPSIS()\n", "\n", "pref = topsis(matrix, weights, types)\n", "rank = topsis.rank(pref)\n", "\n", "print(rank)" ] }, { "cell_type": "markdown", "id": "705d4875-1a9a-4d15-9ad1-24e2a1c4092f", "metadata": {}, "source": [ "Hovewer, if we want to investigate the process of the calculations we should add `verbose=True` parameter to the call.\n", "\n", "This makes the TOPSIS method return not preferences, but `MCDA_Results` object, which contains and manage all intermediate results and allow to format them in different output formats." ] }, { "cell_type": "code", "execution_count": 3, "id": "86f3573d-45b8-4ade-b236-1d6d7ad38540", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Results for the TOPSIS method.\n", "\n", "Decision matrix ($x_{ij}$)\n", "$A_{i}$ $C_{1}$ $C_{2}$ $C_{3}$\n", "$A_{1}$ 94.0000 69.9000 2017\n", "$A_{2}$ 297.0000 42.0000 2013\n", "$A_{3}$ 205.0000 68.9000 2015\n", "$A_{4}$ 360.0000 36.9000 2014\n", "$A_{5}$ 86.0000 59.9000 2017\n", "$A_{6}$ 79.6000 63.8000 2017\n", "$A_{7}$ 113.0000 56.9000 2015\n", "$A_{8}$ 171.0000 58.0000 2016\n", "\n", "Normalized decision matrix ($r_{ij}$)\n", "$A_{i}$ $C_{1}$ $C_{2}$ $C_{3}$\n", "$A_{1}$ 0.9486 0.0000 1.0000\n", "$A_{2}$ 0.2247 0.8455 0.0000\n", "$A_{3}$ 0.5528 0.0303 0.5000\n", "$A_{4}$ 0.0000 1.0000 0.2500\n", "$A_{5}$ 0.9772 0.3030 1.0000\n", "$A_{6}$ 1.0000 0.1848 1.0000\n", "$A_{7}$ 0.8809 0.3939 0.5000\n", "$A_{8}$ 0.6740 0.3606 0.7500\n", "\n", "Weighted normalized decision matrix ($v_{ij}$)\n", "$A_{i}$ $C_{1}$ $C_{2}$ $C_{3}$\n", "$A_{1}$ 0.3162 0.0000 0.1111\n", "$A_{2}$ 0.0749 0.4697 0.0000\n", "$A_{3}$ 0.1843 0.0168 0.0556\n", "$A_{4}$ 0.0000 0.5556 0.0278\n", "$A_{5}$ 0.3257 0.1684 0.1111\n", "$A_{6}$ 0.3333 0.1027 0.1111\n", "$A_{7}$ 0.2936 0.2189 0.0556\n", "$A_{8}$ 0.2247 0.2003 0.0833\n", "\n", "Negative Ideal Solution, Positive Ideal Solution\n", "$C_{j}$ $v^{-}_{j}$ $v^{+}_{j}$\n", "$C_{1}$ 0.0000 0.3333\n", "$C_{2}$ 0.0000 0.5556\n", "$C_{3}$ 0.0000 0.1111\n", "\n", "Distance from NIS, Distance from PIS, Final preference values, Final ranking\n", "$A_{i}$ $D_i^-$ $D_i^+$ $P_i$ $R_{i}$\n", "$A_{1}$ 0.3352 0.5558 0.3762 7\n", "$A_{2}$ 0.4756 0.2941 0.6179 2\n", "$A_{3}$ 0.1932 0.5617 0.2559 8\n", "$A_{4}$ 0.5562 0.3436 0.6182 1\n", "$A_{5}$ 0.3831 0.3873 0.4973 4\n", "$A_{6}$ 0.3661 0.4529 0.4470 6\n", "$A_{7}$ 0.3704 0.3436 0.5188 3\n", "$A_{8}$ 0.3123 0.3725 0.4561 5\n", "\n", "Total 5 tables.\n", "\n" ] } ], "source": [ "results = topsis(matrix, weights, types, verbose=True)\n", "\n", "print(results)" ] }, { "cell_type": "code", "execution_count": 4, "id": "934e784f-2eb6-494d-8532-290b0cdd2f46", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Results for the TOPSIS method.\n", "\n", "\\begin{table}[h]\n", "\\centering\n", "\\caption{Decision matrix ($x_{ij}$)}\n", "\\label{tab:topsis_matrix}\n", "\\begin{tabular}{lrrr}\n", "\\toprule\n", "$A_{i}$ & $C_{1}$ & $C_{2}$ & $C_{3}$ \\\\\n", "\\midrule\n", "$A_{1}$ & 94.0000 & 69.9000 & 2017 \\\\\n", "$A_{2}$ & 297.0000 & 42.0000 & 2013 \\\\\n", "$A_{3}$ & 205.0000 & 68.9000 & 2015 \\\\\n", "$A_{4}$ & 360.0000 & 36.9000 & 2014 \\\\\n", "$A_{5}$ & 86.0000 & 59.9000 & 2017 \\\\\n", "$A_{6}$ & 79.6000 & 63.8000 & 2017 \\\\\n", "$A_{7}$ & 113.0000 & 56.9000 & 2015 \\\\\n", "$A_{8}$ & 171.0000 & 58.0000 & 2016 \\\\\n", "\\bottomrule\n", "\\end{tabular}\n", "\\end{table}\n", "\n", "\n", "\\begin{table}[h]\n", "\\centering\n", "\\caption{Normalized decision matrix ($r_{ij}$)}\n", "\\label{tab:topsis_nmatrix}\n", "\\begin{tabular}{lrrr}\n", "\\toprule\n", "$A_{i}$ & $C_{1}$ & $C_{2}$ & $C_{3}$ \\\\\n", "\\midrule\n", "$A_{1}$ & 0.9486 & 0.0000 & 1.0000 \\\\\n", "$A_{2}$ & 0.2247 & 0.8455 & 0.0000 \\\\\n", "$A_{3}$ & 0.5528 & 0.0303 & 0.5000 \\\\\n", "$A_{4}$ & 0.0000 & 1.0000 & 0.2500 \\\\\n", "$A_{5}$ & 0.9772 & 0.3030 & 1.0000 \\\\\n", "$A_{6}$ & 1.0000 & 0.1848 & 1.0000 \\\\\n", "$A_{7}$ & 0.8809 & 0.3939 & 0.5000 \\\\\n", "$A_{8}$ & 0.6740 & 0.3606 & 0.7500 \\\\\n", "\\bottomrule\n", "\\end{tabular}\n", "\\end{table}\n", "\n", "\n", "\\begin{table}[h]\n", "\\centering\n", "\\caption{Weighted normalized decision matrix ($v_{ij}$)}\n", "\\label{tab:topsis_wnmatrix}\n", "\\begin{tabular}{lrrr}\n", "\\toprule\n", "$A_{i}$ & $C_{1}$ & $C_{2}$ & $C_{3}$ \\\\\n", "\\midrule\n", "$A_{1}$ & 0.3162 & 0.0000 & 0.1111 \\\\\n", "$A_{2}$ & 0.0749 & 0.4697 & 0.0000 \\\\\n", "$A_{3}$ & 0.1843 & 0.0168 & 0.0556 \\\\\n", "$A_{4}$ & 0.0000 & 0.5556 & 0.0278 \\\\\n", "$A_{5}$ & 0.3257 & 0.1684 & 0.1111 \\\\\n", "$A_{6}$ & 0.3333 & 0.1027 & 0.1111 \\\\\n", "$A_{7}$ & 0.2936 & 0.2189 & 0.0556 \\\\\n", "$A_{8}$ & 0.2247 & 0.2003 & 0.0833 \\\\\n", "\\bottomrule\n", "\\end{tabular}\n", "\\end{table}\n", "\n", "\n", "\\begin{table}[h]\n", "\\centering\n", "\\caption{Negative Ideal Solution, Positive Ideal Solution}\n", "\\label{tab:topsis_nis_pis}\n", "\\begin{tabular}{lrr}\n", "\\toprule\n", "$C_{j}$ & $v^{-}_{j}$ & $v^{+}_{j}$ \\\\\n", "\\midrule\n", "$C_{1}$ & 0.0000 & 0.3333 \\\\\n", "$C_{2}$ & 0.0000 & 0.5556 \\\\\n", "$C_{3}$ & 0.0000 & 0.1111 \\\\\n", "\\bottomrule\n", "\\end{tabular}\n", "\\end{table}\n", "\n", "\n", "\\begin{table}[h]\n", "\\centering\n", "\\caption{Distance from NIS, Distance from PIS, Final preference values, Final ranking}\n", "\\label{tab:topsis_dnis_dpis_pref_ranking}\n", "\\begin{tabular}{lrrrr}\n", "\\toprule\n", "$A_{i}$ & $D_i^-$ & $D_i^+$ & $P_i$ & $R_{i}$ \\\\\n", "\\midrule\n", "$A_{1}$ & 0.3352 & 0.5558 & 0.3762 & 7 \\\\\n", "$A_{2}$ & 0.4756 & 0.2941 & 0.6179 & 2 \\\\\n", "$A_{3}$ & 0.1932 & 0.5617 & 0.2559 & 8 \\\\\n", "$A_{4}$ & 0.5562 & 0.3436 & 0.6182 & 1 \\\\\n", "$A_{5}$ & 0.3831 & 0.3873 & 0.4973 & 4 \\\\\n", "$A_{6}$ & 0.3661 & 0.4529 & 0.4470 & 6 \\\\\n", "$A_{7}$ & 0.3704 & 0.3436 & 0.5188 & 3 \\\\\n", "$A_{8}$ & 0.3123 & 0.3725 & 0.4561 & 5 \\\\\n", "\\bottomrule\n", "\\end{tabular}\n", "\\end{table}\n", "\n", "\n", "Total 5 tables.\n", "\n" ] } ], "source": [ "print(results.to_latex())" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.2" } }, "nbformat": 4, "nbformat_minor": 5 }