Short scenario generation

%matplotlib widget

import time
from pacti.contracts import PolyhedralIoContract
from pacti_instrumentation.pacti_counters import summarize_instrumentation_data
import numpy as np
from contract_utils import *
from generators import *

from p_tqdm import p_umap
from scipy.stats import qmc

import pickle

This notebook demonstrates generating scenarios by varying the hyper-parameters of specific system functions (dsn, chrg, sbo, tcm_h, and tcm_db) as described below:

# lower bounds for design hyperparameters
l_bounds = [
    2.0,  # power: min dns cons
    2.5,  # power: min chrg gen
    0.3,  # power: min sbo cons
    0.2,  # power: min tcm_h cons
    0.1,  # power: min tcm_dv cons
    5.0,  # science: min dsn speed
    2.0,  # science: min sbo gen
    1.0,  # nav: min dsn noise
    1.0,  # nav: min chrg noise
    0.5,  # nav: min sbo imp
    1.2,  # nav: min tcm_dv noise
    0.3,  # nav: min tcm_dv progress
]
# upper bounds for design hyperparameters
u_bounds = [
    2.2,  # power: max dns cons
    3.5,  # power: max chrg gen
    0.4,  # power: max sbo cons
    0.3,  # power: max tcm_h cons
    0.2,  # power: max tcm_dv cons
    6.0,  # science: max dsn speed
    8.0,  # science: max sbo gen
    1.2,  # nav: max dsn noise
    1.2,  # nav: max chrg noise
    0.8,  # nav: max sbo imp
    1.4,  # nav: max tcm_dv noise
    0.5,  # nav: max tcm_dv progress
]

We use the Latin Hypercube sampler to generate n5 random combinations of hyper-parameters. We exploit as much parallelism as available on the machine to generate 5-step scenarios for each combination, which requires creating 23 contracts combined via 12 contract composition and 5 contract merge operations. The results show that Pacti's operations for constructing contracts scale very well.

mean_sampler = qmc.LatinHypercube(d=len(l_bounds))
dev_sampler = qmc.LatinHypercube(d=len(l_bounds))

n5 = 200
mean_sample5: np.ndarray = mean_sampler.random(n=n5)
scaled_mean_sample5: np.ndarray = qmc.scale(sample=mean_sample5, l_bounds=l_bounds, u_bounds=u_bounds)
dev_sample5: np.ndarray = dev_sampler.random(n=n5)

from pacti_instrumentation.cpu_usage_plot import cpu_usage_plot
with cpu_usage_plot(finally_clear_output=True):
    ta = time.time()
    results: List[Tuple[PactiInstrumentationData, List[tuple2float], PolyhedralIoContract]] = p_umap(generate_5step_scenario, list(zip(scaled_mean_sample5, dev_sample5)))
    tb = time.time()

stats = summarize_instrumentation_data([result[0] for result in results])
scenarios5 = [result[1:3] for result in results if result[1]]

print(
    f"Generated {n5} hyperparameter variations of the 5-step scenario in {tb-ta} seconds.\n"
    f"Running on {cpu_info_message}\n"
    f"{stats.stats()}"
)
s = open("scenarios5.data", "wb")
pickle.dump(scenarios5, s)
s.close()

png

Output()


Generated 200 hyperparameter variations of the 5-step scenario in 16.240273475646973 seconds.
Running on AMD Ryzen Threadripper PRO 3955WX 16-Cores @ 3.8927 GHz with up to 32 threads.
Pacti compose,quotient,merge statistics:
compose invocation counts: (min: 0, max: 12, avg: 10.08, total: 2016)
min/max compose contract size: (constraints: 6, variables: 3)/(constraints: 22, variables: 12)
no quotient operations
merge invocation counts: (min: 0, max: 10, avg: 8.4, total: 1680)
min/max merge contract size: (constraints: 3, variables: 2)/(constraints: 44, variables: 23)
Pacti PolyhedralTermList statistics:
no contains_behavior operations
Pacti PolyhedralCompoundContract statistics:
no compound_merge operations