AHP Examples

Christoph Glur

2018-03-06

Introduction

What is AHP?

AHP is a method allowing individuals or groups to make complex decisions. The core concept of AHP is that alternatives are always compared pairwise (and not, say, by giving a score, or sorting alternatives). AHP is used in many fields, from finance to criminal investigation.

For a general introduction to AHP, you might be interested in this.

Another good introduction is here

For a more formal introduction to the subject, see: Saaty, T. L. (2001). Decision Making for Leaders: The Analytic Hierarchy Process for Decisions in a Complex World, New Edition 2001 (3 Revised). Pittsburgh, PA: RWS Publications.

About this Package

This package is built on top of the data.tree package, and uses R6 reference classes. To learn more about these, you might be interested in the Introduction:

library(R6)
vignette('Introduction', package = 'R6')

Even though this is not required, the data.tree Introduction vignette might also be helpful:

library(data.tree)
vignette(package = 'data.tree')

Car Example

This vignette follows a well-known AHP example that you can also find e.g. on Wikipedia. In this example, the Jones family wants to buy a new car and uses AHP to decide systematically which car they should buy. Even though a few details are different from the original article, it is recommended to consider this vignette as an extension of that article, and not as a self sufficient document.

When deciding which car to buy, the family considers the following criteria: cost, safety, style, and capacity. Additionally, some of the criteria have sub-criteria.

The Jones’ have a shortlist of 6 cars.

We can draw the hierarchy like this:

Ahp Tree

Ahp Tree

Model Specification

Using the ahp package, the AHP hierarchy tree can be defined in an ahp file. An ahp file is a text file in yaml format, following a few conventions. For example:

