Call a local R script in diviz: the example of the weighted sum

Short description of the tutorial

In this tutorial we show how to call a local R script in diviz implementing a weighted sum.

Detailed description of the tutorial

This tutorial focusses on the following aspects:

  • Writing the weighted sum script in R;
  • Adding this program to diviz.

Tutorial

This tutorial requires that you have installed R on your computer (https://www.r-project.org/) and that you have installed the RXMCDA package (XMCDA parsing library for R, available via the CRAN). To install the RXMCDA package, just do it in R via the command:

install.packages("RXMCDA", dependencies=TRUE)

Create a new empty workflow (see this tutorial to learn how to do this) and drag and drop generic_program in the workspace. You should now have a program called generic_program-1 in your workspace with one input (infile1) and one output (outfile1).

If you double-click on generic_program-1, its properties window will open. There you can specify the number of inputs and outputs you need for your program. In this tutorial, we wish to implement a weighted sum program. We will therefore need 4 inputs: two inputs to define the alternatives and the criteria, an input for the performance table, and one for the weights of the criteria. Concerning the outputs, we will only produce one output, which contains the overall values of the input alternatives. We therefore select 4 inputs and 1 output.

To specify the commandline call for this program, enter the following in the cmdline field of the properties window of generic_program-1:

R --slave --vanilla --args infile1 infile2 infile3 infile4 outfile1

The arguments (“infile1”, ..., “outfile1”) define the input and output file names.

Then check the Use a script option and enter the following in the textbox :

# Load the RXMCDA package (which in turn
# will load the required XML package)

library(RXMCDA)

# Get the list of arguments behind the --args option

args <- commandArgs(trailingOnly = TRUE)

# Get the filenames from the arguments

alternativesFile <- args[1]
criteriaFile <- args[2]
performanceTableFile <- args[3]
criteriaWeightsFile <- args[4]
overallValuesFile <- args[5]

# Load the input files
# See the documentation of the XML package for R
# for further details on the xmlParse function

treeAlternatives<-xmlTreeParse(alternativesFile,useInternalNodes=TRUE)
treeCriteria<-xmlTreeParse(criteriaFile,useInternalNodes=TRUE)
treePerformanceTable<-xmlTreeParse(performanceTableFile,useInternalNodes=TRUE)
treeCriteriaWeights<-xmlTreeParse(criteriaWeightsFile,useInternalNodes=TRUE)

# Read the MCDA data from the files
# See the documentation of the RXMCDA package for R for further
# details concerning this step, and for the description
# of the output data

critIDs <- getCriteriaIDs(treeCriteria)[[1]]
altIDs <- getAlternativesIDs(treeAlternatives)[[1]]
perfTable <- getPerformanceTables(treePerformanceTable,altIDs = altIDs, critIDs = critIDs)[[1]]
critWeights <- getCriteriaValues(treeCriteriaWeights, critIDs)[[1]]

# Calculate the weighted sum of the alternatives

overallValues <- c()
for (i in 1:dim(perfTable)[1]){
     overallValues <- rbind(overallValues, c(i,sum(perfTable[i,]*t(critWeights[,2]))))
}

# Write the result file
# We first create an empty XML tree

outTree = newXMLDoc()

# Then we specify the root node

newXMLNode("xmcda:XMCDA",
     attrs=c("xsi:schemaLocation" = "http://www.decision-deck.org/2009/XMCDA-2.1.0 https://www.decision-deck.org/xmcda/_downloads/XMCDA-2.1.0.xsd"),
     suppressNamespaceWarning=TRUE,
     namespace = c("xsi" = "http://www.w3.org/2001/XMLSchema-instance", "xmcda" = "http://www.decision-deck.org/2009/XMCDA-2.1.0"),
     parent=outTree)

# And finally we write the output data in the XML tree
# Again, see the RXMCDA documentation for
# further details on the putAlternativesValues function and its arguments

putAlternativesValues(outTree, overallValues, rownames(perfTable), "overallValues")

saveXML(outTree, file=overallValuesFile)

Instead of pasting everything in the script field of the properties window, you could have created a new file (let’s say “weightedSum.R”) and changed the command line to :

R --slave --vanilla --file=/path/to/weightedSum.R --args infile1 infile2 infile3 infile4 outfile1

Another option is to add the file of the script (let’s say “weightedSum.R”) to your workspace, and connect it to generic_program-1. To do so, you need to check the option ‘Provide the script as a file’, which adds an input called script to the generic_program-1 box. You just have to connect the file representing your script to this entry. The command-line now becomes:

R --slave --vanilla --file=script --args infile1 infile2 infile3 infile4 outfile1

To check that your program works as expected, connect the following 4 input files to the correct input elements of generic_program-1:

Then, execute the workflow and click on outfile1 to display the overall values of the input alternatives.

Remarks

This example shows the basic usage of local R scripts in R. Note that we warmly recommend to do further tests in your scripts in order to increase its robustness. For example, you should encapsulate parts of the script in tryCatch blocks to handle exceptions. Such errors could then be written to a second output file which would help the user to solve the execution problems. Furthermore, you should check the validity of the input files with respect to the XMCDA Schema. You could do that by using the checkXSD function of the R package RXMCDA.

You can download the workflow bundled with the input files described in this tutorial from here. See here for a tutorial on how to import such a workflow into diviz.