From 1291adb8de2d1a6df1a4f89298838af3584748f1 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Tue, 17 Jan 2023 13:20:36 -0600 Subject: [PATCH] Refactor `DryRunExecutor` (#45) --- CHANGELOG.md | 23 + graviton/blackbox.py | 747 +- graviton/inspector.py | 21 +- graviton/invariant.py | 6 +- graviton/models.py | 3 +- notebooks/quadratic_factoring_game.ipynb | 16445 +++++++++++---------- setup.py | 2 +- tests/integration/abi_test.py | 21 +- tests/integration/blackbox_test.py | 25 +- tests/integration/doc_examples_test.py | 126 +- tests/integration/identical_test.py | 23 +- tests/integration/lsig_test.py | 25 +- tests/unit/encode_test.py | 189 +- 13 files changed, 8964 insertions(+), 8692 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d2c208b..22c96d75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,31 @@ # Changelog + +## `v0.8.0` (_aka_ 🦛) + +### Breaking changes + +In [#48](https://github.com/algorand/graviton/pull/48), the following classes were pulled out of `graviton/blackbox.py` and into a new file `graviton/inspector.py` +* `TealVal` +* `DryRunResults` (renamed from `BlackboxResults`) +* `DryRunInspector` + +In [#44](https://github.com/algorand/graviton/pull/44): +* `DryRunExecutor` has been refactored. All the class methods `dryrun_*` have been removed in favor of the instance methods `run_one()` and `run_sequence()`. In particular, it is now required to instantiate a `DryRunExecutor` object before calling a dry run executing method. +* `DryRunInspector` no longer accepts `args` as a second parameter and uses `self.args` instead. +* Migration path to the above: it is recommended that calls be re-written to use the new API. If you find that this causes too much friction, please open an issue. +### Added +* Adding `budget_added` and `budget_consumed` to `DryRunInspector.csv_row()` + +### Addressed +* [#45](https://github.com/algorand/graviton/pull/45): addresses [#38](https://github.com/algorand/graviton/issues/38) and [#40](https://github.com/algorand/graviton/issues/40) +* [#48](https://github.com/algorand/graviton/pull/48): addresses [#14](https://github.com/algorand/graviton/issues/14) and [#29](https://github.com/algorand/graviton/issues/29) + ## `v0.7.1` +### Breaking changes + * Upgrade to `py-algorand-sdk` v2 ([#46](https://github.com/algorand/graviton/pull/46)) ## `v0.7.0` (_aka_ 🦒) diff --git a/graviton/blackbox.py b/graviton/blackbox.py index d9b43f4f..374bfc54 100644 --- a/graviton/blackbox.py +++ b/graviton/blackbox.py @@ -1,11 +1,8 @@ -from graviton.abi_strategy import PyTypes, ABIStrategy, RandomABIStrategy -from graviton.dryrun import DryRunHelper -from graviton.inspector import DryRunInspector -from graviton.models import ZERO_ADDRESS, ArgType, DryRunAccountType, ExecutionMode - - +from copy import copy +from dataclasses import asdict, dataclass, field from typing import ( Any, + Callable, Dict, Final, List, @@ -13,6 +10,7 @@ Sequence, Tuple, Type, + TypeVar, Union, cast, ) @@ -27,12 +25,36 @@ SuggestedParams, ) +from graviton.abi_strategy import ABIStrategy, RandomABIStrategy +from graviton.dryrun import DryRunHelper +from graviton.inspector import DryRunInspector, EncodingType +from graviton.models import ( + ArgType, + DryRunAccountType, + ExecutionMode, + PyTypes, + Stringy, + ZERO_ADDRESS, +) TealAndMethodType = Union[Tuple[str], Tuple[str, str]] -EncodingType = Union[abi.ABIType, str, None] + +T = TypeVar("T") + +OneOrMany = Union[T, Sequence[T]] MAX_APP_ARG_LIMIT = atc.AtomicTransactionComposer.MAX_APP_ARG_LIMIT +# `CREATION_APP_CALL` and `EXISTING_APP_CALL` are enum-like constants used to denote whether a dry run +# execution will simulate calling during on-creation vs post-creation. +# In the default case that a dry run is executed without a provided application id (aka `index`), the `index` +# supplied will be: +# * `CREATION_APP_CALL` in the case of `is_app_create == True` +# * `EXISTING_APP_CALL` in the case of `is_app_create == False` +CREATION_APP_CALL: Final[int] = 0 +EXISTING_APP_CALL: Final[int] = 42 + +SUGGESTED_PARAMS = SuggestedParams(int(1000), int(1), int(100), "", flat_fee=True) class DryRunEncoder: @@ -64,7 +86,7 @@ def encode_args( which allows the automatic prepending of `None` to the ABI types list. """ a_len = len(args) - if abi_types: + if abi_types is not None: t_len = len(abi_types) if validation: assert ( @@ -174,406 +196,382 @@ def _partial_encode_assert( return None -class DryRunExecutor: - """Methods to package up and kick off dry run executions - - When executing an A.B.I. compliant dry-run specify `abi_argument_types` as well as an `abi_return_type`: - * `abi_argument_types` are handed off to the `DryRunEncoder` for encoding purposes - * `abi_return_type` is given the `DryRunInspector`'s resulting from execution for ABI-decoding into Python - """ - - # `CREATION_APP_CALL` and `EXISTING_APP_CALL` are enum-like constants used to denote whether a dry run - # execution will simulate calling during on-creation vs post-creation. - # In the default case that a dry run is executed without a provided application id (aka `index`), the `index` - # supplied will be: - # * `CREATION_APP_CALL` in the case of `is_app_create == True` - # * `EXISTING_APP_CALL` in the case of `is_app_create == False` - CREATION_APP_CALL: Final[int] = 0 - EXISTING_APP_CALL: Final[int] = 42 +@dataclass(frozen=True) +class DryRunTransactionParams: + + # generic: + sender: Optional[Stringy] = None + sp: Optional[SuggestedParams] = None + note: Optional[Stringy] = None + lease: Optional[Stringy] = None + rekey_to: Optional[Stringy] = None + # payments + receiver: Optional[Stringy] = None + amt: Optional[int] = None + close_remainder_to: Optional[Stringy] = None + # apps + index: Optional[int] = None + on_complete: Optional[OnComplete] = None + local_schema: Optional[StateSchema] = None + global_schema: Optional[StateSchema] = None + approval_program: Optional[str] = None + clear_program: Optional[str] = None + app_args: Optional[Sequence[ArgType]] = None + accounts: Optional[List[str]] = None + foreign_apps: Optional[List[str]] = None + foreign_assets: Optional[List[str]] = None + extra_pages: Optional[int] = None + dryrun_accounts: List[DryRunAccountType] = field( + default_factory=list + ) # belongs here??? + # future: + box_refs: Optional[List[Tuple[int, str]]] = None - SUGGESTED_PARAMS = SuggestedParams(int(1000), int(1), int(100), "", flat_fee=True) + @classmethod + def for_logicsig( + cls, + sender: Optional[Stringy] = None, + sp: Optional[SuggestedParams] = None, + note: Optional[Stringy] = None, + lease: Optional[Stringy] = None, + rekey_to: Optional[Stringy] = None, + receiver: Optional[Stringy] = None, + amt: Optional[int] = None, + close_remainder_to: Optional[Stringy] = None, + ) -> "DryRunTransactionParams": + return cls( + sender=sender or ZERO_ADDRESS, + sp=sp or SUGGESTED_PARAMS, + note=note, + lease=lease, + rekey_to=rekey_to, + receiver=receiver or ZERO_ADDRESS, + amt=0 if amt is None else amt, + close_remainder_to=close_remainder_to, + ) @classmethod - def dryrun_app( + def for_app( cls, - algod: AlgodClient, - teal: str, - args: Sequence[PyTypes], is_app_create: bool = False, - on_complete: OnComplete = OnComplete.NoOpOC, - *, - abi_method_signature: Optional[str] = None, - omit_method_selector: Optional[bool] = False, - validation: bool = True, - sender: Optional[str] = None, + sender: Optional[Stringy] = None, sp: Optional[SuggestedParams] = None, + note: Optional[Stringy] = None, + lease: Optional[Stringy] = None, + rekey_to: Optional[Stringy] = None, index: Optional[int] = None, + on_complete: Optional[OnComplete] = None, local_schema: Optional[StateSchema] = None, global_schema: Optional[StateSchema] = None, approval_program: Optional[str] = None, clear_program: Optional[str] = None, - app_args: Optional[Sequence[Union[str, int]]] = None, + app_args: Optional[Sequence[ArgType]] = None, accounts: Optional[List[str]] = None, foreign_apps: Optional[List[str]] = None, foreign_assets: Optional[List[str]] = None, - note: Optional[str] = None, - lease: Optional[str] = None, - rekey_to: Optional[str] = None, extra_pages: Optional[int] = None, dryrun_accounts: List[DryRunAccountType] = [], - ) -> "DryRunInspector": - """ - Execute a dry run to simulate an app call using provided: + ): + return cls( + sender=sender or ZERO_ADDRESS, + sp=sp or SUGGESTED_PARAMS, + note=note, + lease=lease, + rekey_to=rekey_to, + index=(CREATION_APP_CALL if is_app_create else EXISTING_APP_CALL) + if index is None + else index, + on_complete=on_complete, + local_schema=local_schema, + global_schema=global_schema, + approval_program=approval_program, + clear_program=clear_program, + app_args=app_args, + accounts=accounts, + foreign_apps=foreign_apps, + foreign_assets=foreign_assets, + extra_pages=extra_pages, + dryrun_accounts=dryrun_accounts, + ) - * algod - * teal program for the approval (or clear in the case `on_complete=OnComplete.ClearStateOC`) - * args - the application arguments as Python types - * abi_argument_types - ABI types of the arguments, in the case of an ABI method call - * abi_return_type - the ABI type returned, in the case of an ABI method call - * is_app_create to indicate whether or not to simulate an app create call - * on_complete - the OnComplete that should be provided in the app call transaction + def asdict(self, drop_nones: bool = True) -> Dict[str, Any]: + d = asdict(self) + del d["dryrun_accounts"] + del d["box_refs"] + if not drop_nones: + return d - Additional application call transaction parameters can be provided as well - """ - return cls.execute_one_dryrun( - algod, - teal, - args, - ExecutionMode.Application, - abi_method_signature=abi_method_signature, - omit_method_selector=omit_method_selector, - validation=validation, - txn_params=cls.transaction_params( - sender=ZERO_ADDRESS if sender is None else sender, - sp=cls.SUGGESTED_PARAMS if sp is None else sp, - note=note, - lease=lease, - rekey_to=rekey_to, - index=( - (cls.CREATION_APP_CALL if is_app_create else cls.EXISTING_APP_CALL) - if index is None - else index - ), - on_complete=on_complete, - local_schema=local_schema, - global_schema=global_schema, - approval_program=approval_program, - clear_program=clear_program, - app_args=app_args, - accounts=accounts, - foreign_apps=foreign_apps, - foreign_assets=foreign_assets, - extra_pages=extra_pages, - ), - accounts=dryrun_accounts, - ) + return {k: v for k, v in d.items() if v is not None} - @classmethod - def dryrun_logicsig( - cls, - algod: AlgodClient, - teal: str, - args: Sequence[PyTypes], - *, - abi_method_signature: Optional[str] = None, - omit_method_selector: Optional[bool] = False, - validation: bool = True, - sender: str = ZERO_ADDRESS, - sp: Optional[SuggestedParams] = None, - receiver: Optional[str] = None, - amt: Optional[int] = None, - close_remainder_to: Optional[str] = None, - note: Optional[str] = None, - lease: Optional[str] = None, - rekey_to: Optional[str] = None, - ) -> "DryRunInspector": - return cls.execute_one_dryrun( - algod, - teal, - args, - ExecutionMode.Signature, - abi_method_signature=abi_method_signature, - omit_method_selector=omit_method_selector, - validation=validation, - txn_params=cls.transaction_params( - sender=ZERO_ADDRESS if sender is None else sender, - sp=cls.SUGGESTED_PARAMS if sp is None else sp, - note=note, - lease=lease, - rekey_to=rekey_to, - receiver=ZERO_ADDRESS if receiver is None else receiver, - amt=0 if amt is None else amt, - close_remainder_to=close_remainder_to, - ), - ) - @classmethod - def dryrun_app_pair_on_sequence( - cls, - algod: AlgodClient, - teal_and_method1: TealAndMethodType, - teal_and_method2: TealAndMethodType, - inputs: List[Sequence[PyTypes]], - *, - is_app_create: bool = False, - on_complete: OnComplete = OnComplete.NoOpOC, - dryrun_accounts: List[DryRunAccountType] = [], - omit_method_selector: Optional[bool] = False, - validation: bool = True, - ) -> Tuple[Sequence["DryRunInspector"], Sequence["DryRunInspector"]]: - return tuple( # type: ignore - cls.dryrun_multiapps_on_sequence( - algod=algod, - multi_teal_method_pairs=[teal_and_method1, teal_and_method2], - inputs=inputs, - is_app_create=is_app_create, - on_complete=on_complete, - dryrun_accounts=dryrun_accounts, - omit_method_selector=omit_method_selector, - validation=validation, - ) - ) +class DryRunExecutor: - @classmethod - def dryrun_multiapps_on_sequence( - cls, - algod: AlgodClient, - multi_teal_method_pairs: List[TealAndMethodType], - inputs: List[Sequence[PyTypes]], - *, - is_app_create: bool = False, - on_complete: OnComplete = OnComplete.NoOpOC, - dryrun_accounts: List[DryRunAccountType] = [], - omit_method_selector: Optional[bool] = False, - validation: bool = True, - ) -> List[Sequence["DryRunInspector"]]: - def runner(teal_method_pair): - teal = teal_method_pair[0] - abi_method = None - if len(teal_method_pair) > 1: - abi_method = teal_method_pair[1] - - return cls.dryrun_app_on_sequence( - algod=algod, - teal=teal, - inputs=inputs, - abi_method_signature=abi_method, - omit_method_selector=omit_method_selector, - validation=validation, - is_app_create=is_app_create, - on_complete=on_complete, - dryrun_accounts=dryrun_accounts, - ) + """Methods to package up and kick off dry run executions""" - return list(map(runner, multi_teal_method_pairs)) + # for usage convenience, copy constants over into the class + CREATION_APP_CALL = CREATION_APP_CALL + EXISTING_APP_CALL = EXISTING_APP_CALL - @classmethod - def dryrun_app_on_sequence( - cls, - algod: AlgodClient, - teal: str, - inputs: List[Sequence[PyTypes]], - *, - abi_method_signature: Optional[str] = None, - omit_method_selector: Optional[bool] = False, - validation: bool = True, - is_app_create: bool = False, - on_complete: OnComplete = OnComplete.NoOpOC, - dryrun_accounts: List[DryRunAccountType] = [], - ) -> List["DryRunInspector"]: - # TODO: handle txn_params - return list( - map( - lambda args: cls.dryrun_app( - algod=algod, - teal=teal, - args=args, - abi_method_signature=abi_method_signature, - omit_method_selector=omit_method_selector, - validation=validation, - is_app_create=is_app_create, - on_complete=on_complete, - dryrun_accounts=dryrun_accounts, - ), - inputs, - ) - ) + SUGGESTED_PARAMS = SUGGESTED_PARAMS - @classmethod - def dryrun_logicsig_on_sequence( - cls, + def __init__( + self, algod: AlgodClient, + mode: ExecutionMode, teal: str, - inputs: List[Sequence[PyTypes]], *, abi_method_signature: Optional[str] = None, - omit_method_selector: Optional[bool] = False, + omit_method_selector: bool = False, validation: bool = True, - ) -> List["DryRunInspector"]: - # TODO: handle txn_params - return list( - map( - lambda args: cls.dryrun_logicsig( - algod=algod, - teal=teal, - args=args, - abi_method_signature=abi_method_signature, - omit_method_selector=omit_method_selector, - validation=validation, - ), - inputs, - ) - ) + ): + self.algod: AlgodClient = algod + self.mode: ExecutionMode = mode + self.program: str = teal + self.abi_method_signature: Optional[str] = abi_method_signature + self.omit_method_selector: bool = omit_method_selector + self.validation: bool = validation + + self.is_app: bool + self.abi_argument_types: Optional[List[EncodingType]] + self.abi_return_type: Optional[EncodingType] + self.method: Optional[abi.Method] + self.selector: Optional[bytes] + + ( + self.is_app, + self.abi_argument_types, + self.abi_return_type, + self.method, + self.selector, + ) = self._init_impl(self.mode, self.abi_method_signature) @classmethod - def execute_one_dryrun( - cls, - algod: AlgodClient, - teal: str, - args: Sequence[PyTypes], - mode: ExecutionMode, - *, - abi_method_signature: Optional[str] = None, - omit_method_selector: Optional[bool] = False, - validation: bool = True, - txn_params: dict = {}, - accounts: List[DryRunAccountType] = [], - verbose: bool = False, - ) -> "DryRunInspector": + def _init_impl( + cls, mode: ExecutionMode, abi_method_signature: Optional[str] + ) -> Tuple[ + bool, + Optional[List[EncodingType]], + Optional[Union[abi.ABIType, str]], + Optional[abi.Method], + Optional[bytes], + ]: assert ( len(ExecutionMode) == 2 ), f"assuming only 2 ExecutionMode's but have {len(ExecutionMode)}" assert mode in ExecutionMode, f"unknown mode {mode} of type {type(mode)}" is_app = mode == ExecutionMode.Application + method: Optional[abi.Method] = None + selector: Optional[bytes] = None abi_argument_types: Optional[List[EncodingType]] = None - abi_return_type: Optional[abi.ABIType] = None + abi_return_type: Optional[Union[abi.ABIType, str]] = None + if abi_method_signature: - """ - Try to do the right thing. - When `omit_method_selector is False`: - * if provided with the same number of args as expected arg types - --> prepend `None` to the types and `selector` to args - * if provided with |arg types| + 1 args - --> assert that `args[0] == selector` - * otherwise - --> there is a cardinality mismatch, so fail - When `omit_method_selector is True`: - * if provided with the same number of args as expected arg types - --> good to go - * if provided with |arg types| + 1 args - --> assert that `args[0] == selector` but DROP it from the args - * otherwise - --> there is a cardinality mismatch, so fail - """ method = abi.Method.from_signature(abi_method_signature) selector = method.get_selector() abi_argument_types = [a.type for a in method.args] - if validation: - args = list(args) - if len(args) == len(abi_argument_types): - if not omit_method_selector: - # the method selector is not abi-encoded, hence its abi-type is set to None - abi_argument_types = [None] + abi_argument_types # type: ignore - args = [selector] + args - - elif len(args) == len(abi_argument_types) + 1: - assert ( - args[0] == selector - ), f"{args[0]=} should have been the {selector=}" - - if omit_method_selector: - args = args[1:] - else: - abi_argument_types = [None] + abi_argument_types # type: ignore - - else: - raise AssertionError( - f"{len(args)=} is incompatible with {len(method.args)=}: LEFT should be equal or exactly RIGHT + 1" - ) - elif not omit_method_selector: - abi_argument_types = [None] + abi_argument_types # type: ignore - - args = tuple(args) - if method.returns.type != abi.Returns.VOID: - abi_return_type = cast(abi.ABIType, method.returns.type) + abi_return_type = method.returns.type - encoded_args = DryRunEncoder.encode_args( - args, abi_types=abi_argument_types, validation=validation + return is_app, abi_argument_types, abi_return_type, method, selector + + def run_one( + self, + args: Sequence[PyTypes], + *, + txn_params: Optional[DryRunTransactionParams] = None, + verbose: bool = False, + ) -> DryRunInspector: + """Convenience method for easier typing - executes a single dry run""" + return cast( + DryRunInspector, + self._run(tuple(args), txn_params=txn_params, verbose=verbose), ) - dryrun_req: DryrunRequest - if is_app: - dryrun_req = DryRunHelper.singleton_app_request( - teal, encoded_args, txn_params, accounts - ) - else: - dryrun_req = DryRunHelper.singleton_logicsig_request( - teal, encoded_args, txn_params - ) - if verbose: - print(f"{cls}::execute_one_dryrun(): {dryrun_req=}") - dryrun_resp = algod.dryrun(dryrun_req) - if verbose: - print(f"{cls}::execute_one_dryrun(): {dryrun_resp=}") - return DryRunInspector.from_single_response( - dryrun_resp, args, encoded_args, abi_type=cast(abi.ABIType, abi_return_type) + def run_sequence( + self, + inputs: Sequence[Sequence[PyTypes]], + *, + txn_params: Optional[DryRunTransactionParams] = None, + verbose: bool = False, + ) -> Sequence[DryRunInspector]: + """Convenience method for easier typing - executes dry run sequence""" + return cast( + Sequence[DryRunInspector], + self._run( + [tuple(args) for args in inputs], txn_params=txn_params, verbose=verbose + ), ) @classmethod - def transaction_params( + def multi_exec( cls, + execs: List["DryRunExecutor"], + inputs: Sequence[Sequence[PyTypes]], *, - # generic: - sender: Optional[str] = None, - sp: Optional[SuggestedParams] = None, - note: Optional[str] = None, - lease: Optional[str] = None, - rekey_to: Optional[str] = None, - # payments: - receiver: Optional[str] = None, - amt: Optional[int] = None, - close_remainder_to: Optional[str] = None, - # apps: - index: Optional[int] = None, - on_complete: Optional[OnComplete] = None, - local_schema: Optional[StateSchema] = None, - global_schema: Optional[StateSchema] = None, - approval_program: Optional[str] = None, - clear_program: Optional[str] = None, - app_args: Optional[Sequence[Union[str, int]]] = None, - accounts: Optional[List[str]] = None, - foreign_apps: Optional[List[str]] = None, - foreign_assets: Optional[List[str]] = None, - extra_pages: Optional[int] = None, - ) -> Dict[str, Any]: + txn_params: Optional[DryRunTransactionParams] = None, + verbose: bool = False, + ) -> Sequence[Sequence[DryRunInspector]]: + return [ + cast( + Sequence[DryRunInspector], + e._run(inputs, txn_params=txn_params, verbose=verbose), + ) + for e in execs + ] + + def _run( + self, + inputs: OneOrMany[Sequence[PyTypes]], + *, + txn_params: Optional[DryRunTransactionParams] = None, + verbose: bool = False, + ) -> OneOrMany[DryRunInspector]: """ - Returns a `dict` with keys the same as method params, after removing all `None` values + Be careful when using this private method. Its behavior depends on the following type-switch: + * when `inputs` is a tuple ---> interpret this to be a single `args` tuple and run a single dry run + * otherwise ---> we require `inputs` to either be a `list` or a `map`, and take a dry-run for every element in the sequence """ - params = dict( - sender=sender, - sp=sp, - note=note, - lease=lease, - rekey_to=rekey_to, - receiver=receiver, - amt=amt, - close_remainder_to=close_remainder_to, - index=index, - on_complete=on_complete, - local_schema=local_schema, - global_schema=global_schema, - approval_program=approval_program, - clear_program=clear_program, - app_args=app_args, - accounts=accounts, - foreign_apps=foreign_apps, - foreign_assets=foreign_assets, - extra_pages=extra_pages, + executor = self._executor(txn_params, verbose) + if isinstance(inputs, tuple): + return executor(inputs) + + assert isinstance( + inputs, (list, map) + ), f"inputs must be of type list or map (for multiple args) or tuple (for single args) but was {type(inputs)}" + if isinstance(inputs, map): + inputs = list(inputs) + + assert inputs, "must provide at least one input args tuple" + + for i, args in enumerate(inputs): + assert isinstance( + args, tuple + ), f"each args in inputs list must be a tuple but at index {i=} we have {type(args)}" + + inputs = cast(List[Tuple[PyTypes, ...]], inputs) + return list(map(executor, inputs)) + + def _executor( + self, + txn_params: Optional[DryRunTransactionParams], + verbose: bool, + ) -> Callable[[Tuple[PyTypes, ...]], DryRunInspector]: + def executor(args: Tuple[PyTypes, ...]) -> DryRunInspector: + args, encoded_args = self._executor_prep(args) + + dryrun_req: DryrunRequest + txn_params_d = txn_params.asdict() if txn_params else {} + dr_acts = txn_params.dryrun_accounts if txn_params else [] + if self.is_app: + dryrun_req = DryRunHelper.singleton_app_request( + self.program, + encoded_args, + txn_params_d, + dr_acts, + ) + else: + dryrun_req = DryRunHelper.singleton_logicsig_request( + self.program, encoded_args, txn_params_d + ) + if verbose: + print(f"{type(self)}._run(): {dryrun_req=}") + dryrun_resp = self.algod.dryrun(dryrun_req) + if verbose: + print(f"{type(self)}::_executor(): {dryrun_resp=}") + return DryRunInspector.from_single_response( + dryrun_resp, args, encoded_args, abi_type=self.abi_return_type + ) + + return executor + + def _executor_prep( + self, args: Tuple[PyTypes, ...] + ) -> Tuple[Tuple[PyTypes, ...], List[ArgType]]: + abi_argument_types = self.abi_argument_types + if self.abi_method_signature: + args, abi_argument_types = self._abi_adapter(args) + + encoded_args = DryRunEncoder.encode_args( + args, abi_types=abi_argument_types, validation=self.validation ) - return {k: v for k, v in params.items() if v is not None} + return args, encoded_args + + def _abi_adapter( + self, args: Sequence[PyTypes] + ) -> Tuple[Tuple[PyTypes, ...], Optional[List[EncodingType]]]: + """ + Validate and possibly return modified versions of: + * args + * abi_argument_types + """ + args_out = list(args) + aats_out = copy(self.abi_argument_types) + nope: EncodingType = None + if self.validation: + assert aats_out is not None, "unexpected None" + assert self.method is not None, "unexpected None" + assert self.selector is not None, "unexpected None" + aats_out = cast(List[EncodingType], aats_out) + method = cast(abi.Method, self.method) + selector = cast(PyTypes, self.selector) + if len(args_out) == len(aats_out): + if not self.omit_method_selector: + # the method selector is not abi-encoded, hence its abi-type is set to None + aats_out = [None] + aats_out + args_out = [selector] + args_out + + elif len(args_out) == len(aats_out) + 1: + assert ( + args_out[0] == selector + ), f"{args_out[0]=} should have been the {selector=}" + + if self.omit_method_selector: + args_out = args_out[1:] + else: + aats_out = [nope] + aats_out + + else: + raise AssertionError( + f"{len(args_out)=} is incompatible with {len(method.args)=}: LEFT should be equal or exactly RIGHT + 1" + ) + elif not self.omit_method_selector: + assert aats_out is not None + aats_out = [nope] + cast(List[EncodingType], aats_out) + # else: not validating + omitting method selector ==> aats_out == abi_argument_types + + return tuple(args_out), aats_out + + @classmethod + def _prerun_validation( + cls, mode: ExecutionMode, abi_method_signature: Optional[str] + ) -> Tuple[ + bool, + Optional[List[EncodingType]], + Optional[Union[abi.ABIType, str]], + Optional[abi.Method], + Optional[bytes], + ]: + assert ( + len(ExecutionMode) == 2 + ), f"assuming only 2 ExecutionMode's but have {len(ExecutionMode)}" + assert mode in ExecutionMode, f"unknown mode {mode} of type {type(mode)}" + is_app = mode == ExecutionMode.Application + + method: Optional[abi.Method] = None + selector: Optional[bytes] = None + abi_argument_types: Optional[List[EncodingType]] = None + abi_return_type: Optional[Union[abi.ABIType, str]] = None + + if abi_method_signature: + method = abi.Method.from_signature(abi_method_signature) + selector = method.get_selector() + abi_argument_types = [a.type for a in method.args] + if method.returns.type != abi.Returns.VOID: + abi_return_type = method.returns.type + + return is_app, abi_argument_types, abi_return_type, method, selector class ABIContractExecutor: @@ -597,7 +595,7 @@ def __init__( dry_runs (default=1) - the number of dry runs to run (generates different inputs each time) - handle_selector - usually we'll want to let `DryRunExecutor.execute_one_dryrun()` + handle_selector - usually we'll want to let `DryRunExecutor.run_*()` handle adding the method selector so this param should _probably_ be left False. But when set True, when providing `inputs` ensure that the 0'th argument for method calls is the selector. @@ -617,17 +615,14 @@ def method_signature(self, method: Optional[str]) -> Optional[str]: return self.contract.get_method_by_name(method).get_signature() - def argument_types(self, method: Optional[str] = None) -> List[abi.ABIType]: + def argument_types(self, method: Optional[str] = None) -> List[EncodingType]: """ Argument types (excluding selector) """ if not method: return [] - return [ - cast(abi.ABIType, arg.type) - for arg in self.contract.get_method_by_name(method).args - ] + return [arg.type for arg in self.contract.get_method_by_name(method).args] def generate_inputs(self, method: Optional[str]) -> List[Sequence[PyTypes]]: """ @@ -657,8 +652,6 @@ def gen_args(): return [gen_args() for _ in range(self.dry_runs)] def validate_inputs(self, method: Optional[str], inputs: List[Sequence[PyTypes]]): - """TODO: add type validation for arguments""" - if not method: assert not any( inputs @@ -695,14 +688,13 @@ def dry_run_on_sequence( *, validation: bool = True, dryrun_accounts: List[DryRunAccountType] = [], - ) -> List["DryRunInspector"]: + ) -> List[DryRunInspector]: """ARC-4 Compliant Dry Run When inputs aren't provided, you should INSTEAD SHOULD HAVE PROVIDED an `argument_strategy` upon construction. When inputs ARE provided, don't include the method selector as that is automatically generated. """ - # TODO: handle txn_params if inputs is None: inputs = self.generate_inputs(method) @@ -710,14 +702,23 @@ def dry_run_on_sequence( if validation: self.validate_inputs(method, inputs) - return DryRunExecutor.dryrun_app_on_sequence( - algod, - self.program, - inputs, - abi_method_signature=self.method_signature(method), - omit_method_selector=False, - validation=validation, - is_app_create=is_app_create, - on_complete=on_complete, - dryrun_accounts=dryrun_accounts, + return list( + cast( + Sequence[DryRunInspector], + DryRunExecutor( + algod, + ExecutionMode.Application, + self.program, + abi_method_signature=self.method_signature(method), + omit_method_selector=False, + validation=validation, + )._run( + inputs, + txn_params=DryRunTransactionParams.for_app( + is_app_create=is_app_create, + on_complete=on_complete, + dryrun_accounts=dryrun_accounts, + ), + ), + ) ) diff --git a/graviton/inspector.py b/graviton/inspector.py index a2fbf1c7..09d92a3e 100644 --- a/graviton/inspector.py +++ b/graviton/inspector.py @@ -43,6 +43,7 @@ class DryRunProperty(Enum): DRProp = DryRunProperty +EncodingType = Union[abi.ABIType, str, None] def mode_has_property(mode: ExecutionMode, assertion_type: "DryRunProperty") -> bool: @@ -311,7 +312,7 @@ def __init__( txn_index: int, args: Sequence[PyTypes], encoded_args: List[ArgType], - abi_type: Optional[abi.ABIType] = None, + abi_type: EncodingType = None, ): txns = dryrun_resp.get("txns", []) assert txns, "Dry Run response is missing transactions" @@ -384,7 +385,7 @@ def from_single_response( dryrun_resp: dict, args: Sequence[PyTypes], encoded_args: List[ArgType], - abi_type: Optional[abi.ABIType] = None, + abi_type: EncodingType = None, ) -> "DryRunInspector": error = dryrun_resp.get("error") assert not error, f"dryrun response included the following error: [{error}]" @@ -428,7 +429,7 @@ def dig(self, dr_property: DryRunProperty, **kwargs: Dict[str, Any]) -> Any: if self.has_abi_prefix: # skip the first 8 hex char's == first 4 bytes: last_log = last_log[8:] - return self.abi_type.decode(bytes.fromhex(last_log)) + return cast(abi.ABIType, self.abi_type).decode(bytes.fromhex(last_log)) except Exception as e: if self.show_internal_errors_on_log: return str(e) @@ -710,31 +711,31 @@ def report( Local Delta: {self.local_deltas()} =============== - TXN AS ROW: {self.csv_row(row, args)} + TXN AS ROW: {self.csv_row(row)} =============== <<<<<<<<<<<{msg}>>>>>>>>>>> =============== """ - def csv_row( - self, row_num: int, args: Sequence[PyTypes] - ) -> Dict[str, Optional[PyTypes]]: + def csv_row(self, row_num: int) -> Dict[str, Optional[PyTypes]]: return { " Run": row_num, + " budget_added": self.budget_added(), + " budget_consumed": self.budget_consumed(), " cost": self.cost(), # back-tick needed to keep Excel/Google sheets from stumbling over hex " last_log": f"`{self.last_log()}", " final_message": self.last_message(), " Status": self.status(), **self.black_box_results.final_as_row(), - **{f"Arg_{i:02}": arg for i, arg in enumerate(args)}, + **{f"Arg_{i:02}": arg for i, arg in enumerate(self.args)}, } @classmethod def csv_report( cls, inputs: List[Sequence[PyTypes]], - dr_resps: List["DryRunInspector"], + dr_resps: Sequence["DryRunInspector"], txns: Optional[List[Dict[str, Any]]] = None, ) -> str: """Produce a Comma Separated Values report string capturing important statistics @@ -775,7 +776,7 @@ def csv_report( txns ), f"cannot produce CSV with unmatching size of inputs ({len(inputs)}) v. txns ({len(txns)})" - _drrs = [resp.csv_row(i + 1, inputs[i]) for i, resp in enumerate(dr_resps)] + _drrs = [resp.csv_row(i + 1) for i, resp in enumerate(dr_resps)] def row(i): return {**_drrs[i], **(txns[i] if txns else {})} diff --git a/graviton/invariant.py b/graviton/invariant.py index b044fb0e..b52a0430 100644 --- a/graviton/invariant.py +++ b/graviton/invariant.py @@ -2,9 +2,8 @@ from inspect import getsource, signature from typing import cast, Any, Callable, Dict, Optional, Sequence, Tuple, Union -from graviton.blackbox import ExecutionMode from graviton.inspector import DryRunInspector, DryRunProperty, mode_has_property -from graviton.models import PyTypes +from graviton.models import ExecutionMode, PyTypes class PredicateKind(Enum): @@ -95,9 +94,10 @@ def __call__( **kwargs, ) -> Tuple[bool, str]: has_external_expected: bool = False + external_expected: Optional[PyTypes] = None if kwargs and (ee_key := "external_expected") in kwargs: has_external_expected = True - external_expected: Optional[PyTypes] = kwargs[ee_key] + external_expected = kwargs[ee_key] invariant = ( self.predicate(args, actual, external_expected) if has_external_expected diff --git a/graviton/models.py b/graviton/models.py index eea80cb9..c4b8d2b1 100644 --- a/graviton/models.py +++ b/graviton/models.py @@ -11,7 +11,8 @@ ArgType = Union[bytes, str] DryRunAccountType = Union[str, Account] -PyTypes = Union[bool, int, Sequence, str, bytes] +Stringy = Union[str, bytes] +PyTypes = Union[bool, int, Sequence, Stringy] class ExecutionMode(Enum): diff --git a/notebooks/quadratic_factoring_game.ipynb b/notebooks/quadratic_factoring_game.ipynb index c3b67af9..ad79b07b 100644 --- a/notebooks/quadratic_factoring_game.ipynb +++ b/notebooks/quadratic_factoring_game.ipynb @@ -1,8251 +1,8276 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Factorizer Game for Quadratic $x^2 - 12x + 35$" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### All the imports (and an `algod` as well)" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "from io import StringIO\n", - "from itertools import product\n", - "import pandas as pd\n", - "import plotly.graph_objects as go\n", - "\n", - "from graviton.blackbox import DryRunExecutor\n", - "from tests.clients import get_algod\n", - "algod = get_algod()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Logic Signature for Quadratic" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "TEAL = \"\"\"#pragma version 5\n", - "intcblock 1 12 35\n", - "pushbytes 0x43616e20796f7520666163746f722031202a20785e32202d203132202a2078202b203335203f // \"Can you factor 1 * x^2 - 12 * x + 35 ?\"\n", - "pop\n", - "intc_0 // 1\n", - "intc_1 // 12\n", - "intc_2 // 35\n", - "arg 0\n", - "btoi\n", - "callsub sub0\n", - "store 0\n", - "intc_0 // 1\n", - "intc_1 // 12\n", - "intc_2 // 35\n", - "arg 1\n", - "btoi\n", - "callsub sub0\n", - "store 1\n", - "load 0\n", - "load 1\n", - "+\n", - "store 2\n", - "load 2\n", - "callsub sub1\n", - "store 3\n", - "txn TypeEnum\n", - "intc_0 // pay\n", - "==\n", - "txn CloseRemainderTo\n", - "global ZeroAddress\n", - "==\n", - "&&\n", - "arg 0\n", - "btoi\n", - "arg 1\n", - "btoi\n", - "!=\n", - "&&\n", - "load 3\n", - "&&\n", - "txn Amount\n", - "load 3\n", - "==\n", - "&&\n", - "return\n", - "sub0: // root_closeness\n", - "store 7\n", - "store 6\n", - "store 5\n", - "store 4\n", - "load 4\n", - "load 7\n", - "*\n", - "load 7\n", - "*\n", - "load 6\n", - "+\n", - "store 8\n", - "load 5\n", - "load 7\n", - "*\n", - "store 9\n", - "load 8\n", - "load 9\n", - "<\n", - "bnz sub0_l2\n", - "load 8\n", - "load 9\n", - "-\n", - "b sub0_l3\n", - "sub0_l2:\n", - "load 9\n", - "load 8\n", - "-\n", - "sub0_l3:\n", - "retsub\n", - "sub1: // calculate_prize\n", - "store 10\n", - "load 10\n", - "intc_0 // 1\n", - "+\n", - "pushint 20 // 20\n", - "<\n", - "bnz sub1_l2\n", - "pushint 0 // 0\n", - "b sub1_l3\n", - "sub1_l2:\n", - "pushint 1000000 // 1000000\n", - "pushint 10 // 10\n", - "load 10\n", - "intc_0 // 1\n", - "+\n", - "pushint 2 // 2\n", - "/\n", - "-\n", - "*\n", - "sub1_l3:\n", - "retsub\"\"\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Let's Dry-Run this Logic Sig as a Contract Account\n", - "\n", - "### To run a proper simulation we'll need to also provide the `pymnt` transaction which the contract approves" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# The prize winning args (i.e. the roots of x^2 - 12x + 35)\n", - "args = (5,7)\n", - "\n", - "# Payment txn information:\n", - "pymt = {\"amt\": 10_000_000} \n", - "inspector = DryRunExecutor.dryrun_logicsig(algod, TEAL, args, **pymt)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### We get a `DryRunInspector` object:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "type(inspector)=\n", - "inspector.passed()=True\n", - "inspector.stack_top()=1\n", - "inspector.final_scratch()={3: 10000000, 4: 1, 5: 12, 6: 35, 7: 7, 8: 84, 9: 84}\n", - "inspector.messages()=['PASS']\n", - "inspector.max_stack_height()=4\n", - "inspector.status()='PASS'\n", - "inspector.last_log()=None\n", - "\n" - ] - } - ], - "source": [ - "print(f\"\"\"\n", - "{type(inspector)=}\n", - "{inspector.passed()=}\n", - "{inspector.stack_top()=}\n", - "{inspector.final_scratch()=}\n", - "{inspector.messages()=}\n", - "{inspector.max_stack_height()=}\n", - "{inspector.status()=}\n", - "{inspector.last_log()=}\n", - "\"\"\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Generate CSV from a Bunch of Inputs\n", - "\n", - "### But since we're using this to validate a payment, and the amount has a complicated formula (the closer you are to the actual answer, the more you get payed), we need to have the formulas ready:" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "def payment_amount(p, q):\n", - " if p == q:\n", - " return 0\n", - " return 1_000_000 * max(10 - (sum(map(lambda x: abs(x**2 - 12 * x + 35), (p, q))) + 1) // 2, 0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Now let's execute 400 dry runs on all `int` pairs $(x, y)$ in $[0,19] \\times [0,19]$" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "inputs = list(product(range(20), range(20)))\n", - "amts = list(map(lambda args: payment_amount(*args), inputs))\n", - "dryrun_results, txns = [], []\n", - "for args, amt in zip(inputs, amts):\n", - " txn = {\"amt\": amt}\n", - " txns.append(txn)\n", - " dryrun_results.append(DryRunExecutor.dryrun_logicsig(algod, TEAL, args, **txn))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Let's create a CSV-report, and since we're in a Notebook, might as well load into a `DataFrame`" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
RunStatuscostfinal_messagelast_logtop_of_stackArg_00Arg_01amtmax_stack_height...s@002s@003s@004s@005s@006s@007s@008s@009s@010steps
01REJECTNaNREJECT`None00004...70.0NaN11235NaN35NaN70.0105
12REJECTNaNREJECT`None00104...59.0NaN112351.03612.059.0105
23REJECTNaNREJECT`None00204...50.0NaN112352.03924.050.0105
34REJECTNaNREJECT`None00304...43.0NaN112353.04436.043.0105
45REJECTNaNREJECT`None00404...38.0NaN112354.05148.038.0105
..................................................................
395396REJECTNaNREJECT`None0191504...248.0NaN1123515.0260180.0248.0105
396397REJECTNaNREJECT`None0191604...267.0NaN1123516.0291192.0267.0105
397398REJECTNaNREJECT`None0191704...288.0NaN1123517.0324204.0288.0105
398399REJECTNaNREJECT`None0191804...311.0NaN1123518.0359216.0311.0105
399400REJECTNaNREJECT`None0191904...336.0NaN1123519.0396228.0336.0105
\n", - "

400 rows × 22 columns

\n", - "
" - ], - "text/plain": [ - " Run Status cost final_message last_log top_of_stack Arg_00 \\\n", - "0 1 REJECT NaN REJECT `None 0 0 \n", - "1 2 REJECT NaN REJECT `None 0 0 \n", - "2 3 REJECT NaN REJECT `None 0 0 \n", - "3 4 REJECT NaN REJECT `None 0 0 \n", - "4 5 REJECT NaN REJECT `None 0 0 \n", - ".. ... ... ... ... ... ... ... \n", - "395 396 REJECT NaN REJECT `None 0 19 \n", - "396 397 REJECT NaN REJECT `None 0 19 \n", - "397 398 REJECT NaN REJECT `None 0 19 \n", - "398 399 REJECT NaN REJECT `None 0 19 \n", - "399 400 REJECT NaN REJECT `None 0 19 \n", - "\n", - " Arg_01 amt max_stack_height ... s@002 s@003 s@004 s@005 s@006 \\\n", - "0 0 0 4 ... 70.0 NaN 1 12 35 \n", - "1 1 0 4 ... 59.0 NaN 1 12 35 \n", - "2 2 0 4 ... 50.0 NaN 1 12 35 \n", - "3 3 0 4 ... 43.0 NaN 1 12 35 \n", - "4 4 0 4 ... 38.0 NaN 1 12 35 \n", - ".. ... ... ... ... ... ... ... ... ... \n", - "395 15 0 4 ... 248.0 NaN 1 12 35 \n", - "396 16 0 4 ... 267.0 NaN 1 12 35 \n", - "397 17 0 4 ... 288.0 NaN 1 12 35 \n", - "398 18 0 4 ... 311.0 NaN 1 12 35 \n", - "399 19 0 4 ... 336.0 NaN 1 12 35 \n", - "\n", - " s@007 s@008 s@009 s@010 steps \n", - "0 NaN 35 NaN 70.0 105 \n", - "1 1.0 36 12.0 59.0 105 \n", - "2 2.0 39 24.0 50.0 105 \n", - "3 3.0 44 36.0 43.0 105 \n", - "4 4.0 51 48.0 38.0 105 \n", - ".. ... ... ... ... ... \n", - "395 15.0 260 180.0 248.0 105 \n", - "396 16.0 291 192.0 267.0 105 \n", - "397 17.0 324 204.0 288.0 105 \n", - "398 18.0 359 216.0 311.0 105 \n", - "399 19.0 396 228.0 336.0 105 \n", - "\n", - "[400 rows x 22 columns]" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "csv = inspector.csv_report(inputs, dryrun_results, txns)\n", - "df = pd.read_csv(StringIO(csv))\n", - "df" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Some cleanup" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Statusfinal_messagetop_of_stackxyamtmax_stack_heights@000s@001s@002s@003s@004s@005s@006s@007s@008s@009s@010steps
0REJECTREJECT0000435.035.070.00.0112350.0350.070.0105
1REJECTREJECT0010435.024.059.00.0112351.03612.059.0105
2REJECTREJECT0020435.015.050.00.0112352.03924.050.0105
3REJECTREJECT0030435.08.043.00.0112353.04436.043.0105
4REJECTREJECT0040435.03.038.00.0112354.05148.038.0105
............................................................
395REJECTREJECT0191504168.080.0248.00.01123515.0260180.0248.0105
396REJECTREJECT0191604168.099.0267.00.01123516.0291192.0267.0105
397REJECTREJECT0191704168.0120.0288.00.01123517.0324204.0288.0105
398REJECTREJECT0191804168.0143.0311.00.01123518.0359216.0311.0105
399REJECTREJECT0191904168.0168.0336.00.01123519.0396228.0336.0105
\n", - "

400 rows × 19 columns

\n", - "
" - ], - "text/plain": [ - " Status final_message top_of_stack x y amt max_stack_height \\\n", - "0 REJECT REJECT 0 0 0 0 4 \n", - "1 REJECT REJECT 0 0 1 0 4 \n", - "2 REJECT REJECT 0 0 2 0 4 \n", - "3 REJECT REJECT 0 0 3 0 4 \n", - "4 REJECT REJECT 0 0 4 0 4 \n", - ".. ... ... ... .. .. ... ... \n", - "395 REJECT REJECT 0 19 15 0 4 \n", - "396 REJECT REJECT 0 19 16 0 4 \n", - "397 REJECT REJECT 0 19 17 0 4 \n", - "398 REJECT REJECT 0 19 18 0 4 \n", - "399 REJECT REJECT 0 19 19 0 4 \n", - "\n", - " s@000 s@001 s@002 s@003 s@004 s@005 s@006 s@007 s@008 s@009 \\\n", - "0 35.0 35.0 70.0 0.0 1 12 35 0.0 35 0.0 \n", - "1 35.0 24.0 59.0 0.0 1 12 35 1.0 36 12.0 \n", - "2 35.0 15.0 50.0 0.0 1 12 35 2.0 39 24.0 \n", - "3 35.0 8.0 43.0 0.0 1 12 35 3.0 44 36.0 \n", - "4 35.0 3.0 38.0 0.0 1 12 35 4.0 51 48.0 \n", - ".. ... ... ... ... ... ... ... ... ... ... \n", - "395 168.0 80.0 248.0 0.0 1 12 35 15.0 260 180.0 \n", - "396 168.0 99.0 267.0 0.0 1 12 35 16.0 291 192.0 \n", - "397 168.0 120.0 288.0 0.0 1 12 35 17.0 324 204.0 \n", - "398 168.0 143.0 311.0 0.0 1 12 35 18.0 359 216.0 \n", - "399 168.0 168.0 336.0 0.0 1 12 35 19.0 396 228.0 \n", - "\n", - " s@010 steps \n", - "0 70.0 105 \n", - "1 59.0 105 \n", - "2 50.0 105 \n", - "3 43.0 105 \n", - "4 38.0 105 \n", - ".. ... ... \n", - "395 248.0 105 \n", - "396 267.0 105 \n", - "397 288.0 105 \n", - "398 311.0 105 \n", - "399 336.0 105 \n", - "\n", - "[400 rows x 19 columns]" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df = (df[[col for col in df.columns if col not in (\" Run\", \" cost\", \" last_log\")]]\n", - " .rename({\n", - " \"Arg_00\": \"x\",\n", - " \"Arg_01\": \"y\",\n", - " }, axis=1)\n", - ").fillna(0)\n", - "df" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Zoom in on solution $(x, y) = (5, 7)$:" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Statustop_of_stackxyamts@000s@001s@002s@003s@004s@005s@006s@007s@008s@009
107PASS157100000000.00.00.010000000.0112357.08484.0
\n", - "
" - ], - "text/plain": [ - " Status top_of_stack x y amt s@000 s@001 s@002 s@003 \\\n", - "107 PASS 1 5 7 10000000 0.0 0.0 0.0 10000000.0 \n", - "\n", - " s@004 s@005 s@006 s@007 s@008 s@009 \n", - "107 1 12 35 7.0 84 84.0 " - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df[(df.x == 5) & (df.y == 7)][[\" Status\", \" top_of_stack\", \"x\", \"y\", \"amt\"] + [f\"s@00{i}\" for i in range(0,10)]]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Looks like `Scratch Slot 3` is where the expected payment amount is stored (except when the program `REJECT`s):" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "assert all((df[\" Status\"] == \"REJECT\") | (df.amt == df[\"s@003\"]))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3D-Plots from our Blackbox Results" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "def inspectors_3D_from_dryruns(max_x, max_y):\n", - " X = list(range(max_x))\n", - " Y = list(range(max_y))\n", - "\n", - " Z = []\n", - " for x in X:\n", - " row = []\n", - " for y in Y:\n", - " row.append(DryRunExecutor.dryrun_logicsig(algod, TEAL, (x, y), amt=payment_amount(x,y)))\n", - " Z.append(row)\n", - "\n", - " return X, Y, Z" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "def blackbox_plot(xs, ys, zs, ztick='µA', ztitle='prize (µA)', title='pymt txn analysis'):\n", - " fig = go.Figure(data=[go.Surface(z=zs, x=xs, y=ys)])\n", - " fig.update_traces(contours_z=dict(show=True, usecolormap=True,\n", - " highlightcolor=\"limegreen\", project_z=True))\n", - " fig.update_layout(title=title, autosize=False,\n", - " scene=dict(\n", - " zaxis=dict(ticksuffix=ztick),\n", - " zaxis_title=ztitle,\n", - " ),\n", - " scene_camera_eye=dict(x=1.87, y=0.88, z=-0.64),\n", - " width=600, height=600,\n", - " margin=dict(l=65, r=50, b=65, t=90)\n", - " ) \n", - " return fig.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "X, Y, i3d = inspectors_3D_from_dryruns(21, 21)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.plotly.v1+json": { - "config": { - "plotlyServerURL": "https://plot.ly" - }, - "data": [ + "cells": [ { - "contours": { - "z": { - "highlightcolor": "limegreen", - "project": { - "z": true - }, - "show": true, - "usecolormap": true - } - }, - "type": "surface", - "x": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "y": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "z": [ - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 1000000, - 2000000, - 2000000, - 2000000, - 1000000, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 2000000, - 4000000, - 6000000, - 5000000, - 6000000, - 4000000, - 2000000, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 1000000, - 4000000, - 7000000, - 8000000, - 8000000, - 8000000, - 7000000, - 4000000, - 1000000, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 2000000, - 6000000, - 8000000, - 10000000, - 9000000, - 10000000, - 8000000, - 6000000, - 2000000, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 2000000, - 5000000, - 8000000, - 9000000, - 9000000, - 9000000, - 8000000, - 5000000, - 2000000, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 2000000, - 6000000, - 8000000, - 10000000, - 9000000, - 10000000, - 8000000, - 6000000, - 2000000, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 1000000, - 4000000, - 7000000, - 8000000, - 8000000, - 8000000, - 7000000, - 4000000, - 1000000, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 2000000, - 4000000, - 6000000, - 5000000, - 6000000, - 4000000, - 2000000, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 1000000, - 2000000, - 2000000, - 2000000, - 1000000, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ] - ] - } - ], - "layout": { - "autosize": false, - "height": 600, - "margin": { - "b": 65, - "l": 65, - "r": 50, - "t": 90 + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Factorizer Game for Quadratic $x^2 - 12x + 35$" + ] }, - "scene": { - "camera": { - "eye": { - "x": 1.87, - "y": 0.88, - "z": -0.64 - } - }, - "zaxis": { - "ticksuffix": "µA", - "title": { - "text": "prize (µA)" - } - } + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### All the imports (and an `algod` as well)" + ] }, - "template": { - "data": { - "bar": [ - { - "error_x": { - "color": "#2a3f5f" - }, - "error_y": { - "color": "#2a3f5f" - }, - "marker": { - "line": { - "color": "#E5ECF6", - "width": 0.5 - }, - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "bar" - } - ], - "barpolar": [ - { - "marker": { - "line": { - "color": "#E5ECF6", - "width": 0.5 - }, - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "barpolar" - } - ], - "carpet": [ - { - "aaxis": { - "endlinecolor": "#2a3f5f", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "#2a3f5f" - }, - "baxis": { - "endlinecolor": "#2a3f5f", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "#2a3f5f" - }, - "type": "carpet" - } - ], - "choropleth": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "choropleth" - } - ], - "contour": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "contour" - } - ], - "contourcarpet": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "contourcarpet" - } - ], - "heatmap": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "heatmap" - } - ], - "heatmapgl": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "heatmapgl" - } - ], - "histogram": [ - { - "marker": { - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "histogram" - } - ], - "histogram2d": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "histogram2d" - } - ], - "histogram2dcontour": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "histogram2dcontour" - } - ], - "mesh3d": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "mesh3d" - } - ], - "parcoords": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "parcoords" - } - ], - "pie": [ - { - "automargin": true, - "type": "pie" - } - ], - "scatter": [ - { - "fillpattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - }, - "type": "scatter" - } - ], - "scatter3d": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatter3d" - } - ], - "scattercarpet": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattercarpet" - } - ], - "scattergeo": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattergeo" - } - ], - "scattergl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattergl" - } - ], - "scattermapbox": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattermapbox" - } - ], - "scatterpolar": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterpolar" - } - ], - "scatterpolargl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterpolargl" - } - ], - "scatterternary": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterternary" - } - ], - "surface": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "surface" - } - ], - "table": [ - { - "cells": { - "fill": { - "color": "#EBF0F8" - }, - "line": { - "color": "white" - } - }, - "header": { - "fill": { - "color": "#C8D4E3" - }, - "line": { - "color": "white" - } - }, - "type": "table" - } - ] - }, - "layout": { - "annotationdefaults": { - "arrowcolor": "#2a3f5f", - "arrowhead": 0, - "arrowwidth": 1 - }, - "autotypenumbers": "strict", - "coloraxis": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "colorscale": { - "diverging": [ - [ - 0, - "#8e0152" - ], - [ - 0.1, - "#c51b7d" - ], - [ - 0.2, - "#de77ae" - ], - [ - 0.3, - "#f1b6da" - ], - [ - 0.4, - "#fde0ef" - ], - [ - 0.5, - "#f7f7f7" - ], - [ - 0.6, - "#e6f5d0" - ], - [ - 0.7, - "#b8e186" - ], - [ - 0.8, - "#7fbc41" - ], - [ - 0.9, - "#4d9221" - ], - [ - 1, - "#276419" + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from io import StringIO\n", + "from itertools import product\n", + "import pandas as pd\n", + "import plotly.graph_objects as go\n", + "\n", + "from graviton.blackbox import DryRunExecutor, DryRunTransactionParams as TxParams, ExecutionMode\n", + "from tests.clients import get_algod\n", + "algod = get_algod()" ] - ], - "sequential": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Logic Signature for Quadratic" ] - ], - "sequentialminus": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "TEAL = \"\"\"#pragma version 5\n", + "intcblock 1 12 35\n", + "pushbytes 0x43616e20796f7520666163746f722031202a20785e32202d203132202a2078202b203335203f // \"Can you factor 1 * x^2 - 12 * x + 35 ?\"\n", + "pop\n", + "intc_0 // 1\n", + "intc_1 // 12\n", + "intc_2 // 35\n", + "arg 0\n", + "btoi\n", + "callsub sub0\n", + "store 0\n", + "intc_0 // 1\n", + "intc_1 // 12\n", + "intc_2 // 35\n", + "arg 1\n", + "btoi\n", + "callsub sub0\n", + "store 1\n", + "load 0\n", + "load 1\n", + "+\n", + "store 2\n", + "load 2\n", + "callsub sub1\n", + "store 3\n", + "txn TypeEnum\n", + "intc_0 // pay\n", + "==\n", + "txn CloseRemainderTo\n", + "global ZeroAddress\n", + "==\n", + "&&\n", + "arg 0\n", + "btoi\n", + "arg 1\n", + "btoi\n", + "!=\n", + "&&\n", + "load 3\n", + "&&\n", + "txn Amount\n", + "load 3\n", + "==\n", + "&&\n", + "return\n", + "sub0: // root_closeness\n", + "store 7\n", + "store 6\n", + "store 5\n", + "store 4\n", + "load 4\n", + "load 7\n", + "*\n", + "load 7\n", + "*\n", + "load 6\n", + "+\n", + "store 8\n", + "load 5\n", + "load 7\n", + "*\n", + "store 9\n", + "load 8\n", + "load 9\n", + "<\n", + "bnz sub0_l2\n", + "load 8\n", + "load 9\n", + "-\n", + "b sub0_l3\n", + "sub0_l2:\n", + "load 9\n", + "load 8\n", + "-\n", + "sub0_l3:\n", + "retsub\n", + "sub1: // calculate_prize\n", + "store 10\n", + "load 10\n", + "intc_0 // 1\n", + "+\n", + "pushint 20 // 20\n", + "<\n", + "bnz sub1_l2\n", + "pushint 0 // 0\n", + "b sub1_l3\n", + "sub1_l2:\n", + "pushint 1000000 // 1000000\n", + "pushint 10 // 10\n", + "load 10\n", + "intc_0 // 1\n", + "+\n", + "pushint 2 // 2\n", + "/\n", + "-\n", + "*\n", + "sub1_l3:\n", + "retsub\"\"\"" ] - ] - }, - "colorway": [ - "#636efa", - "#EF553B", - "#00cc96", - "#ab63fa", - "#FFA15A", - "#19d3f3", - "#FF6692", - "#B6E880", - "#FF97FF", - "#FECB52" - ], - "font": { - "color": "#2a3f5f" - }, - "geo": { - "bgcolor": "white", - "lakecolor": "white", - "landcolor": "#E5ECF6", - "showlakes": true, - "showland": true, - "subunitcolor": "white" - }, - "hoverlabel": { - "align": "left" - }, - "hovermode": "closest", - "mapbox": { - "style": "light" - }, - "paper_bgcolor": "white", - "plot_bgcolor": "#E5ECF6", - "polar": { - "angularaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "bgcolor": "#E5ECF6", - "radialaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - } - }, - "scene": { - "xaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - }, - "yaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - }, - "zaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - } - }, - "shapedefaults": { - "line": { - "color": "#2a3f5f" - } - }, - "ternary": { - "aaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "baxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "bgcolor": "#E5ECF6", - "caxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - } - }, - "title": { - "x": 0.05 - }, - "xaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "ticks": "", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white", - "zerolinewidth": 2 - }, - "yaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "ticks": "", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white", - "zerolinewidth": 2 - } - } }, - "title": { - "text": "Scratch Slot #3" + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Let's Dry-Run this Logic Sig as a Contract Account\n", + "\n", + "### To run a proper simulation we'll need to also provide the `pymnt` transaction which the contract approves" + ] }, - "width": 600 - } - } - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "blackbox_plot(X, Y, [[inspector.final_scratch().get(3,0) for inspector in row] for row in i3d], title=\"Scratch Slot #3\")" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.plotly.v1+json": { - "config": { - "plotlyServerURL": "https://plot.ly" - }, - "data": [ { - "contours": { - "z": { - "highlightcolor": "limegreen", - "project": { - "z": true - }, - "show": true, - "usecolormap": true - } - }, - "type": "surface", - "x": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "y": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "z": [ - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ], - [ - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4 - ] - ] - } - ], - "layout": { - "autosize": false, - "height": 600, - "margin": { - "b": 65, - "l": 65, - "r": 50, - "t": 90 + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# The prize winning args (i.e. the roots of x^2 - 12x + 35)\n", + "args = (5,7)\n", + "\n", + "# Payment txn information:\n", + "txn = TxParams.for_logicsig(amt=10_000_000)\n", + "\n", + "# Use a single executor for the rest of the notebook:\n", + "executor = DryRunExecutor(algod, ExecutionMode.Signature, TEAL)\n", + "\n", + "inspector = executor.run_one(args, txn_params=txn)" + ] }, - "scene": { - "camera": { - "eye": { - "x": 1.87, - "y": 0.88, - "z": -0.64 - } - }, - "zaxis": { - "title": { - "text": "Max Stack Height" - } - } + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### We get a `DryRunInspector` object:" + ] }, - "template": { - "data": { - "bar": [ - { - "error_x": { - "color": "#2a3f5f" - }, - "error_y": { - "color": "#2a3f5f" - }, - "marker": { - "line": { - "color": "#E5ECF6", - "width": 0.5 - }, - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "bar" - } - ], - "barpolar": [ - { - "marker": { - "line": { - "color": "#E5ECF6", - "width": 0.5 - }, - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "barpolar" - } - ], - "carpet": [ - { - "aaxis": { - "endlinecolor": "#2a3f5f", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "#2a3f5f" - }, - "baxis": { - "endlinecolor": "#2a3f5f", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "#2a3f5f" - }, - "type": "carpet" - } - ], - "choropleth": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "choropleth" - } - ], - "contour": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "contour" - } - ], - "contourcarpet": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "contourcarpet" - } - ], - "heatmap": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "heatmap" - } - ], - "heatmapgl": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "heatmapgl" - } - ], - "histogram": [ - { - "marker": { - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "histogram" - } - ], - "histogram2d": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "histogram2d" - } - ], - "histogram2dcontour": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "histogram2dcontour" - } - ], - "mesh3d": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "mesh3d" - } - ], - "parcoords": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "parcoords" - } - ], - "pie": [ - { - "automargin": true, - "type": "pie" - } - ], - "scatter": [ - { - "fillpattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - }, - "type": "scatter" - } - ], - "scatter3d": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatter3d" - } - ], - "scattercarpet": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattercarpet" - } - ], - "scattergeo": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattergeo" - } - ], - "scattergl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattergl" - } - ], - "scattermapbox": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattermapbox" - } - ], - "scatterpolar": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterpolar" - } - ], - "scatterpolargl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterpolargl" - } - ], - "scatterternary": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterternary" - } - ], - "surface": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "surface" - } - ], - "table": [ - { - "cells": { - "fill": { - "color": "#EBF0F8" - }, - "line": { - "color": "white" - } - }, - "header": { - "fill": { - "color": "#C8D4E3" - }, - "line": { - "color": "white" - } - }, - "type": "table" - } - ] - }, - "layout": { - "annotationdefaults": { - "arrowcolor": "#2a3f5f", - "arrowhead": 0, - "arrowwidth": 1 - }, - "autotypenumbers": "strict", - "coloraxis": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "colorscale": { - "diverging": [ - [ - 0, - "#8e0152" - ], - [ - 0.1, - "#c51b7d" - ], - [ - 0.2, - "#de77ae" - ], - [ - 0.3, - "#f1b6da" - ], - [ - 0.4, - "#fde0ef" - ], - [ - 0.5, - "#f7f7f7" - ], - [ - 0.6, - "#e6f5d0" - ], - [ - 0.7, - "#b8e186" - ], - [ - 0.8, - "#7fbc41" - ], - [ - 0.9, - "#4d9221" - ], - [ - 1, - "#276419" + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "type(inspector)=\n", + "inspector.passed()=True\n", + "inspector.stack_top()=1\n", + "inspector.final_scratch()={3: 10000000, 4: 1, 5: 12, 6: 35, 7: 7, 8: 84, 9: 84}\n", + "inspector.messages()=['PASS']\n", + "inspector.max_stack_height()=4\n", + "inspector.status()='PASS'\n", + "inspector.last_log()=None\n", + "\n" + ] + } + ], + "source": [ + "print(f\"\"\"\n", + "{type(inspector)=}\n", + "{inspector.passed()=}\n", + "{inspector.stack_top()=}\n", + "{inspector.final_scratch()=}\n", + "{inspector.messages()=}\n", + "{inspector.max_stack_height()=}\n", + "{inspector.status()=}\n", + "{inspector.last_log()=}\n", + "\"\"\")" ] - ], - "sequential": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generate CSV from a Bunch of Inputs\n", + "\n", + "### But since we're using this to validate a payment, and the amount has a complicated formula (the closer you are to the actual answer, the more you get payed), we need to have the formulas ready:" ] - ], - "sequentialminus": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def payment_amount(p, q):\n", + " if p == q:\n", + " return 0\n", + " return 1_000_000 * max(10 - (sum(map(lambda x: abs(x**2 - 12 * x + 35), (p, q))) + 1) // 2, 0)" ] - ] - }, - "colorway": [ - "#636efa", - "#EF553B", - "#00cc96", - "#ab63fa", - "#FFA15A", - "#19d3f3", - "#FF6692", - "#B6E880", - "#FF97FF", - "#FECB52" - ], - "font": { - "color": "#2a3f5f" - }, - "geo": { - "bgcolor": "white", - "lakecolor": "white", - "landcolor": "#E5ECF6", - "showlakes": true, - "showland": true, - "subunitcolor": "white" - }, - "hoverlabel": { - "align": "left" - }, - "hovermode": "closest", - "mapbox": { - "style": "light" - }, - "paper_bgcolor": "white", - "plot_bgcolor": "#E5ECF6", - "polar": { - "angularaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "bgcolor": "#E5ECF6", - "radialaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - } - }, - "scene": { - "xaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - }, - "yaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - }, - "zaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - } - }, - "shapedefaults": { - "line": { - "color": "#2a3f5f" - } - }, - "ternary": { - "aaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "baxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "bgcolor": "#E5ECF6", - "caxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - } - }, - "title": { - "x": 0.05 - }, - "xaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "ticks": "", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white", - "zerolinewidth": 2 - }, - "yaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "ticks": "", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white", - "zerolinewidth": 2 - } - } }, - "title": { - "text": "Max Stack Height Analysis" + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Now let's execute 400 dry runs on all `int` pairs $(x, y)$ in $[0,19] \\times [0,19]$" + ] }, - "width": 600 - } - } - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "blackbox_plot(X, Y, [[inspector.max_stack_height() for inspector in row] for row in i3d], ztick=None, ztitle=\"Max Stack Height\", title=\"Max Stack Height Analysis\")" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.plotly.v1+json": { - "config": { - "plotlyServerURL": "https://plot.ly" - }, - "data": [ { - "contours": { - "z": { - "highlightcolor": "limegreen", - "project": { - "z": true - }, - "show": true, - "usecolormap": true - } - }, - "type": "surface", - "x": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "y": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "z": [ - [ - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35 - ], - [ - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24 - ], - [ - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15 - ], - [ - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8 - ], - [ - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3 - ], - [ - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8 - ], - [ - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15, - 15 - ], - [ - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24 - ], - [ - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35, - 35 - ], - [ - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48 - ], - [ - 63, - 63, - 63, - 63, - 63, - 63, - 63, - 63, - 63, - 63, - 63, - 63, - 63, - 63, - 63, - 63, - 63, - 63, - 63, - 63, - 63 - ], - [ - 80, - 80, - 80, - 80, - 80, - 80, - 80, - 80, - 80, - 80, - 80, - 80, - 80, - 80, - 80, - 80, - 80, - 80, - 80, - 80, - 80 - ], - [ - 99, - 99, - 99, - 99, - 99, - 99, - 99, - 99, - 99, - 99, - 99, - 99, - 99, - 99, - 99, - 99, - 99, - 99, - 99, - 99, - 99 - ], - [ - 120, - 120, - 120, - 120, - 120, - 120, - 120, - 120, - 120, - 120, - 120, - 120, - 120, - 120, - 120, - 120, - 120, - 120, - 120, - 120, - 120 - ], - [ - 143, - 143, - 143, - 143, - 143, - 143, - 143, - 143, - 143, - 143, - 143, - 143, - 143, - 143, - 143, - 143, - 143, - 143, - 143, - 143, - 143 - ], - [ - 168, - 168, - 168, - 168, - 168, - 168, - 168, - 168, - 168, - 168, - 168, - 168, - 168, - 168, - 168, - 168, - 168, - 168, - 168, - 168, - 168 - ], - [ - 195, - 195, - 195, - 195, - 195, - 195, - 195, - 195, - 195, - 195, - 195, - 195, - 195, - 195, - 195, - 195, - 195, - 195, - 195, - 195, - 195 - ] - ] - } - ], - "layout": { - "autosize": false, - "height": 600, - "margin": { - "b": 65, - "l": 65, - "r": 50, - "t": 90 + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "inputs = list(product(range(20), range(20)))\n", + "amts = list(map(lambda args: payment_amount(*args), inputs))\n", + "dryrun_results, txns = [], []\n", + "for args, amt in zip(inputs, amts):\n", + " txn = {\"amt\": amt}\n", + " txn_params = TxParams.for_logicsig(**txn)\n", + " txns.append(txn)\n", + " dryrun_results.append(executor.run_one(args, txn_params=txn_params))" + ] }, - "scene": { - "camera": { - "eye": { - "x": 1.87, - "y": 0.88, - "z": -0.64 - } - }, - "zaxis": { - "title": { - "text": "Scratch Slot 0" - } - } + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Let's create a CSV-report, and since we're in a Notebook, might as well load into a `DataFrame`" + ] }, - "template": { - "data": { - "bar": [ - { - "error_x": { - "color": "#2a3f5f" - }, - "error_y": { - "color": "#2a3f5f" - }, - "marker": { - "line": { - "color": "#E5ECF6", - "width": 0.5 - }, - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "bar" - } - ], - "barpolar": [ - { - "marker": { - "line": { - "color": "#E5ECF6", - "width": 0.5 - }, - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "barpolar" - } - ], - "carpet": [ - { - "aaxis": { - "endlinecolor": "#2a3f5f", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "#2a3f5f" - }, - "baxis": { - "endlinecolor": "#2a3f5f", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "#2a3f5f" - }, - "type": "carpet" - } - ], - "choropleth": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "choropleth" - } - ], - "contour": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "contour" - } - ], - "contourcarpet": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "contourcarpet" - } - ], - "heatmap": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "heatmap" - } - ], - "heatmapgl": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "heatmapgl" - } - ], - "histogram": [ - { - "marker": { - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "histogram" - } - ], - "histogram2d": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "histogram2d" - } - ], - "histogram2dcontour": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "histogram2dcontour" - } - ], - "mesh3d": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "mesh3d" - } - ], - "parcoords": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "parcoords" - } - ], - "pie": [ - { - "automargin": true, - "type": "pie" - } - ], - "scatter": [ - { - "fillpattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - }, - "type": "scatter" - } - ], - "scatter3d": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatter3d" - } - ], - "scattercarpet": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattercarpet" - } - ], - "scattergeo": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattergeo" - } - ], - "scattergl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattergl" - } - ], - "scattermapbox": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattermapbox" - } - ], - "scatterpolar": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterpolar" - } - ], - "scatterpolargl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterpolargl" - } - ], - "scatterternary": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterternary" - } - ], - "surface": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "surface" - } - ], - "table": [ - { - "cells": { - "fill": { - "color": "#EBF0F8" - }, - "line": { - "color": "white" - } - }, - "header": { - "fill": { - "color": "#C8D4E3" - }, - "line": { - "color": "white" - } - }, - "type": "table" - } - ] - }, - "layout": { - "annotationdefaults": { - "arrowcolor": "#2a3f5f", - "arrowhead": 0, - "arrowwidth": 1 - }, - "autotypenumbers": "strict", - "coloraxis": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "colorscale": { - "diverging": [ - [ - 0, - "#8e0152" - ], - [ - 0.1, - "#c51b7d" - ], - [ - 0.2, - "#de77ae" - ], - [ - 0.3, - "#f1b6da" - ], - [ - 0.4, - "#fde0ef" - ], - [ - 0.5, - "#f7f7f7" - ], - [ - 0.6, - "#e6f5d0" - ], - [ - 0.7, - "#b8e186" - ], - [ - 0.8, - "#7fbc41" - ], - [ - 0.9, - "#4d9221" - ], - [ - 1, - "#276419" + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
RunStatusbudget_addedbudget_consumedcostfinal_messagelast_logtop_of_stackArg_00Arg_01...s@002s@003s@004s@005s@006s@007s@008s@009s@010steps
01REJECTNaNNaNNaNREJECT`None000...70.0NaN11235NaN35NaN70.0105
12REJECTNaNNaNNaNREJECT`None001...59.0NaN112351.03612.059.0105
23REJECTNaNNaNNaNREJECT`None002...50.0NaN112352.03924.050.0105
34REJECTNaNNaNNaNREJECT`None003...43.0NaN112353.04436.043.0105
45REJECTNaNNaNNaNREJECT`None004...38.0NaN112354.05148.038.0105
..................................................................
395396REJECTNaNNaNNaNREJECT`None01915...248.0NaN1123515.0260180.0248.0105
396397REJECTNaNNaNNaNREJECT`None01916...267.0NaN1123516.0291192.0267.0105
397398REJECTNaNNaNNaNREJECT`None01917...288.0NaN1123517.0324204.0288.0105
398399REJECTNaNNaNNaNREJECT`None01918...311.0NaN1123518.0359216.0311.0105
399400REJECTNaNNaNNaNREJECT`None01919...336.0NaN1123519.0396228.0336.0105
\n", + "

400 rows × 24 columns

\n", + "
" + ], + "text/plain": [ + " Run Status budget_added budget_consumed cost final_message \\\n", + "0 1 REJECT NaN NaN NaN REJECT \n", + "1 2 REJECT NaN NaN NaN REJECT \n", + "2 3 REJECT NaN NaN NaN REJECT \n", + "3 4 REJECT NaN NaN NaN REJECT \n", + "4 5 REJECT NaN NaN NaN REJECT \n", + ".. ... ... ... ... ... ... \n", + "395 396 REJECT NaN NaN NaN REJECT \n", + "396 397 REJECT NaN NaN NaN REJECT \n", + "397 398 REJECT NaN NaN NaN REJECT \n", + "398 399 REJECT NaN NaN NaN REJECT \n", + "399 400 REJECT NaN NaN NaN REJECT \n", + "\n", + " last_log top_of_stack Arg_00 Arg_01 ... s@002 s@003 s@004 s@005 \\\n", + "0 `None 0 0 0 ... 70.0 NaN 1 12 \n", + "1 `None 0 0 1 ... 59.0 NaN 1 12 \n", + "2 `None 0 0 2 ... 50.0 NaN 1 12 \n", + "3 `None 0 0 3 ... 43.0 NaN 1 12 \n", + "4 `None 0 0 4 ... 38.0 NaN 1 12 \n", + ".. ... ... ... ... ... ... ... ... ... \n", + "395 `None 0 19 15 ... 248.0 NaN 1 12 \n", + "396 `None 0 19 16 ... 267.0 NaN 1 12 \n", + "397 `None 0 19 17 ... 288.0 NaN 1 12 \n", + "398 `None 0 19 18 ... 311.0 NaN 1 12 \n", + "399 `None 0 19 19 ... 336.0 NaN 1 12 \n", + "\n", + " s@006 s@007 s@008 s@009 s@010 steps \n", + "0 35 NaN 35 NaN 70.0 105 \n", + "1 35 1.0 36 12.0 59.0 105 \n", + "2 35 2.0 39 24.0 50.0 105 \n", + "3 35 3.0 44 36.0 43.0 105 \n", + "4 35 4.0 51 48.0 38.0 105 \n", + ".. ... ... ... ... ... ... \n", + "395 35 15.0 260 180.0 248.0 105 \n", + "396 35 16.0 291 192.0 267.0 105 \n", + "397 35 17.0 324 204.0 288.0 105 \n", + "398 35 18.0 359 216.0 311.0 105 \n", + "399 35 19.0 396 228.0 336.0 105 \n", + "\n", + "[400 rows x 24 columns]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "csv = inspector.csv_report(inputs, dryrun_results, txns)\n", + "df = pd.read_csv(StringIO(csv))\n", + "df" ] - ], - "sequential": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Some cleanup" ] - ], - "sequentialminus": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Statusbudget_addedbudget_consumedfinal_messagetop_of_stackxyamtmax_stack_heights@000...s@002s@003s@004s@005s@006s@007s@008s@009s@010steps
0REJECT0.00.0REJECT0000435.0...70.00.0112350.0350.070.0105
1REJECT0.00.0REJECT0010435.0...59.00.0112351.03612.059.0105
2REJECT0.00.0REJECT0020435.0...50.00.0112352.03924.050.0105
3REJECT0.00.0REJECT0030435.0...43.00.0112353.04436.043.0105
4REJECT0.00.0REJECT0040435.0...38.00.0112354.05148.038.0105
..................................................................
395REJECT0.00.0REJECT0191504168.0...248.00.01123515.0260180.0248.0105
396REJECT0.00.0REJECT0191604168.0...267.00.01123516.0291192.0267.0105
397REJECT0.00.0REJECT0191704168.0...288.00.01123517.0324204.0288.0105
398REJECT0.00.0REJECT0191804168.0...311.00.01123518.0359216.0311.0105
399REJECT0.00.0REJECT0191904168.0...336.00.01123519.0396228.0336.0105
\n", + "

400 rows × 21 columns

\n", + "
" + ], + "text/plain": [ + " Status budget_added budget_consumed final_message top_of_stack \\\n", + "0 REJECT 0.0 0.0 REJECT 0 \n", + "1 REJECT 0.0 0.0 REJECT 0 \n", + "2 REJECT 0.0 0.0 REJECT 0 \n", + "3 REJECT 0.0 0.0 REJECT 0 \n", + "4 REJECT 0.0 0.0 REJECT 0 \n", + ".. ... ... ... ... ... \n", + "395 REJECT 0.0 0.0 REJECT 0 \n", + "396 REJECT 0.0 0.0 REJECT 0 \n", + "397 REJECT 0.0 0.0 REJECT 0 \n", + "398 REJECT 0.0 0.0 REJECT 0 \n", + "399 REJECT 0.0 0.0 REJECT 0 \n", + "\n", + " x y amt max_stack_height s@000 ... s@002 s@003 s@004 s@005 \\\n", + "0 0 0 0 4 35.0 ... 70.0 0.0 1 12 \n", + "1 0 1 0 4 35.0 ... 59.0 0.0 1 12 \n", + "2 0 2 0 4 35.0 ... 50.0 0.0 1 12 \n", + "3 0 3 0 4 35.0 ... 43.0 0.0 1 12 \n", + "4 0 4 0 4 35.0 ... 38.0 0.0 1 12 \n", + ".. .. .. ... ... ... ... ... ... ... ... \n", + "395 19 15 0 4 168.0 ... 248.0 0.0 1 12 \n", + "396 19 16 0 4 168.0 ... 267.0 0.0 1 12 \n", + "397 19 17 0 4 168.0 ... 288.0 0.0 1 12 \n", + "398 19 18 0 4 168.0 ... 311.0 0.0 1 12 \n", + "399 19 19 0 4 168.0 ... 336.0 0.0 1 12 \n", + "\n", + " s@006 s@007 s@008 s@009 s@010 steps \n", + "0 35 0.0 35 0.0 70.0 105 \n", + "1 35 1.0 36 12.0 59.0 105 \n", + "2 35 2.0 39 24.0 50.0 105 \n", + "3 35 3.0 44 36.0 43.0 105 \n", + "4 35 4.0 51 48.0 38.0 105 \n", + ".. ... ... ... ... ... ... \n", + "395 35 15.0 260 180.0 248.0 105 \n", + "396 35 16.0 291 192.0 267.0 105 \n", + "397 35 17.0 324 204.0 288.0 105 \n", + "398 35 18.0 359 216.0 311.0 105 \n", + "399 35 19.0 396 228.0 336.0 105 \n", + "\n", + "[400 rows x 21 columns]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = (df[[col for col in df.columns if col not in (\" Run\", \" cost\", \" last_log\")]]\n", + " .rename({\n", + " \"Arg_00\": \"x\",\n", + " \"Arg_01\": \"y\",\n", + " }, axis=1)\n", + ").fillna(0)\n", + "df" ] - ] - }, - "colorway": [ - "#636efa", - "#EF553B", - "#00cc96", - "#ab63fa", - "#FFA15A", - "#19d3f3", - "#FF6692", - "#B6E880", - "#FF97FF", - "#FECB52" - ], - "font": { - "color": "#2a3f5f" - }, - "geo": { - "bgcolor": "white", - "lakecolor": "white", - "landcolor": "#E5ECF6", - "showlakes": true, - "showland": true, - "subunitcolor": "white" - }, - "hoverlabel": { - "align": "left" - }, - "hovermode": "closest", - "mapbox": { - "style": "light" - }, - "paper_bgcolor": "white", - "plot_bgcolor": "#E5ECF6", - "polar": { - "angularaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "bgcolor": "#E5ECF6", - "radialaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - } - }, - "scene": { - "xaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - }, - "yaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - }, - "zaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - } - }, - "shapedefaults": { - "line": { - "color": "#2a3f5f" - } - }, - "ternary": { - "aaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "baxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "bgcolor": "#E5ECF6", - "caxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - } - }, - "title": { - "x": 0.05 - }, - "xaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "ticks": "", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white", - "zerolinewidth": 2 - }, - "yaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "ticks": "", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white", - "zerolinewidth": 2 - } - } }, - "title": { - "text": "Slot 0 Analysis" + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Zoom in on solution $(x, y) = (5, 7)$:" + ] }, - "width": 600 - } - } - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "blackbox_plot(\n", - " X, \n", - " Y, \n", - " [[inspector.final_scratch().get(0,0) for inspector in row] for row in i3d], \n", - " ztick=None, \n", - " ztitle=\"Scratch Slot 0\",\n", - " title=\"Slot 0 Analysis\"\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.plotly.v1+json": { - "config": { - "plotlyServerURL": "https://plot.ly" - }, - "data": [ { - "contours": { - "z": { - "highlightcolor": "limegreen", - "project": { - "z": true - }, - "show": true, - "usecolormap": true - } - }, - "type": "surface", - "x": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "y": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "z": [ - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 1, - 1, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 1, - 1, - 1, - 0, - 1, - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 1, - 1, - 1, - 1, - 0, - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 0, - 1, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 0, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ] - ] - } - ], - "layout": { - "autosize": false, - "height": 600, - "margin": { - "b": 65, - "l": 65, - "r": 50, - "t": 90 + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Statustop_of_stackxyamts@000s@001s@002s@003s@004s@005s@006s@007s@008s@009
107PASS157100000000.00.00.010000000.0112357.08484.0
\n", + "
" + ], + "text/plain": [ + " Status top_of_stack x y amt s@000 s@001 s@002 s@003 \\\n", + "107 PASS 1 5 7 10000000 0.0 0.0 0.0 10000000.0 \n", + "\n", + " s@004 s@005 s@006 s@007 s@008 s@009 \n", + "107 1 12 35 7.0 84 84.0 " + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[(df.x == 5) & (df.y == 7)][[\" Status\", \" top_of_stack\", \"x\", \"y\", \"amt\"] + [f\"s@00{i}\" for i in range(0,10)]]" + ] }, - "scene": { - "camera": { - "eye": { - "x": 1.87, - "y": 0.88, - "z": -0.64 - } - }, - "zaxis": { - "title": { - "text": "final stack top" - } - } + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Looks like `Scratch Slot 3` is where the expected payment amount is stored (except when the program `REJECT`s):" + ] }, - "template": { - "data": { - "bar": [ - { - "error_x": { - "color": "#2a3f5f" - }, - "error_y": { - "color": "#2a3f5f" - }, - "marker": { - "line": { - "color": "#E5ECF6", - "width": 0.5 - }, - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "bar" - } - ], - "barpolar": [ - { - "marker": { - "line": { - "color": "#E5ECF6", - "width": 0.5 - }, - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "barpolar" - } - ], - "carpet": [ - { - "aaxis": { - "endlinecolor": "#2a3f5f", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "#2a3f5f" - }, - "baxis": { - "endlinecolor": "#2a3f5f", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "#2a3f5f" - }, - "type": "carpet" - } - ], - "choropleth": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "choropleth" - } - ], - "contour": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "contour" - } - ], - "contourcarpet": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "contourcarpet" - } - ], - "heatmap": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "heatmap" - } - ], - "heatmapgl": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "heatmapgl" - } - ], - "histogram": [ - { - "marker": { - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "histogram" - } - ], - "histogram2d": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "histogram2d" - } - ], - "histogram2dcontour": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "histogram2dcontour" - } - ], - "mesh3d": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "mesh3d" - } - ], - "parcoords": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "parcoords" - } - ], - "pie": [ - { - "automargin": true, - "type": "pie" - } - ], - "scatter": [ - { - "fillpattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - }, - "type": "scatter" - } - ], - "scatter3d": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatter3d" - } - ], - "scattercarpet": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattercarpet" - } - ], - "scattergeo": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattergeo" - } - ], - "scattergl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattergl" - } - ], - "scattermapbox": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattermapbox" - } - ], - "scatterpolar": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterpolar" - } - ], - "scatterpolargl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterpolargl" - } - ], - "scatterternary": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterternary" - } - ], - "surface": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "surface" - } - ], - "table": [ - { - "cells": { - "fill": { - "color": "#EBF0F8" - }, - "line": { - "color": "white" - } - }, - "header": { - "fill": { - "color": "#C8D4E3" - }, - "line": { - "color": "white" - } - }, - "type": "table" - } - ] - }, - "layout": { - "annotationdefaults": { - "arrowcolor": "#2a3f5f", - "arrowhead": 0, - "arrowwidth": 1 - }, - "autotypenumbers": "strict", - "coloraxis": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "colorscale": { - "diverging": [ - [ - 0, - "#8e0152" - ], - [ - 0.1, - "#c51b7d" - ], - [ - 0.2, - "#de77ae" - ], - [ - 0.3, - "#f1b6da" - ], - [ - 0.4, - "#fde0ef" - ], - [ - 0.5, - "#f7f7f7" - ], - [ - 0.6, - "#e6f5d0" - ], - [ - 0.7, - "#b8e186" - ], - [ - 0.8, - "#7fbc41" - ], - [ - 0.9, - "#4d9221" - ], - [ - 1, - "#276419" + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "assert all((df[\" Status\"] == \"REJECT\") | (df.amt == df[\"s@003\"]))" ] - ], - "sequential": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3D-Plots from our Blackbox Results" ] - ], - "sequentialminus": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "def inspectors_3D_from_dryruns(max_x, max_y):\n", + " X = list(range(max_x))\n", + " Y = list(range(max_y))\n", + "\n", + " Z = []\n", + " for x in X:\n", + " row = []\n", + " for y in Y:\n", + " txn_params = TxParams.for_logicsig(amt=payment_amount(x,y))\n", + " row.append(executor._run((x, y),txn_params=txn_params))\n", + " Z.append(row)\n", + "\n", + " return X, Y, Z" ] - ] - }, - "colorway": [ - "#636efa", - "#EF553B", - "#00cc96", - "#ab63fa", - "#FFA15A", - "#19d3f3", - "#FF6692", - "#B6E880", - "#FF97FF", - "#FECB52" - ], - "font": { - "color": "#2a3f5f" - }, - "geo": { - "bgcolor": "white", - "lakecolor": "white", - "landcolor": "#E5ECF6", - "showlakes": true, - "showland": true, - "subunitcolor": "white" - }, - "hoverlabel": { - "align": "left" - }, - "hovermode": "closest", - "mapbox": { - "style": "light" - }, - "paper_bgcolor": "white", - "plot_bgcolor": "#E5ECF6", - "polar": { - "angularaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "bgcolor": "#E5ECF6", - "radialaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - } - }, - "scene": { - "xaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - }, - "yaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - }, - "zaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - } - }, - "shapedefaults": { - "line": { - "color": "#2a3f5f" - } - }, - "ternary": { - "aaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "baxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "bgcolor": "#E5ECF6", - "caxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - } - }, - "title": { - "x": 0.05 - }, - "xaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "ticks": "", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white", - "zerolinewidth": 2 - }, - "yaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "ticks": "", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white", - "zerolinewidth": 2 - } - } }, - "title": { - "text": "Stack Top Analysis" + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "def blackbox_plot(xs, ys, zs, ztick='µA', ztitle='prize (µA)', title='pymt txn analysis'):\n", + " fig = go.Figure(data=[go.Surface(z=zs, x=xs, y=ys)])\n", + " fig.update_traces(contours_z=dict(show=True, usecolormap=True,\n", + " highlightcolor=\"limegreen\", project_z=True))\n", + " fig.update_layout(title=title, autosize=False,\n", + " scene=dict(\n", + " zaxis=dict(ticksuffix=ztick),\n", + " zaxis_title=ztitle,\n", + " ),\n", + " scene_camera_eye=dict(x=1.87, y=0.88, z=-0.64),\n", + " width=600, height=600,\n", + " margin=dict(l=65, r=50, b=65, t=90)\n", + " ) \n", + " return fig.show()" + ] }, - "width": 600 - } - } - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "blackbox_plot(X, Y, [[inspector.stack_top() for inspector in row] for row in i3d], ztick=None, ztitle=\"final stack top\", title=\"Stack Top Analysis\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Hackey Appendix" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [], - "source": [ - "\"\"\"\n", - "Ok... This is a hack that I came up with last minute for the demo... \n", - "But this could easily be done in a straightforward, non-hacky way (just build z directly from the dry runs)\n", - "\"\"\"\n", - "def x(row):\n", - " return row.x\n", - "\n", - "def y(row):\n", - " return row.y\n", - "\n", - "def z_factory(df, z_col=\"amt\"):\n", - " def z(_x, _y):\n", - " _rows = df[(df.x == _x) & (df.y == _y)]\n", - " assert len(_rows) == 1\n", - " return _rows.iloc[0][z_col]\n", - "\n", - " return z\n", - "\n", - "z = z_factory(df)\n", - "\n", - "row = df[(df.x == 5) & (df.y == 7)].iloc[0]\n", - "z(x(row), y(row))\n", - "\n", - "xs = sorted(df.x.unique())\n", - "ys = sorted(df.y.unique())\n", - "zs = [[z(_x, _y) for _y in ys] for _x in xs]" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.plotly.v1+json": { - "config": { - "plotlyServerURL": "https://plot.ly" - }, - "data": [ { - "contours": { - "z": { - "highlightcolor": "limegreen", - "project": { - "z": true - }, - "show": true, - "usecolormap": true - } - }, - "type": "surface", - "x": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19 - ], - "y": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19 - ], - "z": [ - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 1000000, - 2000000, - 2000000, - 2000000, - 1000000, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 4000000, - 6000000, - 5000000, - 6000000, - 4000000, - 2000000, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 1000000, - 4000000, - 0, - 8000000, - 8000000, - 8000000, - 7000000, - 4000000, - 1000000, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 2000000, - 6000000, - 8000000, - 0, - 9000000, - 10000000, - 8000000, - 6000000, - 2000000, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 2000000, - 5000000, - 8000000, - 9000000, - 0, - 9000000, - 8000000, - 5000000, - 2000000, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 2000000, - 6000000, - 8000000, - 10000000, - 9000000, - 0, - 8000000, - 6000000, - 2000000, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 1000000, - 4000000, - 7000000, - 8000000, - 8000000, - 8000000, - 0, - 4000000, - 1000000, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 2000000, - 4000000, - 6000000, - 5000000, - 6000000, - 4000000, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 1000000, - 2000000, - 2000000, - 2000000, - 1000000, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ] - ] - } - ], - "layout": { - "autosize": false, - "height": 600, - "margin": { - "b": 65, - "l": 65, - "r": 50, - "t": 90 + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "X, Y, i3d = inspectors_3D_from_dryruns(21, 21)" + ] }, - "scene": { - "camera": { - "eye": { - "x": 1.87, - "y": 0.88, - "z": -0.64 - } - }, - "zaxis": { - "ticksuffix": "µA", - "title": { - "text": "prize (µA)" - } - } + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "contours": { + "z": { + "highlightcolor": "limegreen", + "project": { + "z": true + }, + "show": true, + "usecolormap": true + } + }, + "type": "surface", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "y": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "z": [ + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 1000000, + 2000000, + 2000000, + 2000000, + 1000000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 2000000, + 4000000, + 6000000, + 5000000, + 6000000, + 4000000, + 2000000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 1000000, + 4000000, + 7000000, + 8000000, + 8000000, + 8000000, + 7000000, + 4000000, + 1000000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 2000000, + 6000000, + 8000000, + 10000000, + 9000000, + 10000000, + 8000000, + 6000000, + 2000000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 2000000, + 5000000, + 8000000, + 9000000, + 9000000, + 9000000, + 8000000, + 5000000, + 2000000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 2000000, + 6000000, + 8000000, + 10000000, + 9000000, + 10000000, + 8000000, + 6000000, + 2000000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 1000000, + 4000000, + 7000000, + 8000000, + 8000000, + 8000000, + 7000000, + 4000000, + 1000000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 2000000, + 4000000, + 6000000, + 5000000, + 6000000, + 4000000, + 2000000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 1000000, + 2000000, + 2000000, + 2000000, + 1000000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + ] + } + ], + "layout": { + "autosize": false, + "height": 600, + "margin": { + "b": 65, + "l": 65, + "r": 50, + "t": 90 + }, + "scene": { + "camera": { + "eye": { + "x": 1.87, + "y": 0.88, + "z": -0.64 + } + }, + "zaxis": { + "ticksuffix": "µA", + "title": { + "text": "prize (µA)" + } + } + }, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "title": { + "text": "Scratch Slot #3" + }, + "width": 600 + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "blackbox_plot(X, Y, [[inspector.final_scratch().get(3,0) for inspector in row] for row in i3d], title=\"Scratch Slot #3\")" + ] }, - "template": { - "data": { - "bar": [ - { - "error_x": { - "color": "#2a3f5f" - }, - "error_y": { - "color": "#2a3f5f" - }, - "marker": { - "line": { - "color": "#E5ECF6", - "width": 0.5 - }, - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "bar" - } - ], - "barpolar": [ - { - "marker": { - "line": { - "color": "#E5ECF6", - "width": 0.5 - }, - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "barpolar" - } - ], - "carpet": [ - { - "aaxis": { - "endlinecolor": "#2a3f5f", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "#2a3f5f" - }, - "baxis": { - "endlinecolor": "#2a3f5f", - "gridcolor": "white", - "linecolor": "white", - "minorgridcolor": "white", - "startlinecolor": "#2a3f5f" - }, - "type": "carpet" - } - ], - "choropleth": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "choropleth" - } - ], - "contour": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "contour" - } - ], - "contourcarpet": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "contourcarpet" - } - ], - "heatmap": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "heatmap" - } - ], - "heatmapgl": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "heatmapgl" - } - ], - "histogram": [ - { - "marker": { - "pattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - } - }, - "type": "histogram" - } - ], - "histogram2d": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "histogram2d" - } - ], - "histogram2dcontour": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "histogram2dcontour" - } - ], - "mesh3d": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "type": "mesh3d" - } - ], - "parcoords": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "parcoords" - } - ], - "pie": [ - { - "automargin": true, - "type": "pie" - } - ], - "scatter": [ - { - "fillpattern": { - "fillmode": "overlay", - "size": 10, - "solidity": 0.2 - }, - "type": "scatter" - } - ], - "scatter3d": [ - { - "line": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatter3d" - } - ], - "scattercarpet": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattercarpet" - } - ], - "scattergeo": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattergeo" - } - ], - "scattergl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattergl" - } - ], - "scattermapbox": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scattermapbox" - } - ], - "scatterpolar": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterpolar" - } - ], - "scatterpolargl": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterpolargl" - } - ], - "scatterternary": [ - { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "type": "scatterternary" - } - ], - "surface": [ - { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - }, - "colorscale": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" - ] - ], - "type": "surface" - } - ], - "table": [ - { - "cells": { - "fill": { - "color": "#EBF0F8" - }, - "line": { - "color": "white" - } - }, - "header": { - "fill": { - "color": "#C8D4E3" - }, - "line": { - "color": "white" - } - }, - "type": "table" - } - ] - }, - "layout": { - "annotationdefaults": { - "arrowcolor": "#2a3f5f", - "arrowhead": 0, - "arrowwidth": 1 - }, - "autotypenumbers": "strict", - "coloraxis": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } - }, - "colorscale": { - "diverging": [ - [ - 0, - "#8e0152" - ], - [ - 0.1, - "#c51b7d" - ], - [ - 0.2, - "#de77ae" - ], - [ - 0.3, - "#f1b6da" - ], - [ - 0.4, - "#fde0ef" - ], - [ - 0.5, - "#f7f7f7" - ], - [ - 0.6, - "#e6f5d0" - ], - [ - 0.7, - "#b8e186" - ], - [ - 0.8, - "#7fbc41" - ], - [ - 0.9, - "#4d9221" - ], - [ - 1, - "#276419" + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "contours": { + "z": { + "highlightcolor": "limegreen", + "project": { + "z": true + }, + "show": true, + "usecolormap": true + } + }, + "type": "surface", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "y": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "z": [ + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ], + [ + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4 + ] + ] + } + ], + "layout": { + "autosize": false, + "height": 600, + "margin": { + "b": 65, + "l": 65, + "r": 50, + "t": 90 + }, + "scene": { + "camera": { + "eye": { + "x": 1.87, + "y": 0.88, + "z": -0.64 + } + }, + "zaxis": { + "title": { + "text": "Max Stack Height" + } + } + }, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "title": { + "text": "Max Stack Height Analysis" + }, + "width": 600 + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "blackbox_plot(X, Y, [[inspector.max_stack_height() for inspector in row] for row in i3d], ztick=None, ztitle=\"Max Stack Height\", title=\"Max Stack Height Analysis\")" ] - ], - "sequential": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "contours": { + "z": { + "highlightcolor": "limegreen", + "project": { + "z": true + }, + "show": true, + "usecolormap": true + } + }, + "type": "surface", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "y": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "z": [ + [ + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35 + ], + [ + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24 + ], + [ + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15 + ], + [ + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8 + ], + [ + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3 + ], + [ + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8, + 8 + ], + [ + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15, + 15 + ], + [ + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24 + ], + [ + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35, + 35 + ], + [ + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 48, + 48 + ], + [ + 63, + 63, + 63, + 63, + 63, + 63, + 63, + 63, + 63, + 63, + 63, + 63, + 63, + 63, + 63, + 63, + 63, + 63, + 63, + 63, + 63 + ], + [ + 80, + 80, + 80, + 80, + 80, + 80, + 80, + 80, + 80, + 80, + 80, + 80, + 80, + 80, + 80, + 80, + 80, + 80, + 80, + 80, + 80 + ], + [ + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99, + 99 + ], + [ + 120, + 120, + 120, + 120, + 120, + 120, + 120, + 120, + 120, + 120, + 120, + 120, + 120, + 120, + 120, + 120, + 120, + 120, + 120, + 120, + 120 + ], + [ + 143, + 143, + 143, + 143, + 143, + 143, + 143, + 143, + 143, + 143, + 143, + 143, + 143, + 143, + 143, + 143, + 143, + 143, + 143, + 143, + 143 + ], + [ + 168, + 168, + 168, + 168, + 168, + 168, + 168, + 168, + 168, + 168, + 168, + 168, + 168, + 168, + 168, + 168, + 168, + 168, + 168, + 168, + 168 + ], + [ + 195, + 195, + 195, + 195, + 195, + 195, + 195, + 195, + 195, + 195, + 195, + 195, + 195, + 195, + 195, + 195, + 195, + 195, + 195, + 195, + 195 + ] + ] + } + ], + "layout": { + "autosize": false, + "height": 600, + "margin": { + "b": 65, + "l": 65, + "r": 50, + "t": 90 + }, + "scene": { + "camera": { + "eye": { + "x": 1.87, + "y": 0.88, + "z": -0.64 + } + }, + "zaxis": { + "title": { + "text": "Scratch Slot 0" + } + } + }, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "title": { + "text": "Slot 0 Analysis" + }, + "width": 600 + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "blackbox_plot(\n", + " X, \n", + " Y, \n", + " [[inspector.final_scratch().get(0,0) for inspector in row] for row in i3d], \n", + " ztick=None, \n", + " ztitle=\"Scratch Slot 0\",\n", + " title=\"Slot 0 Analysis\"\n", + ")" ] - ], - "sequentialminus": [ - [ - 0, - "#0d0887" - ], - [ - 0.1111111111111111, - "#46039f" - ], - [ - 0.2222222222222222, - "#7201a8" - ], - [ - 0.3333333333333333, - "#9c179e" - ], - [ - 0.4444444444444444, - "#bd3786" - ], - [ - 0.5555555555555556, - "#d8576b" - ], - [ - 0.6666666666666666, - "#ed7953" - ], - [ - 0.7777777777777778, - "#fb9f3a" - ], - [ - 0.8888888888888888, - "#fdca26" - ], - [ - 1, - "#f0f921" + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "contours": { + "z": { + "highlightcolor": "limegreen", + "project": { + "z": true + }, + "show": true, + "usecolormap": true + } + }, + "type": "surface", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "y": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "z": [ + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 1, + 1, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 1, + 1, + 1, + 0, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 0, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + ] + } + ], + "layout": { + "autosize": false, + "height": 600, + "margin": { + "b": 65, + "l": 65, + "r": 50, + "t": 90 + }, + "scene": { + "camera": { + "eye": { + "x": 1.87, + "y": 0.88, + "z": -0.64 + } + }, + "zaxis": { + "title": { + "text": "final stack top" + } + } + }, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "title": { + "text": "Stack Top Analysis" + }, + "width": 600 + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "blackbox_plot(X, Y, [[inspector.stack_top() for inspector in row] for row in i3d], ztick=None, ztitle=\"final stack top\", title=\"Stack Top Analysis\")" ] - ] - }, - "colorway": [ - "#636efa", - "#EF553B", - "#00cc96", - "#ab63fa", - "#FFA15A", - "#19d3f3", - "#FF6692", - "#B6E880", - "#FF97FF", - "#FECB52" - ], - "font": { - "color": "#2a3f5f" - }, - "geo": { - "bgcolor": "white", - "lakecolor": "white", - "landcolor": "#E5ECF6", - "showlakes": true, - "showland": true, - "subunitcolor": "white" - }, - "hoverlabel": { - "align": "left" - }, - "hovermode": "closest", - "mapbox": { - "style": "light" - }, - "paper_bgcolor": "white", - "plot_bgcolor": "#E5ECF6", - "polar": { - "angularaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "bgcolor": "#E5ECF6", - "radialaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - } - }, - "scene": { - "xaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - }, - "yaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - }, - "zaxis": { - "backgroundcolor": "#E5ECF6", - "gridcolor": "white", - "gridwidth": 2, - "linecolor": "white", - "showbackground": true, - "ticks": "", - "zerolinecolor": "white" - } - }, - "shapedefaults": { - "line": { - "color": "#2a3f5f" - } - }, - "ternary": { - "aaxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "baxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - }, - "bgcolor": "#E5ECF6", - "caxis": { - "gridcolor": "white", - "linecolor": "white", - "ticks": "" - } - }, - "title": { - "x": 0.05 - }, - "xaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "ticks": "", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white", - "zerolinewidth": 2 - }, - "yaxis": { - "automargin": true, - "gridcolor": "white", - "linecolor": "white", - "ticks": "", - "title": { - "standoff": 15 - }, - "zerolinecolor": "white", - "zerolinewidth": 2 - } - } }, - "title": { - "text": "pymt txn analysis" + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Hackey Appendix" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "Ok... This is a hack that I came up with last minute for the demo... \n", + "But this could easily be done in a straightforward, non-hacky way (just build z directly from the dry runs)\n", + "\"\"\"\n", + "def x(row):\n", + " return row.x\n", + "\n", + "def y(row):\n", + " return row.y\n", + "\n", + "def z_factory(df, z_col=\"amt\"):\n", + " def z(_x, _y):\n", + " _rows = df[(df.x == _x) & (df.y == _y)]\n", + " assert len(_rows) == 1\n", + " return _rows.iloc[0][z_col]\n", + "\n", + " return z\n", + "\n", + "z = z_factory(df)\n", + "\n", + "row = df[(df.x == 5) & (df.y == 7)].iloc[0]\n", + "z(x(row), y(row))\n", + "\n", + "xs = sorted(df.x.unique())\n", + "ys = sorted(df.y.unique())\n", + "zs = [[z(_x, _y) for _y in ys] for _x in xs]" + ] }, - "width": 600 - } - } - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "blackbox_plot(xs, ys, zs)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "interpreter": { - "hash": "cc7b2a1767988fd8894055f999bc37e0cedcf372c09868088564c4af532681ed" - }, - "kernelspec": { - "display_name": "Python 3.10.2 ('py310-graviton': venv)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.4" - }, - "orig_nbformat": 4 - }, - "nbformat": 4, - "nbformat_minor": 2 -} + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "contours": { + "z": { + "highlightcolor": "limegreen", + "project": { + "z": true + }, + "show": true, + "usecolormap": true + } + }, + "type": "surface", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19 + ], + "y": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19 + ], + "z": [ + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 1000000, + 2000000, + 2000000, + 2000000, + 1000000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 4000000, + 6000000, + 5000000, + 6000000, + 4000000, + 2000000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 1000000, + 4000000, + 0, + 8000000, + 8000000, + 8000000, + 7000000, + 4000000, + 1000000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 2000000, + 6000000, + 8000000, + 0, + 9000000, + 10000000, + 8000000, + 6000000, + 2000000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 2000000, + 5000000, + 8000000, + 9000000, + 0, + 9000000, + 8000000, + 5000000, + 2000000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 2000000, + 6000000, + 8000000, + 10000000, + 9000000, + 0, + 8000000, + 6000000, + 2000000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 1000000, + 4000000, + 7000000, + 8000000, + 8000000, + 8000000, + 0, + 4000000, + 1000000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 2000000, + 4000000, + 6000000, + 5000000, + 6000000, + 4000000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 1000000, + 2000000, + 2000000, + 2000000, + 1000000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + ] + } + ], + "layout": { + "autosize": false, + "height": 600, + "margin": { + "b": 65, + "l": 65, + "r": 50, + "t": 90 + }, + "scene": { + "camera": { + "eye": { + "x": 1.87, + "y": 0.88, + "z": -0.64 + } + }, + "zaxis": { + "ticksuffix": "µA", + "title": { + "text": "prize (µA)" + } + } + }, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "title": { + "text": "pymt txn analysis" + }, + "width": 600 + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "blackbox_plot(xs, ys, zs)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.1" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "a77191ba92f2943d1a774acb6c6c3997b8927cbdda28e3b65c414b7e4100969f" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} \ No newline at end of file diff --git a/setup.py b/setup.py index 8c6fc85f..d8a8a114 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setup( name="graviton", - version="0.7.1", + version="0.8.0", url="https://github.com/algorand/graviton", description="verify your TEAL program by experiment and observation", long_description=long_description, diff --git a/tests/integration/abi_test.py b/tests/integration/abi_test.py index 20923191..264b4a6c 100644 --- a/tests/integration/abi_test.py +++ b/tests/integration/abi_test.py @@ -24,14 +24,11 @@ from algosdk import abi from algosdk.transaction import OnComplete -from graviton.blackbox import ( - ABIContractExecutor, - DryRunExecutor as DRE, - DryRunEncoder, -) -from graviton.inspector import DryRunProperty as DRProp from graviton.abi_strategy import RandomABIStrategy, RandomABIStrategyHalfSized +from graviton.blackbox import ABIContractExecutor, DryRunExecutor as DRE, DryRunEncoder +from graviton.inspector import DryRunProperty as DRProp from graviton.invariant import Invariant +from graviton.models import ExecutionMode from tests.clients import get_algod @@ -93,12 +90,12 @@ def test_dynamic_array_sum(): algod = get_algod() args = ([1, 2, 3, 4, 5],) - inspector = DRE.dryrun_app( + inspector = DRE( algod, + ExecutionMode.Application, DYNAMIC_ARRAY_SUM_TEAL, - args, abi_method_signature="abi_sum(uint64[])uint64", - ) + ).run_one(args) # with default config: assert inspector.abi_type assert inspector.suppress_abi is False @@ -196,13 +193,13 @@ def test_roundtrip_abi_strategy(roundtrip_app): with open(filename) as f: roundtrip_teal = f.read() - inspector = DRE.dryrun_app( + inspector = DRE( algod, + ExecutionMode.Application, roundtrip_teal, - args, abi_method_signature=method_sig, omit_method_selector=True, - ) + ).run_one(args) cost = inspector.cost() passed = inspector.passed() diff --git a/tests/integration/blackbox_test.py b/tests/integration/blackbox_test.py index da0dbc2f..ce1bc8a7 100644 --- a/tests/integration/blackbox_test.py +++ b/tests/integration/blackbox_test.py @@ -9,7 +9,7 @@ from graviton.blackbox import ( DryRunEncoder as Encoder, DryRunExecutor as Executor, - ExecutionMode, + DryRunTransactionParams as TxParams, ) from graviton.inspector import ( DryRunInspector as Inspector, @@ -17,7 +17,7 @@ mode_has_property, ) from graviton.invariant import Invariant, InvariantType -from graviton.models import PyTypes +from graviton.models import ExecutionMode, PyTypes from tests.clients import get_algod @@ -86,17 +86,17 @@ def test_singleton_invariants(): ) x = 9 - args = [x] + args = (x,) app_res, app_log_res = list( map( - lambda teal: Executor.dryrun_app(algod, teal, args), + lambda teal: Executor(algod, ExecutionMode.Application, teal).run_one(args), [teal_app, teal_app_log], ) ) lsig_res, bad_lsig_res = list( map( - lambda teal: Executor.dryrun_logicsig(algod, teal, args), + lambda teal: Executor(algod, ExecutionMode.Signature, teal).run_one(args), [teal_lsig, bad_teal_lsig], ) ) @@ -422,7 +422,9 @@ def test_app_with_report(filebase: str): ) # 2. Run the requests to obtain sequence of Dryrun responses: - dryrun_results = Executor.dryrun_app_on_sequence(algod, teal, inputs) + dryrun_results = Executor(algod, ExecutionMode.Application, teal).run_sequence( + inputs + ) # 3. Generate statistical report of all the runs: csvpath = path / f"{filebase}.csv" with open(csvpath, "w") as f: @@ -483,8 +485,9 @@ def test_app_itxn_with_report(): amount_without_pending_rewards=10500000, ) ] - dryrun_results = Executor.dryrun_app_on_sequence( - algod, teal, inputs, dryrun_accounts=accounts + dryrun_results = Executor(algod, ExecutionMode.Application, teal).run_sequence( + inputs, + txn_params=TxParams.for_app(dryrun_accounts=accounts), ) # 3. Generate statistical report of all the runs: @@ -522,7 +525,9 @@ def test_app_itxn_with_report(): }, } - dryrun_results = Executor.dryrun_app_on_sequence(algod, teal, inputs) + dryrun_results = Executor(algod, ExecutionMode.Application, teal).run_sequence( + inputs + ) inputs = scenario_failure["inputs"] invariants = scenario_failure["invariants"] @@ -718,7 +723,7 @@ def test_logicsig_with_report(filebase: str): ) # 2. Run the requests to obtain sequence of Dryrun resonses: - dryrun_results = Executor.dryrun_logicsig_on_sequence(algod, teal, inputs) + dryrun_results = Executor(algod, ExecutionMode.Signature, teal).run_sequence(inputs) # 3. Generate statistical report of all the runs: csvpath = path / f"{filebase}.csv" diff --git a/tests/integration/doc_examples_test.py b/tests/integration/doc_examples_test.py index fb51e705..ae8fb8ee 100644 --- a/tests/integration/doc_examples_test.py +++ b/tests/integration/doc_examples_test.py @@ -1,5 +1,4 @@ import pytest -import re teal = """#pragma version 6 arg 0 @@ -18,12 +17,13 @@ def test_step4(): from graviton.blackbox import DryRunExecutor + from graviton.models import ExecutionMode from tests.clients import get_algod algod = get_algod() x = 9 args = (x,) - inspector = DryRunExecutor.dryrun_logicsig(algod, teal, args) + inspector = DryRunExecutor(algod, ExecutionMode.Signature, teal).run_one(args) assert inspector.status() == "PASS" assert inspector.stack_top() == x**2 @@ -38,12 +38,13 @@ def test_step4(): def test_step5(): from graviton.blackbox import DryRunExecutor + from graviton.models import ExecutionMode from tests.clients import get_algod algod = get_algod() x = 2 args = (x,) - inspector = DryRunExecutor.dryrun_logicsig(algod, teal, args) + inspector = DryRunExecutor(algod, ExecutionMode.Signature, teal).run_one(args) # This one's ok expected, actual = "PASS", inspector.status() @@ -59,68 +60,68 @@ def test_step5(): assert expected == actual, inspector.report( args, f"expected {expected} but got {actual}" ) - expected = """AssertionError: -=============== -<<<<<<<<<<>>>>>>>>>> -=============== + expected = """=============== + <<<<<<<<<<>>>>>>>>>> + =============== App Trace: - step | PC# | L# | Teal | Scratch | Stack ---------+-------+------+-------------------+-----------+---------------------- - 1 | 1 | 1 | #pragma version 6 | | [] - 2 | 2 | 2 | arg_0 | | [0x0000000000000002] - 3 | 3 | 3 | btoi | | [2] - 4 | 7 | 6 | label1: | | [2] - 5 | 9 | 7 | store 0 | 0->2 | [] - 6 | 11 | 8 | load 0 | | [2] - 7 | 13 | 9 | pushint 2 | | [2, 2] - 8 | 14 | 10 | exp | | [4] - 9 | 6 | 4 | callsub label1 | | [4] - 10 | 15 | 11 | retsub | | [4] -=============== -MODE: ExecutionMode.Signature -TOTAL COST: None -=============== -FINAL MESSAGE: PASS -=============== -Messages: ['PASS'] -Logs: [] -=============== ------BlackBoxResult(steps_executed=10)----- -TOTAL STEPS: 10 -FINAL STACK: [4] -FINAL STACK TOP: 4 -MAX STACK HEIGHT: 2 -FINAL SCRATCH: {0: 2} -SLOTS USED: [0] -FINAL AS ROW: {'steps': 10, ' top_of_stack': 4, 'max_stack_height': 2, 's@000': 2} -=============== -Global Delta: -[] -=============== -Local Delta: -[] -=============== -TXN AS ROW: {' Run': 0, ' cost': None, ' last_log': '`None', ' final_message': 'PASS', ' Status': 'PASS', 'steps': 10, ' top_of_stack': 4, 'max_stack_height': 2, 's@000': 2, 'Arg_00': 2} -=============== -<<<<<<<<<<>>>>>>>>>> -=============== -assert 8 == 4 -""" - - def remove_whitespace(s): - return re.sub(r"\s+", "", s) - - assert remove_whitespace(expected) == remove_whitespace(ae.exconly()) + step | PC# | L# | Teal | Scratch | Stack + --------+-------+------+-------------------+-----------+---------------------- + 1 | 1 | 1 | #pragma version 6 | | [] + 2 | 2 | 2 | arg_0 | | [0x0000000000000002] + 3 | 3 | 3 | btoi | | [2] + 4 | 7 | 6 | label1: | | [2] + 5 | 9 | 7 | store 0 | 0->2 | [] + 6 | 11 | 8 | load 0 | | [2] + 7 | 13 | 9 | pushint 2 | | [2, 2] + 8 | 14 | 10 | exp | | [4] + 9 | 6 | 4 | callsub label1 | | [4] + 10 | 15 | 11 | retsub | | [4] + =============== + MODE: ExecutionMode.Signature + TOTAL COST: None + =============== + FINAL MESSAGE: PASS + =============== + Messages: ['PASS'] + Logs: [] + =============== + -----BlackBoxResult(steps_executed=10)----- + TOTAL STEPS: 10 + FINAL STACK: [4] + FINAL STACK TOP: 4 + MAX STACK HEIGHT: 2 + FINAL SCRATCH: {0: 2} + SLOTS USED: [0] + FINAL AS ROW: {'steps': 10, ' top_of_stack': 4, 'max_stack_height': 2, 's@000': 2} + =============== + Global Delta: + [] + =============== + Local Delta: + [] + =============== + TXN AS ROW: {' Run': 0, ' budget_added': None, ' budget_consumed': None, ' cost': None, ' last_log': '`None', ' final_message': 'PASS', ' Status': 'PASS', 'steps': 10, ' top_of_stack': 4, 'max_stack_height': 2, 's@000': 2, 'Arg_00': 2} + =============== + <<<<<<<<<<>>>>>>>>>> + =============== + +assert 8 == 4""" # noqa: W293 + + actual = str(ae.value) + assert expected == actual, actual def test_step6_and_7(): from graviton.blackbox import DryRunExecutor + from graviton.models import ExecutionMode from graviton.inspector import DryRunInspector from tests.clients import get_algod algod = get_algod() inputs = [(x,) for x in range(16)] - run_results = DryRunExecutor.dryrun_logicsig_on_sequence(algod, teal, inputs) + run_results = DryRunExecutor(algod, ExecutionMode.Signature, teal).run_sequence( + inputs + ) csv = DryRunInspector.csv_report(inputs, run_results) print(csv) @@ -135,11 +136,14 @@ def test_step6_and_7(): def test_step8(): from graviton.blackbox import DryRunExecutor + from graviton.models import ExecutionMode from tests.clients import get_algod algod = get_algod() inputs = [(x,) for x in range(101)] - dryrun_results = DryRunExecutor.dryrun_logicsig_on_sequence(algod, teal, inputs) + dryrun_results = DryRunExecutor(algod, ExecutionMode.Signature, teal).run_sequence( + inputs + ) for i, inspector in enumerate(dryrun_results): args = inputs[i] x = args[0] @@ -153,6 +157,7 @@ def test_step9(): from graviton.blackbox import DryRunExecutor from graviton.inspector import DryRunProperty as DRProp from graviton.invariant import Invariant + from graviton.models import ExecutionMode from tests.clients import get_algod algod = get_algod() @@ -173,7 +178,9 @@ def test_step9(): assert invariants and isinstance(invariants, dict) # Execute the dry runs and obtain sequence of DryRunInspectors: - inspectors = DryRunExecutor.dryrun_logicsig_on_sequence(algod, teal, inputs) + inspectors = DryRunExecutor(algod, ExecutionMode.Signature, teal).run_sequence( + inputs + ) # Invariant assertions on sequence: for dr_property, invariant in invariants.items(): @@ -185,6 +192,7 @@ def test_exercises(exercise): from graviton.blackbox import DryRunExecutor from graviton.inspector import DryRunProperty as DRProp from graviton.invariant import Invariant + from graviton.models import ExecutionMode from tests.clients import get_algod algod = get_algod() @@ -210,7 +218,9 @@ def test_exercises(exercise): assert invariants and isinstance(invariants, dict) # Execute the dry runs and obtain sequence of DryRunInspectors: - inspectors = DryRunExecutor.dryrun_logicsig_on_sequence(algod, teal, inputs) + inspectors = DryRunExecutor(algod, ExecutionMode.Signature, teal).run_sequence( + inputs + ) # Invariant assertions on sequence: for dr_property, invariant in invariants.items(): diff --git a/tests/integration/identical_test.py b/tests/integration/identical_test.py index 8f707a77..b6f994c7 100644 --- a/tests/integration/identical_test.py +++ b/tests/integration/identical_test.py @@ -5,6 +5,7 @@ from graviton.blackbox import DryRunExecutor as DRExecutor from graviton.inspector import DryRunProperty as DRProp from graviton.invariant import Invariant, PredicateKind +from graviton.models import ExecutionMode from tests.clients import get_algod @@ -118,9 +119,15 @@ @pytest.mark.parametrize("teal_method1, teal_method2, inputs, predicates", COPACETIC) def test_identical_functions(teal_method1, teal_method2, inputs, predicates): algod = get_algod() - inspectors1, inspectors2 = DRExecutor.dryrun_app_pair_on_sequence( - algod, teal_method1, teal_method2, inputs + teal1, meth1 = teal_method1 + teal2, meth2 = teal_method2 + dre1 = DRExecutor( + algod, ExecutionMode.Application, teal1, abi_method_signature=meth1 ) + dre2 = DRExecutor( + algod, ExecutionMode.Application, teal2, abi_method_signature=meth2 + ) + inspectors1, inspectors2 = DRExecutor.multi_exec([dre1, dre2], inputs) Invariant.full_validation( predicates, inspectors=inspectors1, @@ -131,9 +138,17 @@ def test_identical_functions(teal_method1, teal_method2, inputs, predicates): def test_non_identical(): algod = get_algod() - square_inspectors, square_p1_inspectors = DRExecutor.dryrun_app_pair_on_sequence( - algod, square, square_p1, ten + + teal1, meth1 = square + teal2, meth2 = square_p1 + + dre1 = DRExecutor( + algod, ExecutionMode.Application, teal1, abi_method_signature=meth1 + ) + dre2 = DRExecutor( + algod, ExecutionMode.Application, teal2, abi_method_signature=meth2 ) + square_inspectors, square_p1_inspectors = DRExecutor.multi_exec([dre1, dre2], ten) square_predicates = { DRProp.lastLog: lambda args: args[1] ** 2, diff --git a/tests/integration/lsig_test.py b/tests/integration/lsig_test.py index 714bc9b3..3d2b82f2 100644 --- a/tests/integration/lsig_test.py +++ b/tests/integration/lsig_test.py @@ -8,12 +8,17 @@ from itertools import product from pathlib import Path +from typing import cast import pytest -from graviton.blackbox import DryRunExecutor as Executor +from graviton.blackbox import ( + DryRunExecutor as Executor, + DryRunTransactionParams as TxParams, +) from graviton.inspector import DryRunInspector as Inspector +from graviton.models import ExecutionMode from tests.clients import get_algod @@ -32,7 +37,7 @@ def test_factorizer_game_report(): algod = get_algod() - dryrun_results = Executor.dryrun_logicsig_on_sequence(algod, teal, inputs) + dryrun_results = Executor(algod, ExecutionMode.Signature, teal).run_sequence(inputs) csvpath = path / f"{filebase}.csv" with open(csvpath, "w") as f: @@ -46,12 +51,13 @@ def test_logic_sig(): int 0x31 == """ - insp_no_args = Executor.dryrun_logicsig(ALGOD, source, []) - assert "cannot load arg[0] of 0" in insp_no_args.error_message() + executor = Executor(ALGOD, ExecutionMode.Signature, source) + insp_no_args = executor.run_one([]) + assert "cannot load arg[0] of 0" in cast(str, insp_no_args.error_message()) assert insp_no_args.rejected() # providing the string arg "1" results is encoded to 0x31, and hence eval passes: - insp_args_1_2 = Executor.dryrun_logicsig(ALGOD, source, ["1", "2"]) + insp_args_1_2 = executor.run_one(("1", "2")) assert insp_args_1_2.passed() @@ -75,7 +81,7 @@ def payment_amount(p, q): @pytest.mark.parametrize("p, q", product(range(20), range(20))) def test_factorizer_game_3_stateless(p, q): args = (p, q) - inspector = Executor.dryrun_logicsig(ALGOD, FACTORIZER_TEAL, args) + inspector = Executor(ALGOD, ExecutionMode.Signature, FACTORIZER_TEAL).run_one(args) slots = inspector.final_scratch() assert slots.get(3, 0) == expected_prize_before_dupe_constraint( p, q @@ -86,7 +92,9 @@ def test_factorizer_game_3_stateless(p, q): def test_factorizer_game_4_payout(p, q): args = (p, q) eprize = expected_prize_before_dupe_constraint(p, q) - inspector = Executor.dryrun_logicsig(ALGOD, FACTORIZER_TEAL, args, amt=eprize) + inspector = Executor(ALGOD, ExecutionMode.Signature, FACTORIZER_TEAL).run_one( + args, txn_params=TxParams(amt=eprize) + ) assert inspector.final_scratch().get(3, 0) == eprize, inspector.report( args, f"final scratch slot #3 {p, q}" ) @@ -108,10 +116,11 @@ def test_factorizer_report_with_pymnt(): algod = get_algod() dryrun_results, txns = [], [] + executor = Executor(algod, ExecutionMode.Signature, teal) for args, amt in zip(inputs, amts): txn = {"amt": amt} txns.append(txn) - dryrun_results.append(Executor.dryrun_logicsig(algod, teal, args, **txn)) + dryrun_results.append(executor.run_one(args, txn_params=TxParams(**txn))) csvpath = path / f"{filebase}.csv" with open(csvpath, "w") as f: diff --git a/tests/unit/encode_test.py b/tests/unit/encode_test.py index d452d59f..ee525654 100644 --- a/tests/unit/encode_test.py +++ b/tests/unit/encode_test.py @@ -1,7 +1,12 @@ -from algosdk.abi import TupleType, BoolType, UintType, ArrayDynamicType import pytest +from unittest.mock import Mock + +from algosdk.abi import TupleType, BoolType, UintType, ArrayDynamicType +from algosdk.error import ABIEncodingError +from algosdk.v2client.algod import AlgodClient -from graviton.blackbox import DryRunEncoder +from graviton.blackbox import DryRunEncoder, DryRunExecutor +from graviton.models import ExecutionMode def test_encode_arg(): @@ -76,3 +81,183 @@ def test_encode_abi(): ae.value.args[0] == "problem encoding arg (['wrong', 'types', 'for', 'dynamic', 'int', 'array']) at index (0): can't handle arg [['wrong', 'types', 'for', 'dynamic', 'int', 'array']] of type and abi-type uint64[]: value wrong is not a non-negative int or is too big to fit in size 64" ) + + +NONSENSE = "not a valid signature" + + +@pytest.mark.parametrize("mode", ExecutionMode) +@pytest.mark.parametrize( + "abi_method_signature", + [None, "zero()void", "one(uint64)void", "oneOne(uint64)bool", NONSENSE], +) +@pytest.mark.parametrize("omit_method_selector", [False, True]) +@pytest.mark.parametrize("validation", [False, True]) +def test_executor_init(mode, abi_method_signature, omit_method_selector, validation): + if abi_method_signature == NONSENSE: + with pytest.raises(ABIEncodingError) as abiee: + DryRunExecutor( + algod := Mock(AlgodClient), + mode, + teal := "fake teal", + abi_method_signature=abi_method_signature, + omit_method_selector=omit_method_selector, + validation=validation, + ) + + assert ( + f"ABI method string has mismatched parentheses: {abi_method_signature}" + == str(abiee.value) + ) + return None + + sigless = abi_method_signature is None + void = (not sigless) and abi_method_signature.endswith("void") + dre = DryRunExecutor( + algod := Mock(AlgodClient), + mode, + teal := "fake teal", + abi_method_signature=abi_method_signature, + omit_method_selector=omit_method_selector, + validation=validation, + ) + + # simple WYSIWYG members: + assert dre.algod == algod + assert dre.mode == mode + assert dre.program == teal + assert dre.abi_method_signature == abi_method_signature + assert dre.omit_method_selector == omit_method_selector + assert dre.validation == validation + + assert dre.is_app == (mode == ExecutionMode.Application) + + # assert nullity first: + assert (dre.abi_argument_types is None) == sigless + assert (dre.abi_return_type is None) == sigless or void + assert (dre.method is None) == sigless + assert (dre.selector is None) == sigless + + # deeper assertions: + if not sigless: + assert dre.abi_argument_types == [a.type for a in dre.method.args] # type: ignore + if not void: + assert dre.abi_return_type == dre.method.returns.type # type: ignore + assert dre.method.get_signature() == abi_method_signature # type: ignore + assert dre.selector == dre.method.get_selector() # type: ignore + + return dre + + +@pytest.mark.parametrize("mode", ExecutionMode) +@pytest.mark.parametrize( + "abi_method_signature", + [None, "zero()void", "one(uint64)void", "oneOne(uint64)bool"], +) +@pytest.mark.parametrize("omit_method_selector", [False, True]) +@pytest.mark.parametrize("validation", [False, True]) +@pytest.mark.parametrize( + "args", [tuple(), ("one",), (2,), ("three", 3), tuple([20] * 20)] +) # _run +def test_executor_prep( + mode, abi_method_signature, omit_method_selector, validation, args +): + dre = test_executor_init( + mode, abi_method_signature, omit_method_selector, validation + ) + assert dre + + args_below_max_num = len(args) <= 16 + aats_out_is_none = dre.abi_argument_types is None + + if aats_out_is_none: + assert dre.method is None + assert dre.selector is None + assert dre.abi_method_signature is None # so will skip _abi_adapter() call + assert dre.abi_argument_types is None # so will encode args without + + if not args_below_max_num: + with pytest.raises(AssertionError) as ae: + dre._executor_prep(args) + + assert ( + "for non-ABI app calls, there is no specification for encoding more than" + in str(ae.value) + ) + return + + encoded_args = DryRunEncoder.encode_args(args) + args_out, encoded_args_out = dre._executor_prep(args) + assert args_out == args + assert encoded_args_out == encoded_args + return + + assert dre.method + assert dre.selector + assert dre.abi_method_signature + assert isinstance(dre.abi_argument_types, list) + + argnum_same = len(args) == len(dre.abi_argument_types) + argnum_one_more = len(args) == len(dre.abi_argument_types) + 1 + arg0_is_selector = args and args[0] == dre.selector + + if validation: + if argnum_one_more: + if not arg0_is_selector: + with pytest.raises(AssertionError) as ae: + dre._executor_prep(args) + + assert "should have been the selector" in str(ae.value) + return + + if not (argnum_same or argnum_one_more): + with pytest.raises(AssertionError) as ae: + dre._executor_prep(args) + + assert "is incompatible with" in str(ae.value) + return + + try: + prefix = tuple() if omit_method_selector else ("blah",) + type_prefix = [] if omit_method_selector else [None] + encoded_args = DryRunEncoder.encode_args( + prefix + args, + type_prefix + dre.abi_argument_types, + validation=validation, + ) + except AssertionError as encode_args_ae: + with pytest.raises(AssertionError) as ae: + dre._executor_prep(args) + assert "problem encoding arg" in str(encode_args_ae) + assert str(ae.value) == str(encode_args_ae) + return + + args_out, encoded_args_out = dre._executor_prep(args) + argslen = len(args) + aolen = len(args_out) + arg_range = slice(aolen - argslen, aolen) + assert args_out[arg_range] == args + assert len(encoded_args_out) == len(encoded_args) + assert encoded_args_out[arg_range] == encoded_args[arg_range] + return + + assert validation is False + assert aats_out_is_none is False, "already considered this" + + start_from: int = 1 - int(omit_method_selector) + try: + encoded_args = DryRunEncoder.encode_args( + args[start_from:], + dre.abi_argument_types[start_from:], + validation=validation, + ) + except AssertionError as encode_args_ae: + with pytest.raises(AssertionError) as ae: + dre._executor_prep(args) + assert "problem encoding arg" in str(encode_args_ae) + assert "problem encoding arg" in str(ae) + return + + args_out, encoded_args_out = dre._executor_prep(args) + assert args_out[start_from:] == args[start_from:] + assert encoded_args_out[start_from:] == encoded_args