## Version: 2.0
## 
## #########################
## # Alternatives Section
## #
## 
## Alternatives: &alternatives
## # Here, we list all the alternatives, together with their attributes. 
## # We can use these attributes later in the file when defining 
## # preferenceFunctions. The attributes can be quantitative or 
## # qualitative.
##   Accord Sedan:
##     price: 20360
##     mpg: 31
##     passengers: 5
##     cargo: 14
##     curb weight: 3289
##     safety class: Midsize Car
##     crash rating: 4 in Side Impact Front
##     residual value: 0.52
##   Accord Hybrid:
##     price: 31090
##     mpg: 35
##     passengers: 5
##     cargo: 14
##     curb weight: 3501
##     safety class: Midsize Car
##     crash rating: 4 in Side Impact Front
##     residual value: 0.46
##   Pilot:
##     price: 27595
##     mpg: 22
##     passengers: 8
##     cargo: 87.6
##     curb weight: 4264
##     safety class: Midsize SUV
##     crash rating: 4 in Rollover
##     residual value: 0.4
##   CR-V:
##     price: 20700
##     mpg: 27
##     passengers: 5
##     cargo: 72.9
##     curb weight: 3389
##     safety class: Small SUV
##     crash rating: 4 in Rollover
##     residual value: 0.55
##   Element:
##     price: 18980
##     mpg: 25
##     passengers: 4
##     cargo: 74.6
##     curb weight: 3433
##     safety class: Small SUV
##     crash rating: 3 in Rollover
##     residual value: 0.48
##   Odyssey:
##     price: 25645
##     mpg: 26
##     passengers: 8
##     cargo: 147.4
##     curb weight: 4385
##     safety class: Minivan
##     crash rating: All 5 Stars
##     residual value: 0.48
## 
## #
## # End of Alternatives Section
## #####################################
## 
## #####################################
## # Goal Section
## #
## 
## 
## Goal:
## # The goal spans a tree of criteria and the alternatives
##   name: Buy Car
##   description: >
##     This is a classic single decision maker problem. It models
##     the situation facing by a family that wants to buy a new car.
##   author: unknown
##   preferences:
##     # preferences are typically defined pairwise
##     # 1 means: A is equal to B
##     # 9 means: A is highly preferrable to B
##     # 1/9 means: B is highly preferrable to A
##     pairwise:
##       - [Cost, Safety, 3]
##       - [Cost, Style, 7]
##       - [Cost, Capacity, 3]
##       - [Safety, Style, 9]
##       - [Safety, Capacity, 1]
##       - [Style, Capacity, 1/7]
##   children: 
##     Cost:
##       preferences:
##         pairwise:
##           - [Purchase Price, Fuel Cost, 2]
##           - [Purchase Price, Maintenance Cost, 5]
##           - [Purchase Price, Resale Value, 3]
##           - [Fuel Cost, Maintenance Cost, 2]
##           - [Fuel Cost, Resale Value, 2]
##           - [Maintenance Cost, Resale Value, 1/2]
##       children:
##         Purchase Price:
##           preferences: 
##             pairwise:
##               - [Accord Sedan, Accord Hybrid, 9]
##               - [Accord Sedan, Pilot, 9]
##               - [Accord Sedan, CR-V, 1]
##               - [Accord Sedan, Element, 1/2]
##               - [Accord Sedan, Odyssey, 5]
##               - [Accord Hybrid, Pilot, 1]
##               - [Accord Hybrid, CR-V, 1/9]
##               - [Accord Hybrid, Element, 1/9]
##               - [Accord Hybrid, Odyssey, 1/7]
##               - [Pilot, CR-V, 1/9]
##               - [Pilot, Element, 1/9]
##               - [Pilot, Odyssey, 1/7]
##               - [CR-V, Element, 1/2]
##               - [CR-V, Odyssey, 5]
##               - [Element, Odyssey, 6]
##           children: *alternatives
##           # We don't need to retype the alternatives here. Instead
##           # we can simply make a reference to the alternatives anchor
##           # defined in the alternatives section of the file.
##         Fuel Cost:
##           # Alternatively to the pairwise preferences, you 
##           # can define a preference function. This function
##           # is in R syntax, and needs to have two arguments.
##           # The Calculate method will pass all combinations
##           # of alternatives to this function, and the function
##           # is expected to return the pairwise preference, i.e.
##           # a number between 1/9 and 9.
##           preferences: 
##             pairwiseFunction:
##               function(a1, a2) min(9, max(1/9, a2$mpg/a1$mpg))
##           children: *alternatives
##         Maintenance Cost: 
##           preferences:
##             pairwise:
##               - [Accord Sedan, Accord Hybrid, 1.5]
##               - [Accord Sedan, Pilot, 4]
##               - [Accord Sedan, CR-V, 4]
##               - [Accord Sedan, Element, 4]
##               - [Accord Sedan, Odyssey, 5]
##               - [Accord Hybrid, Pilot, 4]
##               - [Accord Hybrid, CR-V, 4]
##               - [Accord Hybrid, Element, 4]
##               - [Accord Hybrid, Odyssey, 5]
##               - [Pilot, CR-V, 1]
##               - [Pilot, Element, 1.2]
##               - [Pilot, Odyssey, 1]
##               - [CR-V, Element, 1]
##               - [CR-V, Odyssey, 3]
##               - [Element, Odyssey, 2]
##           children: *alternatives
##         Resale Value:
##           preferences:
##             pairwiseFunction: >
##               GetResalePreference <- function(a1, a2) {
##                 if (a1$`residual value` < a2$`residual value`) return (1/GetResalePreference(a2, a1))
##                 ratio <- a1$`residual value` / a2$`residual value`
##                 if (ratio < 1.05) return (1)
##                 if (ratio < 1.1) return (2)
##                 if (ratio < 1.15) return (3)
##                 if (ratio < 1.2) return (4)
##                 if (ratio < 1.25) return (5)
##                 return (5)
##               }
##           children: *alternatives 
##     Safety: 
##       preferences:
##         pairwise:
##           - [Accord Sedan, Accord Hybrid, 1]
##           - [Accord Sedan, Pilot, 5]
##           - [Accord Sedan, CR-V, 7]
##           - [Accord Sedan, Element, 9]
##           - [Accord Sedan, Odyssey, 1/3]
##           - [Accord Hybrid, Pilot, 5]
##           - [Accord Hybrid, CR-V, 7]
##           - [Accord Hybrid, Element, 9]
##           - [Accord Hybrid, Odyssey, 1/3]
##           - [Pilot, CR-V, 2]
##           - [Pilot, Element, 9]
##           - [Pilot, Odyssey, 1/8]
##           - [CR-V, Element, 2]
##           - [CR-V, Odyssey, 1/8]
##           - [Element, Odyssey, 1/9]
##       children: *alternatives
##     Style: 
##       preferences: 
##         pairwise:
##           - [Accord Sedan, Accord Hybrid, 1]
##           - [Accord Sedan, Pilot, 7]
##           - [Accord Sedan, CR-V, 5]
##           - [Accord Sedan, Element, 9]
##           - [Accord Sedan, Odyssey, 6]
##           - [Accord Hybrid, Pilot, 7]
##           - [Accord Hybrid, CR-V, 5]
##           - [Accord Hybrid, Element, 9]
##           - [Accord Hybrid, Odyssey, 6]
##           - [Pilot, CR-V, 1/6]
##           - [Pilot, Element, 3]
##           - [Pilot, Odyssey, 1/3]
##           - [CR-V, Element, 7]
##           - [CR-V, Odyssey, 5]
##           - [Element, Odyssey, 1/5]
##       children: *alternatives
##     Capacity:
##       preferences:
##         pairwise:
##           - [Cargo Capacity, Passenger Capacity, 1/5]
##       children:
##         Cargo Capacity: 
##           preferences:
##             pairwiseFunction: >
##               CargoPreference <- function(a1, a2) {
##                 if (a1$cargo < a2$cargo) return (1/CargoPreference(a2, a1))
##                 ratio <- a1$cargo / a2$cargo
##                 if (ratio < 3) return (1)
##                 if (ratio < 8) return (2)
##                 return (3)
##               }
##           children: *alternatives
##         Passenger Capacity: 
##           preferences:
##             pairwise:
##               - [Accord Sedan, Accord Hybrid, 1]
##               - [Accord Sedan, Pilot, 1/2]
##               - [Accord Sedan, CR-V, 1]
##               - [Accord Sedan, Element, 3]
##               - [Accord Sedan, Odyssey, 1/2]
##               - [Accord Hybrid, Pilot, 1/2]
##               - [Accord Hybrid, CR-V, 1]
##               - [Accord Hybrid, Element, 3]
##               - [Accord Hybrid, Odyssey, 1/2]
##               - [Pilot, CR-V, 2]
##               - [Pilot, Element, 6]
##               - [Pilot, Odyssey, 1]
##               - [CR-V, Element, 3]
##               - [CR-V, Odyssey, 1/2]
##               - [Element, Odyssey, 1/6]
##           children: *alternatives
## 
## #
## # End of Goal Section
## #####################################

