Salib V1.4 Dev Release

3 minute read

SALib v1.4 development release

Recently the SALib team made the v1.4 pre-release available for early adopters to try out.

pip install --pre salib==1.4.0.dev2

See the announcement over here.

There are various improvements and enhancements included in this pre-release including a new way of using SALib.

In this blog post I’ll be giving a few examples of how this new approach works and its benefits.

First the set up:

import numpy as np
import time

from SALib.test_functions import Ishigami
from SALib import ProblemSpec


# Problem specification for the Ishigami-Homma test function
sp = ProblemSpec({
    'names': ['x1', 'x2', 'x3'],
    'bounds': [[-np.pi, np.pi]*3],
    'outputs': ['Y']
})

For this example we assign the ProblemSpec object to sp, for “[S]ALib [P]roblem” or “[sp]ecification”. Of course, this variable can be named anything.

Compare the above to the original approach:

problem = {
    'names': ['x1', 'x2', 'x3'],
    'num_vars': 3,
    'bounds': [[-np.pi, np.pi]*3]
}

At first glance, not much has changed.

The number of variables (num_vars) is now inferred from the number of input names. The SALib ProblemSpec accepts outputs to be optionally defined as well, which comes in handy when it is time to display results for multiple model outputs.

That said, there are several benefits to using the new approach.

One is readability:

# New approach
(sp.sample_saltelli(1000)
   .evaluate(Ishigami.evaluate)
   .analyze_sobol(print_to_console=True))

The outer parenthesis () is optional. Without it, it looks like this (a little clunky in my opinion):

sp.sample_saltelli(1000)\
  .evaluate(Ishigami.evaluate)\
  .analyze_sobol(print_to_console=True)

The backslashes (\) tells Python “pretend these are all on the same line”, and so using the outer parenthesis is a stylistic choice.

Unlike the older approach, there is no requirement to import the specific methods (e.g. saltelli). Both the original procedural approach and the new approach are supported.

# Original approach 
from SALib.sample import saltelli
from SALib.analyze import sobol

X = saltelli.sample(problem, 1000)
Y = Ishigami.evaluate(X)
Si = sobol.analyze(problem, Y, print_to_console=True)

# The ProblemSpec is compatible with the procedural approach too
# Note we're passing in `sp`, not `problem`!
X = saltelli.sample(sp, 1000)
Y = Ishigami.evaluate(X)
Si = sobol.analyze(sp, Y, print_to_console=True)

In comparing the two approaches, the newer method no longer requires the user to track, and pass in, problem, X, or Y parameters as these are handled automatically.

Another advantage is that the available sampling and analysis methods are made user discoverable. The full list of available methods can be found via tab-completion in a REPL or Jupyter Notebook.

Generic sample and analyze methods are also available, and can use any function that accepts the SALib ProblemSpec as its first parameter. The analyze method should also accept a Y parameter (and X as well if the method requires it):

from SALib.sample import saltelli
from SALib.analyze import sobol

(sp.sample(saltelli.sample, 1000)
   .evaluate(Ishigami.evaluate)
   .analyze(sobol.analyze, print_to_console=True))

Previously obtained samples and results can be attached like so:

sp.samples = previous_samples
sp.results = pre_existing_model_outputs
sp.analyze_sobol()

The aim of all of this is to simplify the workflow involved in SA.

With that in mind, the evaluate method has a parallel counterpart: evaluate_parallel. Model runs conducted with this method will auto-magically divide the parameter sets to the available (or specified number of) processors.

gif showcasing parallel evaluation of target model

Relevant code snippet:

(sp.sample_saltelli(25000)
   .evaluate_parallel(Ishigami.evaluate, nprocs=4)
   .analyze_sobol())

print(sp)

# Can also plot results
sp.plot()

As noted by the warning shown in the example above, this is an experimental feature for now, and likely only useful for long-running models given the overhead involved in managing distributed runs.

A further benefit, albeit one which regular users won’t experience, is that it will be much easier to develop and maintain future planned improvements.

That’s all for now!

Once again, try it out with

pip install --pre salib==1.4.0.dev2

Report any issues that may occur over here.

Any and all feedback is appreciated.

Updated: