Analytic Hierarchy Process (AHP) using preferenceFunction in ahp
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Yesterday, I wrote about how to use gluc‘s new ahp package on a simple Tom-Dick-Harry one level decision making problem using Analytic Hierarchy Process (AHP). One of the cool things about that package is that in addition to specifying the pairwise comparisons directly using Saaty’s scale (below, from https://kristalaace2014.wordpress.com/2014/05/14/w12_al_vendor-evaluation/)…
…you can also describe each of the Alternatives in terms of descriptive variables which you can use inside a function to make the pairwise comparisons automatically. This is VERY helpful if you have lots of criteria, subcriteria, or alternatives to evaluate!! For example, I used preferenceFunction to compare 55 alternatives using 6 criteria and 4 subcriteria, and was very easily able to create functions to represent my judgments. This was much easier than manually entering all the comparisons.
This post shows HOW I replaced some of my manual comparisons with automated comparisons using preferenceFunction. (The full YAML file is included at the bottom of this post for you to use if you want to run this example yourself.) First, recall that the YAML file starts with specifying the alternatives that you are trying to choose from (at the bottom level of the decision hierarchy) and some variables that characterize those alternatives. I used the descriptions in the problem statement to come up with some assessments between 1=not great and 10=great:
######################### # Alternatives Section # THIS IS FOR The Tom, Dick, & Harry problem at # https://en.wikipedia.org/wiki/Analytic_hierarchy_process_%E2%80%93_leader_example # Alternatives: &alternatives # 1= not well; 10 = best possible # Your assessment based on the paragraph descriptions may be different. Tom: age: 50 experience: 7 education: 4 leadership: 10 Dick: age: 60 experience: 10 education: 6 leadership: 6 Harry: age: 30 experience: 5 education: 8 leadership: 6 # # End of Alternatives Section #####################################
Here is a snippet from my original YAML file specifying my AHP problem manually ():
children: Experience: preferences: - [Tom, Dick, 1/4] - [Tom, Harry, 4] - [Dick, Harry, 9] children: *alternatives Education: preferences: - [Tom, Dick, 3] - [Tom, Harry, 1/5] - [Dick, Harry, 1/7] children: *alternatives
And here is what I changed that snippet to, so that it would do my pairwise comparisons automatically. The functions are written in standard R (fortunately), and each function has access to a1 and a2 (the two alternatives). Recursion is supported which makes this capability particularly useful. I tried to write a function using two of the characteristics in the decision (a1$age and a1$experience) but this didn’t seen to work. I’m not sure whether the package supports it or not. Here are my comparisons rewritten as functions:
children: Experience: preferenceFunction: > ExperiencePreference <- function(a1, a2) { if (a1$experience < a2$experience) return (1/ExperiencePreference(a2, a1)) ratio <- a1$experience / a2$experience if (ratio < 1.05) return (1) if (ratio < 1.2) return (2) if (ratio < 1.5) return (3) if (ratio < 1.8) return (4) if (ratio < 2.1) return (5) return (6) } children: *alternatives Education: preferenceFunction: > EducPreference <- function(a1, a2) { if (a1$education < a2$education) return (1/EducPreference(a2, a1)) ratio <- a1$education / a2$education if (ratio < 1.05) return (1) if (ratio < 1.15) return (2) if (ratio < 1.25) return (3) if (ratio < 1.35) return (4) if (ratio < 1.55) return (5) return (5) } children: *alternatives
To run the AHP with functions in R, I used this code (I am including the part that gets the ahp package, in case you have not done that yet). BE CAREFUL and make sure, like in FORTRAN, that you line things up so that the words START in the appropriate columns. For example, the “p” in preferenceFunction MUST be immediately below the 7th character of your criterion’s variable name.
devtools::install_github("gluc/ahp", build_vignettes = TRUE) install.packages("data.tree") library(ahp) library(data.tree) setwd("C:/AHP/artifacts") nofxnAhp <- LoadFile("tomdickharry.txt") Calculate(nofxnAhp) fxnAhp <- LoadFile("tomdickharry-fxns.txt") Calculate(fxnAhp) print(nofxnAhp, "weight") print(fxnAhp, "weight")
You can see that the weights are approximately the same, indicating that I did a good job at developing functions that represent the reality of how I used the variables attached to the Alternatives to make my pairwise comparisons. The results show that Dick is now the best choice, although there is some inconsistency in our judgments for Experience that we should examine further. (I have not examined this case to see whether rank reversal could be happening).
> print(nofxnAhp, "weight") levelName weight 1 Choose the Most Suitable Leader 1.00000000 2 ¦--Experience 0.54756924 3 ¦ ¦--Tom 0.21716561 4 ¦ ¦--Dick 0.71706504 5 ¦ °--Harry 0.06576935 6 ¦--Education 0.12655528 7 ¦ ¦--Tom 0.18839410 8 ¦ ¦--Dick 0.08096123 9 ¦ °--Harry 0.73064467 10 ¦--Charisma 0.26994992 11 ¦ ¦--Tom 0.74286662 12 ¦ ¦--Dick 0.19388163 13 ¦ °--Harry 0.06325174 14 °--Age 0.05592555 15 ¦--Tom 0.26543334 16 ¦--Dick 0.67162545 17 °--Harry 0.06294121 > print(fxnAhp, "weight") levelName weight 1 Choose the Most Suitable Leader 1.00000000 2 ¦--Experience 0.54756924 3 ¦ ¦--Tom 0.25828499 4 ¦ ¦--Dick 0.63698557 5 ¦ °--Harry 0.10472943 6 ¦--Education 0.12655528 7 ¦ ¦--Tom 0.08273483 8 ¦ ¦--Dick 0.26059839 9 ¦ °--Harry 0.65666678 10 ¦--Charisma 0.26994992 11 ¦ ¦--Tom 0.74286662 12 ¦ ¦--Dick 0.19388163 13 ¦ °--Harry 0.06325174 14 °--Age 0.05592555 15 ¦--Tom 0.26543334 16 ¦--Dick 0.67162545 17 °--Harry 0.06294121 > ShowTable(fxnAhp)
Here is the full YAML file for the “with preferenceFunction” case.
######################### # Alternatives Section # THIS IS FOR The Tom, Dick, & Harry problem at # https://en.wikipedia.org/wiki/Analytic_hierarchy_process_%E2%80%93_leader_example # Alternatives: &alternatives # 1= not well; 10 = best possible # Your assessment based on the paragraph descriptions may be different. Tom: age: 50 experience: 7 education: 4 leadership: 10 Dick: age: 60 experience: 10 education: 6 leadership: 6 Harry: age: 30 experience: 5 education: 8 leadership: 6 # # End of Alternatives Section ##################################### # Goal Section # Goal: # A Goal HAS preferences (within-level comparison) and HAS Children (items in level) name: Choose the Most Suitable Leader preferences: # preferences are 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 - [Experience, Education, 4] - [Experience, Charisma, 3] - [Experience, Age, 7] - [Education, Charisma, 1/3] - [Education, Age, 3] - [Age, Charisma, 1/5] children: Experience: preferenceFunction: > ExperiencePreference <- function(a1, a2) { if (a1$experience < a2$experience) return (1/ExperiencePreference(a2, a1)) ratio <- a1$experience / a2$experience if (ratio < 1.05) return (1) if (ratio < 1.2) return (2) if (ratio < 1.5) return (3) if (ratio < 1.8) return (4) if (ratio < 2.1) return (5) return (6) } children: *alternatives Education: preferenceFunction: > EducPreference <- function(a1, a2) { if (a1$education < a2$education) return (1/EducPreference(a2, a1)) ratio <- a1$education / a2$education if (ratio < 1.05) return (1) if (ratio < 1.15) return (2) if (ratio < 1.25) return (3) if (ratio < 1.35) return (4) if (ratio < 1.55) return (5) return (5) } children: *alternatives Charisma: preferences: - [Tom, Dick, 5] - [Tom, Harry, 9] - [Dick, Harry, 4] children: *alternatives Age: preferences: - [Tom, Dick, 1/3] - [Tom, Harry, 5] - [Dick, Harry, 9] children: *alternatives # # End of Goal Section #####################################
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.