Let’s look at the various elements of this file.

Alternatives

The first section is a list of alternatives. Note that they have properties. For example:

Alternatives: &alternatives
              Accord Sedan:
                price: 20360
                mpg: 31
                passengers: 5
                cargo: 14
                curb weight: 3289
                safety class: Midsize Car
                crash rating: 4 in Side Impact Front
                residual value: 0.52
              Accord Hybrid:
                price: 31090
                mpg: 35
                passengers: 5
                ...

You are entirely free regarding the type and format of information you store in your alternatives. Some models can do without any properties at all. However, often you would like to define your preferences as a function of properties. Later, you will see how you can define functions that refer to these properties to derive the pairwise preferences of alternatives with respect to a specific criteria.

Goal

The second section of the ahp file is the Goal. Here, you define your criteria tree, your pairwise preferences, and - if applicable - your preference functions.

Criteria

Criteria are grouped hierarchically. Each criteria has at least the following sections:

  1. a name of the criteria (e.g. Cost)
  2. the preferences, either
    • pairwise preferences, or
    • a preferenceFunction
  3. its sub-criteria (e.g. Maintenance Cost) or alternatives, as we’ll see in the next section

An example of a criteria which has explicit pairwise preference is the

Cost:
  preferences:
    pairwise:
      - [Purchase Price, Fuel Cost, 2]
      - [Purchase Price, Maintenance Cost, 5]
      - [Purchase Price, Resale Value, 3]
      - [Fuel Cost, Maintenance Cost, 2]
      - [Fuel Cost, Resale Value, 2]
      - [Maintenance Cost, Resale Value, 1/2]
  children:
    Purchase Price:
      preferences: 
      ...

