Source code for casinotools.utilities.multiple_loop

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
.. py:currentmodule:: casinotools.utilities.multiple_loop

.. moduleauthor:: Hendrix Demers <hendrix.demers@mail.mcgill.ca>


"""

###############################################################################
# Copyright 2020 Hendrix Demers
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
###############################################################################

# Standard library modules.

# Third party modules.

# Local modules.

# Project modules.

# Globals and constants variables.


[docs] def _outer(a, b): """ Return the outer product/combination of two lists. a is a multi- or one-dimensional list, b is a one-dimensional list, tuple, NumPy array or scalar (new parameter) Return: outer combination 'all'. The function is to be called repeatedly:: all_combination = _outer(all_combination, p) """ all_combination = [] if not isinstance(a, list): raise TypeError('a must be a list') if isinstance(b, (float, int, complex, str)): b = [b] # scalar? if len(a) == 0: # first call: for j in b: all_combination.append([j]) else: for j in b: for i in a: if not isinstance(i, list): raise TypeError('a must be list of list') # note: i refers to a list; i.append(j) changes # the underlying list (in a), which is not what # we want, we need a copy, extend the copy, and # add to all k = i + [j] # extend previous parameters with new one all_combination.append(k) return all_combination
[docs] def combine(prm_values): """ Compute the combination of all parameter values in the prm_values (nested) list. Main function in this module. param prm_values: nested list ``(parameter_name, list_of_parameter_values)`` or dictionary ``prm_values[parameter_name] = list_of_parameter_values``. return: (all, names, varied) where - all contains all combinations (experiments) all[i] is the list of individual parameter values in experiment no i - names contains a list of all parameter names - varied holds a list of parameter names that are varied (i.e. where there is more than one value of the parameter, the rest of the parameters have fixed values) Code example: >>> from numpy import array >>> dx = array([1.0/2**k for k in range(2, 5)]) >>> dt = 3*dx; dt = dt[:-1] >>> p = {'dx': dx, 'dt': dt} >>> p {'dt': [ 0.75 , 0.375,], 'dx': [ 0.25 , 0.125 , 0.0625,]} >>> all_combination, names, varied = combine(p) >>> all_combination [[0.75, 0.25], [0.375, 0.25], [0.75, 0.125], [0.375, 0.125], [0.75, 0.0625], [0.375, 0.0625]] """ if isinstance(prm_values, dict): # turn dict into list [(name,values),(name,values),...]: prm_values = [(name, prm_values[name]) for name in prm_values] all_combination = [] varied = [] for name, values in prm_values: all_combination = _outer(all_combination, values) if isinstance(values, list) and len(values) > 1: varied.append(name) names = [name for name, values in prm_values] return all_combination, names, varied