Benchmarks Source Code
benchmark_tools
Module containing tools for benchmarking IITCHS MILP problem performance.
The module contains the following classes:
- BenchmarkOptionsGenerator: Class for storing configurations options
for benchmarking.
- named_tuple_iterator: Similar to itertools.product, but returns an
iterator that yields named tuples. Also maintains an internal count of how many items it has left.
- sized_product_iter: Similar to itertools.product, but maintains an
internal count of how many items it has left.
Author: James Usevitch (james.usevitch@ll.mit.edu) Created: Aug 2021
- class BenchmarkOptionsGenerator[source]
Bases:
objectClass used for setting up problem instance generation for IITCHS benchmarking.
All options are in the form of lists, e.g.
[configuration_1, configuration_2]
Each configuration may be an object or another list.
The function [INSERT HERE] produces an iterable that generates tuples of all possible combinations of configurations. These tuples can be passed to benchmarking functions to set up and run the optimization problems in parallel.
For example, given two options
option1, option2,
each having configurations
option1: [[config_1_1], [config_1_2]] option2: [[config_2_1], [config_2_2]],
the iterator returns tuples of the form
([config_1_1], [config_2_1]), ([config_1_1], [config_2_2]), ([config_1_2],[config_2_1]), ([config_1_2], [config_2_2])
Generating the actual problem instances from, e.g., configuration ranges for a particular value is left up to the benchmarking functions running in parallel (? TBD)
Note
If you only want one configuration to be tested for a particular option, simply make the (outer) list have length one, e.g.
option_1 = [configuration]
Conventions:
- Anything appended with “_range_list” is in the form [[min, max],…]. It is meant to present
a list of ranges from which samples can be drawn for a configuration value.
- agent_latin_iterator(random_generator=None, repetitions=1)[source]
Creates a latin iterator for Agent options only.
- create_iterator()[source]
Creates iterator returning namedtuples with all possible combination of solver options.
- create_latin_file_generator(seed=None)[source]
Creates a file generator that directly generates problem .mps / .lp files without actually solving the problem.
- create_latin_iterator(random_generator=None, repetitions=1)[source]
Creates iterator returning latin hypercube samples of the variables in question.
NOTE: This does NOT use the field self.number_of_trials_per_combination.
- custom_latin_iterator(field_names, random_generator=None, repetitions=1)[source]
Creates a latin iterator from a custom list of field names.
Each field name must be a field in the BenchmarkOptionsGenerator class.
- named_tuple_product(**items)[source]
Returns
Based on the following Stack Overflow post: https://stackoverflow.com/a/9098295 CC BY-SA 3.0 https://creativecommons.org/licenses/by-sa/3.0/
- class Latin_MILP_File_Generator(BenchmarkOptionsGenerator, seed=None)[source]
Bases:
objectObject that generates IITCHS MILP .lp / .mps problem files using a BenchmarkOptionsGenerator and Latin Hypercube Sampling.
The MILP problem is NOT solved. The output location of the files can be controlled by setting the .static_options.transition_system_filename variable for the input BenchmarkOptionsGenerator.
- class OutputTuple(Trial_Number, MILP_Solver_Used, Runtime_Seconds, Timed_Out, Robust, Regularize, Alpha, Upper_Bound, Grid_TS_Xdim, Grid_TS_Ydim, Number_of_Agents, Agent_List, Number_of_MILP_Constraints, Number_of_MILP_Variables, Objective_Value, Optimizer_Final_Status, Robustness_Variable_Value, Normalized_Travel_Time, TS_Filename, Solution_Filename, Error_Occurred, Formula, Formula_AST_Bound, Formula_Num_Tasks, Formula_Num_TL_Operators, Formula_Num_Bool_Operators, Max_Generation_Attempts_Hit)
Bases:
tuple- Agent_List
Alias for field number 11
- Alpha
Alias for field number 6
- Error_Occurred
Alias for field number 20
- Formula
Alias for field number 21
- Formula_AST_Bound
Alias for field number 22
- Formula_Num_Bool_Operators
Alias for field number 25
- Formula_Num_TL_Operators
Alias for field number 24
- Formula_Num_Tasks
Alias for field number 23
- Grid_TS_Xdim
Alias for field number 8
- Grid_TS_Ydim
Alias for field number 9
- MILP_Solver_Used
Alias for field number 1
- Max_Generation_Attempts_Hit
Alias for field number 26
- Normalized_Travel_Time
Alias for field number 17
- Number_of_Agents
Alias for field number 10
- Number_of_MILP_Constraints
Alias for field number 12
- Number_of_MILP_Variables
Alias for field number 13
- Objective_Value
Alias for field number 14
- Optimizer_Final_Status
Alias for field number 15
- Regularize
Alias for field number 5
- Robust
Alias for field number 4
- Robustness_Variable_Value
Alias for field number 16
- Runtime_Seconds
Alias for field number 2
- Solution_Filename
Alias for field number 19
- TS_Filename
Alias for field number 18
- Timed_Out
Alias for field number 3
- Trial_Number
Alias for field number 0
- Upper_Bound
Alias for field number 7
- class latin_dict_iterator(random_generator=None, repetitions=1, **kwargs)[source]
Bases:
objectCreates an iterator producing Latin Hypercube samples from the given list of options. Outputs are in the form of dictionaries.
Method for Sampling:
First, all input iterators are turned into lists. The number of input iterators defines the number of “variables” in the sample.
The least common multiple (LCM) of all list lengths defines the dimension of the Latin hypercube samples; i.e. the number of discrete “bins” to be sampled from.
A 2D Numpy array is formed in memory. Each column of the array contains the “raw” coordinates for one Latin hypercube sample routine. (“Raw” means that the coordinates are based on the LCM of all list lengths). When
repetition> 1, multiple Latin hypercube routine results are concatenated horizontally into one matrix, with the number of routines equal torepetition.When next() is called on the iterator, the raw coordinates for a hypercube sample are matched to the corresponding bins in the stored lists. A named tuple is returned containing the entries from these bins.
- latin_hypercube_sample(num_variables, num_bins, random_generator=None)[source]
Generates a discrete latin hypercube sampling.
Given n = num_variables and m = num_bins, this function returns an n x m numpy matrix. The iith column of the matrix contains the coordinates for the iith hypercube sample. All samples are guaranteed to be unique in their respective (multidimensional) rows and columns.
Example: 2 variables, 10 bins. A possible return matrix is
- array([[5, 3, 0, 9, 6, 8, 7, 4, 2, 1],
[2, 5, 3, 4, 1, 7, 6, 8, 9, 0]])
Each column is the 2D index of a sample that is unique in its row and column (i.e. 10 rooks on a chessboard that don’t threaten each other).
Example: 3 variables, 10 bins. A possible return matrix is
- array([[1, 9, 4, 2, 6, 7, 3, 0, 8, 5],
[0, 1, 9, 2, 7, 6, 4, 3, 5, 8], [6, 4, 8, 3, 0, 2, 9, 7, 5, 1]])
Each column is the 3D index of a sample that is unique in its 3D rows /columns (i.e. 10 rooks in a 3D cube chessboard that don’t threaten each other)
TODO: Move this to generation_tools.py?
- class latin_named_tuple_iterator(random_generator=None, repetitions=1, **kwargs)[source]
Bases:
objectSimilar to named_tuple_iterator, but generates latin hypercube samples to reduce the amount of testing required.
Method for Sampling:
First, all input iterators are turned into lists. The number of input iterators defines the number of “variables” in the sample.
The least common multiple (LCM) of all list lengths defines the dimension of the Latin hypercube samples; i.e. the number of discrete “bins” to be sampled from.
A 2D Numpy array is formed in memory. Each column of the array contains the “raw” coordinates for one Latin hypercube sample routine. (“Raw” means that the coordinates are based on the LCM of all list lengths). When
repetition> 1, multiple Latin hypercube routine results are concatenated horizontally into one matrix, with the number of routines equal torepetition.When next() is called on the iterator, the raw coordinates for a hypercube sample are matched to the corresponding bins in the stored lists. A named tuple is returned containing the entries from these bins.
- class named_tuple_iterator(**kwargs)[source]
Bases:
objectSimilar to sized_product_iter, but returns the items as named tuples.
Note: Does not take the “repeat” keyword argument used in itertools.product.
- class sized_product_iter(*args, repeat=1)[source]
Bases:
objectSimilar to itertools.product, but maintains an internal count of the objects it has left.
Works with next() and len().
- solve_one_optimization_problem(options_tuple, static_options, trial_number=None, verbose=False, transition_system=None, formula=None, seed=None)[source]
Runs one optimization problem using the parameters from the named tuple options_tuple argument and the SimpleNamespace object static_options.
The input tuple must be a named tuple obtained from BenchmarkOptionsGenerator.create_iterator().
- Returns
Running time of the optimization algorithm PuLP_Model:
- Return type
runtime (float)
generation_tools
Random generation tools for IITCHS benchmarking purposes.
The generation functions fall roughly in three groups:
Transition System generation
Agent / Capability generation
CaTL Formula generation
Some of the functions are modifications of functions in the file RandomizedCaTLExperiments.py.
Author: James Usevitch (james.usevitch@ll.mit.edu)
- FG_operators_and_tasks_to_strings(operator_strings, intervals, task_strings)[source]
Creates a Python list of formulas from the inputs.
This function only combines the operators
F,G,FG,GFwith tasks. To combine formulas together using AND and OR, use the function [INSERT HERE].Args:
Returns:
- class_to_capability_dict(capabilities, presort=True)[source]
Creates dictionary mapping capability class to the corresponding sets of capabilities.
For example, given the capabilities (UV, IR, Mo), the dictionary might satisfy:
class_to_capability_dict = { 0: set('UV'), 1: set('IR'), 2: set('Mo'), 3: set(['UV','IR']), 4: set(['IR','Mo']), 5: set(['UV','Mo']), 6: set(['UV','IR','Mo']) }
Note
To ensure results are deterministic, by default the list of capabilities is sorted alphabetically in a case insensitive manner (using
str.casefold) before creating the dictionary. To turn off this sorting, use the keyword argumentpresort=False.
- combine_formulas_AND_OR(formulas, operators)[source]
Combines multiple formulas together with AND and OR operators.
Formulas and operators must be listed in order; i.e. entry ii of operators goes between entries ii and ii+1 of formulas.
- Parameters
- Returns
String of the resulting formula.
- Return type
(str)
- generateGridTS_label_counts(tsname, dimensions, labelNames, edgeWeightRange, label_counts, random_generator=None)[source]
Generates a transition system in the form of a grid, with a specified number of occurrences for each label.
Similar to generateRandomGridTS. The main difference is that a
label_countsvector is passed in specifying how many times each label should occur in the transition system. States are allowed to have multiple labels.- Parameters
tsname (str) – Name of the transition system
dimensions (list) – Two-element list with the x, y dimensions of the grid, e.g.
[xdim, ydim]labelNames (list) – String names of each label
edgeWeightRange (list) –
label_counts (list) – List of integers specifying how many times each label should occur in the transition system. Must have the same length as the
labelNameslist.random_generator – Numpy random generator object. If unspecified, a new one is created using
np.random.default_rng().
- Returns
A Lomap transition system
- Return type
()
- generateRandomGridTS(tsname, dimensions, labelNames, edgeWeightRange, max_labels_per_state, random_generator=None)[source]
Generates a transition system in the form of a grid.
All states
Note
This function is loosely based on the function generateRandomGridTS_seed in RandomizedCaTLExperiments.py. The main differences include:
A random_generator is passed into this function instead of a seed number.
The method of assigning labels is different
- generate_agents_by_class(state_list, capability_list, num_agents_per_class, random_generator=None)[source]
Generates an equal amount of agents per agent class.
Initial starting states
- generate_agents_by_total_and_distribution(total_agents, class_to_capability_dict, capability_class_distribution, initial_state_list, random_generator=None)[source]
Generates agents by specifying the total number of agents and a probability distribution over all possible capability classes.
- Parameters
total_agents (int) – The total number of agents to create
class_to_capability_dict –
Dictionary mapping capability class to the corresponding sets of capabilities. For example, given the capabilities (UV, IR, Mo), the dictionary might satisfy ```python class_to_capability_dict = {
0: set(‘UV’), 1: set(‘IR’), 2: set(‘Mo’), 3: set([‘UV’,’IR’]), 4: set([‘IR’,’Mo’]), 5: set([‘UV’,’Mo’]), 6: set([‘UV’,’IR’,’Mo’])
capability_class_distribution (list) – List of probabilities for each capability class
initial_state_list – List of potential starting states for the agents
random_generator – A Numpy random generator. If None, the function creates one using np.random.default_rng().
- Returns
A list of agents.
- Return type
(list)
- generate_multiple_random_CaTL_formula(options_tuple, number_of_formulas=1)[source]
Generates random TL formulas.
- Parameters
number_of_formulas (int) – Number of formula strings to generate.
number_of_atomics_per_formula (int) – Number of atomics to include in each formula string. An “atomic” is one temporal operator (e.g. F, G, FG, GF, U) combined with one task (two tasks for the U operator). Atomics are combined into one formula with the AND / OR boolean operators.
- Returns
List of formula strings.
- Return type
(list)
- generate_random_CaTL_formula_and_info(options_tuple, random_generator=None)[source]
Generates one random TL formula and returns it, along with other information about the formula.
- Parameters
options_tuple (namedtuple) –
random_generator – Numpy random generator, e.g. np.random.default_rng(). If None, then the function will create one using np.random.default_rng(). Passing in a random number generator helps prevent similar results when running multiple benchmark simulations in parallel.
- Returns
- Output tuple including the following elements:
formula (string): The CaTL formula
ast_bound (int): The AST bound of the formula.
- number_of_atomics_per_formula (int): The number of atomics in the formula. Note that by
- the definition of an atomic, this number is identical to:
The number of tasks # TODO: Only true if U isn’t included
The number of TL operators
The number of boolean operators + 1
num_tasks (int): The number of tasks that are in the formula
- num_tl_operators (int): The total number of F, G, FG, GF, or U operators
found in the formula.
- num_bool_operators (int): The total number of AND and OR operators
found in the formula.
- Return type
(tuple)
- generate_random_agents(state_list, capability_list, num_capabilities_per_agent_range, number_of_agents_generated=1, seed=None)[source]
Generates random arrays of agents.
The num_capabilities_per_agent_range is in the form [min,max]. Agents are given a random number of capabilities, where the number of capabilities is in this range. To specify a specific number of capabilities, set min == max.
- probability_over_capability_cardinality(cardinality_distr)[source]
Generates a probability distribution based on how likely it is for agents to have a _number_ of capabilities, e.g. 1 capability vs. 3 capabilities.
A capability cardinality class is a set of capability classes, each class having the same cardinality of capabilities. For example,
The capability classes {UV}, {IR}, {Mo} are all of cardinality class 1 (one capability per class)
The capability classes {UV,IR}, {UV,Mo}, {IR, Mo} are all of cardinality class 2 (two capabilities per class)
The capability class {UV,IR,Mo} is of cardinality class 3 (three capabilities per class)
This function assumes that each cardinality class C_i is given a probability weight w_i (e.g., the probability of an agent having 1, or 2, or 3 capabilities). The probability w_i is then divided uniformly among all possible capability classes within that cardinality class.
More specifically, given n capabilities, the capability cardinality class k has (n choose k) agents. If class k is given probability weight w_k, then each capability class in cardinality class k has probability w_k / (n choose k).
Example
- Suppose our capabilities are {UV, IR, Mo}. Suppose that
cardinality_distr = [0.2, 0.3, 0.5]. Then: Each capability class of cardinality 1 ({UV}, {Mo}, {IR}) would have probability 0.2 / 3
Each capability class of cardinality 2 ({UV,Mo}, {Mo,IR}, {UV,IR}) would have probability 0.3 / 3
Each capability class of cardinality 3 ({UV,Mo,IR}) would have probability 0.5 / 1
- task_capabilities_to_string(capabilities, num_required_agents)[source]
Converts a list of capabilities and a list of number of required agents to string form for CaTL task formulas.
- Parameters
- Returns
A string representation of the capabilities needed for a task, e.g. ‘{(UV,1)}’ or ‘{(IR,2),(Mo,3)}’.
- Return type
(string)