Here, we say, for instance, that Purchase Price is slightly more important to Fuel Cost. Purchase Price is, however, much more important than maintenance cost.

Alternatives

To keep the ahp file short, you can reference to the alternatives defined above. In order for this to work, your alternatives need to be defined as an anchor, using the & sign:

Alternatives: &alternatives
              Accord Sedan:
                price: 20360
                ...

Note that this is a standard YAML feature.

You can then later refer to the anchor using the * reference feature:

Style: 
  preferences: 
    pairwise:
      - [Accord Sedan, Accord Hybrid, 1]
      - [Accord Sedan, Pilot, 7]
      - [Accord Sedan, CR-V, 5]
      - [Accord Sedan, Element, 9]
      - [Accord Sedan, Odyssey, 6]
      - [Accord Hybrid, Pilot, 7]
      - [Accord Hybrid, CR-V, 5]
      - [Accord Hybrid, Element, 9]
      - [Accord Hybrid, Odyssey, 6]
      - [Pilot, CR-V, 1/6]
      - [Pilot, Element, 3]
      - [Pilot, Odyssey, 1/3]
      - [CR-V, Element, 7]
      - [CR-V, Odyssey, 5]
      - [Element, Odyssey, 1/5]
  children: *alternatives

Preference Function

Instead of defining the preferences explicitly in a pairwise manner, you can define a preference function. For example, you can define

Fuel Cost:
  preferences: 
    function:
      function(a1, a2) min(9, max(1/9, a1$mpg/a2$mpg))
  children: *alternatives
  ...

Note that, in this case, we have a field preferenceFunction instead of preferences. The function itself is a standard R function, and the arguments a1 and a2 are pairwise combinations of the criteria, i.e. in this case, the alternatives.

Here, we simply say that the AHP preference is the ratio of the mpg (i.e. miles per gallon) a car uses. And since we store properties mpg on the alternatives, we can reference them directly here. We want the ratio to be between 1/9 and 9, as these are the typical AHP acceptable preferences.

You can even define a named preference function that you can use for recursion:

Resale Value:
  preferences:
    function: >
      GetResalePreference <- function(a1, a2) {
        if (a1$`residual value` < a2$`residual value`) return (1/GetResalePreference(a2, a1))
        ratio <- a1$`residual value` / a2$`residual value`
        if (ratio < 1.05) return (1)
        if (ratio < 1.1) return (2)
        if (ratio < 1.15) return (3)
        if (ratio < 1.2) return (4)
        if (ratio < 1.25) return (5)
        return (5)
      }
    children: *alternatives 

Load

Loading the file is done by calling LoadFile:

library(ahp)
ahpFile <- system.file("extdata", "car.ahp", package="ahp")
carAhp <- Load(ahpFile)

carAhp, the return value of LoadFile, is a data.tree structure. Its structure is the same as the one of the file. If you are interested in solving AHP problems programmatically, all you need to do is to create a tree with that structure, using the data.tree functions.

