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()
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