library(data.tree)
print(carAhp, filterFun = isNotLeaf)
##                     levelName
## 1  Buy Car                   
## 2   ¦--Cost                  
## 3   ¦   ¦--Purchase Price    
## 4   ¦   ¦--Fuel Cost         
## 5   ¦   ¦--Maintenance Cost  
## 6   ¦   °--Resale Value      
## 7   ¦--Safety                
## 8   ¦--Style                 
## 9   °--Capacity              
## 10      ¦--Cargo Capacity    
## 11      °--Passenger Capacity

Calculate

Calculate(carAhp)
print(carAhp, priority = function(x) x$parent$priority["Total", x$name])
##                     levelName   priority
## 1  Buy Car                            NA
## 2   ¦--Cost                   0.51007502
## 3   ¦   ¦--Purchase Price     0.48805379
## 4   ¦   ¦   ¦--Accord Sedan   0.24617542
## 5   ¦   ¦   ¦--Accord Hybrid  0.02455426
## 6   ¦   ¦   ¦--Pilot          0.02455426
## 7   ¦   ¦   ¦--CR-V           0.24617542
## 8   ¦   ¦   ¦--Element        0.36575063
## 9   ¦   ¦   °--Odyssey        0.09279001
## 10  ¦   ¦--Fuel Cost          0.25153610
## 11  ¦   ¦   ¦--Accord Sedan   0.14544902
## 12  ¦   ¦   ¦--Accord Hybrid  0.12882628
## 13  ¦   ¦   ¦--Pilot          0.20495090
## 14  ¦   ¦   ¦--CR-V           0.16699703
## 15  ¦   ¦   ¦--Element        0.18035679
## 16  ¦   ¦   °--Odyssey        0.17341999
## 17  ¦   ¦--Maintenance Cost   0.09986256
## 18  ¦   ¦   ¦--Accord Sedan   0.35819852
## 19  ¦   ¦   ¦--Accord Hybrid  0.31325042
## 20  ¦   ¦   ¦--Pilot          0.08369953
## 21  ¦   ¦   ¦--CR-V           0.09953251
## 22  ¦   ¦   ¦--Element        0.08791282
## 23  ¦   ¦   °--Odyssey        0.05740619
## 24  ¦   °--Resale Value       0.16054755
## 25  ¦       ¦--Accord Sedan   0.23408904
## 26  ¦       ¦--Accord Hybrid  0.11101029
## 27  ¦       ¦--Pilot          0.03808108
## 28  ¦       ¦--CR-V           0.36023288
## 29  ¦       ¦--Element        0.12829335
## 30  ¦       °--Odyssey        0.12829335
## 31  ¦--Safety                 0.23435219
## 32  ¦   ¦--Accord Sedan       0.21624385
## 33  ¦   ¦--Accord Hybrid      0.21624385
## 34  ¦   ¦--Pilot              0.07515991
## 35  ¦   ¦--CR-V               0.03603025
## 36  ¦   ¦--Element            0.02229468
## 37  ¦   °--Odyssey            0.43402745
## 38  ¦--Style                  0.04051875
## 39  ¦   ¦--Accord Sedan       0.35785923
## 40  ¦   ¦--Accord Hybrid      0.35785923
## 41  ¦   ¦--Pilot              0.03886101
## 42  ¦   ¦--CR-V               0.15508522
## 43  ¦   ¦--Element            0.02275249
## 44  ¦   °--Odyssey            0.06758283
## 45  °--Capacity               0.21505404
## 46      ¦--Cargo Capacity     0.16666667
## 47      ¦   ¦--Accord Sedan   0.09193018
## 48      ¦   ¦--Accord Hybrid  0.09193018
## 49      ¦   ¦--Pilot          0.19640904
## 50      ¦   ¦--CR-V           0.19640904
## 51      ¦   ¦--Element        0.19640904
## 52      ¦   °--Odyssey        0.22691251
## 53      °--Passenger Capacity 0.83333333
## 54          ¦--Accord Sedan   0.13636364
## 55          ¦--Accord Hybrid  0.13636364
## 56          ¦--Pilot          0.27272727
## 57          ¦--CR-V           0.13636364
## 58          ¦--Element        0.04545455
## 59          °--Odyssey        0.27272727

Don’t worry if you don’t understand this command. But if you are interested you might want to look into the structure of carAhp, and read up on data.tree documentation.

Visualize

Visualize(carAhp)
visualize

visualize

Analyze

Analyze(carAhp)
##                               Weight Odyssey Accord Sedan  CR-V Element Accord Hybrid Pilot Inconsistency
## 1  Buy Car                    100.0%   22.0%        21.0% 16.3%   15.1%         14.1% 11.5%          7.5%
## 2   ¦--Cost                    51.0%    5.9%        11.7% 11.7%   12.9%          4.8%  4.0%          1.5%
## 3   ¦   ¦--Purchase Price      24.9%    2.3%         6.1%  6.1%    9.1%          0.6%  0.6%          6.8%
## 4   ¦   ¦--Fuel Cost           12.8%    2.2%         1.9%  2.1%    2.3%          1.7%  2.6%          0.0%
## 5   ¦   ¦--Resale Value         8.2%    1.1%         1.9%  2.9%    1.1%          0.9%  0.3%          3.2%
## 6   ¦   °--Maintenance Cost     5.1%    0.3%         1.8%  0.5%    0.4%          1.6%  0.4%          2.3%
## 7   ¦--Safety                  23.4%   10.2%         5.1%  0.8%    0.5%          5.1%  1.8%          8.0%
## 8   ¦--Capacity                21.5%    5.7%         2.8%  3.1%    1.5%          2.8%  5.6%          0.0%
## 9   ¦   ¦--Passenger Capacity  17.9%    4.9%         2.4%  2.4%    0.8%          2.4%  4.9%          0.0%
## 10  ¦   °--Cargo Capacity       3.6%    0.8%         0.3%  0.7%    0.7%          0.3%  0.7%          0.4%
## 11  °--Style                    4.1%    0.3%         1.5%  0.6%    0.1%          1.5%  0.2%         10.1%

Note that, thanks to the formattable package, the columns are numerics, even though they are formatted as percentages.

Another way to display the AHP analysis is with the ShowTable function, which displays an html table with color codings to help interpret the numbers:

AnalyzeTable(carAhp)
Weight Odyssey Accord Sedan CR-V Element Accord Hybrid Pilot Inconsistency
Buy Car 100.0% 22.0% 21.0% 16.3% 15.1% 14.1% 11.5% 7.5%
Cost 51.0% 5.9% 11.7% 11.7% 12.9% 4.8% 4.0% 1.5%
Purchase Price 24.9% 2.3% 6.1% 6.1% 9.1% 0.6% 0.6% 6.8%
Fuel Cost 12.8% 2.2% 1.9% 2.1% 2.3% 1.7% 2.6% 0.0%
Resale Value 8.2% 1.1% 1.9% 2.9% 1.1% 0.9% 0.3% 3.2%
Maintenance Cost 5.1% 0.3% 1.8% 0.5% 0.4% 1.6% 0.4% 2.3%
Safety 23.4% 10.2% 5.1% 0.8% 0.5% 5.1% 1.8% 8.0%
Capacity 21.5% 5.7% 2.8% 3.1% 1.5% 2.8% 5.6% 0.0%
Passenger Capacity 17.9% 4.9% 2.4% 2.4% 0.8% 2.4% 4.9% 0.0%
Cargo Capacity 3.6% 0.8% 0.3% 0.7% 0.7% 0.3% 0.7% 0.4%
Style 4.1% 0.3% 1.5% 0.6% 0.1% 1.5% 0.2% 10.1%

Finally, note that the Analyze and AnalyzeTable functions have many more options, e.g. to sort, filter, and further customize the output. For example:

AnalyzeTable(carAhp, 
             variable = "priority", 
             sort = "orig",
             pruneFun = function(node, decisionMaker) PruneByCutoff(node, decisionMaker, 0.05),
             weightColor = "skyblue",
             consistencyColor = "red",
             alternativeColor = "green")
Priority Accord Sedan Accord Hybrid Pilot CR-V Element Odyssey Inconsistency
Buy Car 100.0% 7.5%
Cost 51.0% 1.5%
Purchase Price 48.8% 24.6% 2.5% 2.5% 24.6% 36.6% 9.3% 6.8%
Fuel Cost 25.2% 14.5% 12.9% 20.5% 16.7% 18.0% 17.3% 0.0%
Maintenance Cost 10.0% 35.8% 31.3% 8.4% 10.0% 8.8% 5.7% 2.3%
Resale Value 16.1% 23.4% 11.1% 3.8% 36.0% 12.8% 12.8% 3.2%
Safety 23.4% 21.6% 21.6% 7.5% 3.6% 2.2% 43.4% 8.0%
Capacity 21.5% 0.0%
Passenger Capacity 83.3% 13.6% 13.6% 27.3% 13.6% 4.5% 27.3% 0.0%

Vacation Example (Multiple Decision Makers)

The ahp package also supports multiple decision makers, as shown by the vacation example, provided with the ahp package. The basic idea is that multiple people get to formulate their pairwise preferences, and then the AHP calculates the average. Often, each decision maker has the same voting weight, but that does not need to be the case.

In this example we look at a family that wants to decide where to go on vacation. There are two options: to the mountains, or to the beach. The family has already found a suitable hotel at each destination, and has calculated to total price of each destination. All three family members can vote on the destination, but mom and dad have twice the voting power of the kid.

Model Specification

The file is provided by the ahp package, and you may look at its content as so:

ahpFile <- system.file("extdata", "vacation.ahp", package="ahp")
cat(readChar(ahpFile, file.info(ahpFile)$size))
Version: 2.0
Alternatives: &alternatives
  Beach:
    cost: 10000
  Mountains:
    cost: 5000
Goal:
  name: Vacation
  decision-makers:
    #optional node, needed only if not all decision-makers have equal voting power
    - Dad: 0.4
    - Mom: 2/5
    - Kid: 0.2
  preferences:
    Dad:
      pairwise:
      - [Costs, Fun, 4]
      - [Costs, Spa, 9]
      - [Fun, Spa, 4]
    Mom:
      pairwise:
      - [Costs, Fun, 1/4]
      - [Costs, Spa, 1/9]
      - [Fun, Spa, 1/5]
    Kid:
      pairwise:
      - [Costs, Fun, 1/9]
      - [Costs, Spa, 1]
      - [Fun, Spa, 9]
  children:
    Costs:
      preferences:
        Dad:
          pairwiseFunction: 
            function(a1, a2) min(9, max(1/9, a2$cost/a1$cost))
        Mom:
          scoreFunction:
            function(a) 1/a$cost
        Kid:
          priority:
            - Beach: 1/2
            - Mountains: 0.5
      children: *alternatives
    Fun:
      preferences:
        Dad:
          pairwise:
            - [Beach, Mountains, 1/6]
        Mom:
          pairwise:
            - [Beach, Mountains, 2]
        Kid:
        # Often, entering pairwise preferences is lengthy, especially if you
        # have multiple alternatives. Instead, you can enter scores, i.e. rate
        # each alternative on a scale. The scale can be chosen freely. The 
        # priorities are derived as score / sum(scores)
          score:
            - Beach: 5
            - Mountains: 0
      children: *alternatives
    Spa:
      preferences:
        Dad:
          pairwise:
            - [Beach, Mountains, 2]
        Mom:
          pairwise:
            - [Beach, Mountains, 6]
        Kid:
          pairwise:
            - [Beach, Mountains, 1/2]
      children: *alternatives

The file structure is similar to the car.ahp file. There are two main differences, however:

The decision-maker section

In our example, this section is directly below the Goal:

  decision-makers:
    #optional node, needed only if not all decision-makers have equal voting power
    - Dad: 0.4
    - Mom: 2/5
    - Kid: 0.2

The node contains a map of decision makers, together with their respective weights. As the commentary says, this section is optional, and only required if you do not have equal voting power.

Additionally, there may be more than a single decision-makers section. If, for example, Dad has more voting power on the Cost criteria, and Mom more on the Spa, then you can add multiple decision-makers nodes. These weights are inherited, i.e. each criteria node checks if it has a decision-makers directive. If it doesn’t, it walks toward the root and checks on each ancestor. If it cannot find a directive, even at the root, it assumes equal voting power.

The preferences section

In the case of multiple decision makers, the preferences look like this:

  preferences:
    Dad:
      pairwise:
      - [Costs, Fun, 4]
      - [Costs, Spa, 9]
      - [Fun, Spa, 4]
    Mom:
      pairwise:
      - [Costs, Fun, 1/4]
      - [Costs, Spa, 1/9]
      - [Fun, Spa, 1/5]
    Kid:
      pairwise:
      - [Costs, Fun, 1/9]
      - [Costs, Spa, 1]
      - [Fun, Spa, 9]

Note, however, that different decision-makers can have different types of preferences, for instance:

    Costs:
      preferences:
        Dad:
          function: 
            function(a1, a2) min(9, max(1/9, a2$cost/a1$cost))
        Mom:
          pairwise:
            - [Beach, Mountains, 1/3]
        Kid:
          weight:
            - Beach: 1/2
            - Mountains: 0.5
      children: *alternatives
    

Here, Dad says that if alternative 1 has half the cost of alternative 2, it is twice as preferred. Mom wants to keep it simple and says that, cost-wise, whe prefers the mountains over the beach. The kid, finally, has not yet fully grasped the concept of money, so he simply gives a 0.5 weight to each alternative, essentially saying he’s indifferent.

Load and Calculate

To make the full analysis, averaging the decision-makers’ preferences, you use the same functions as for the single decision-maker case:

ahpFile <- system.file("extdata", "vacation.ahp", package="ahp")
vacationAhp <- Load(ahpFile)
Calculate(vacationAhp)

Visualize

Visualize(vacationAhp)
visualize

visualize

Analyze

Total

AnalyzeTable(vacationAhp)
Weight Beach Mountains Inconsistency
Vacation 100.0% 52.4% 47.6% 6.8%
Spa 34.2% 23.1% 11.1% 0.0%
Costs 33.0% 12.1% 20.9% 0.0%
Fun 32.8% 17.2% 15.6% 0.0%

However, you may also drill down into each decision maker.

Dad

AnalyzeTable(vacationAhp, decisionMaker = "Dad")
Weight Mountains Beach Inconsistency
Vacation 100.0% 68.6% 31.4% 3.5%
Costs 71.7% 47.8% 23.9% 0.0%
Fun 21.7% 18.6% 3.1% 0.0%
Spa 6.6% 2.2% 4.4% 0.0%

Mom

AnalyzeTable(vacationAhp, decisionMaker = "Mom")
Weight Beach Mountains Inconsistency
Vacation 100.0% 78.7% 21.3% 6.8%
Spa 74.3% 63.7% 10.6% 0.0%
Fun 19.4% 12.9% 6.5% 0.0%
Costs 6.3% 2.1% 4.2% NA

Kid

AnalyzeTable(vacationAhp, decisionMaker = "Kid")
Weight Beach Mountains Inconsistency
Vacation 100.0% 89.4% 10.6% 0.0%
Fun 81.8% 81.8% 0.0% NA
Costs 9.1% 4.5% 4.5% NA
Spa 9.1% 3.0% 6.1% 0.0%