How-To-Guides
Verifying Properties
Simple Example
After installing one or more verifiers, here is how to use them to verify a property. Networks should be in the ONNX format, properties in the VNNLIB format.
from pathlib import Path
from result import Err, Ok
from autoverify.verifier import AbCrown
if __name__ == "__main__":
verifier = AbCrown()
network = Path("my_network.onnx")
prop = Path("my_property.vnnlib")
result = verifier.verify_property(network, prop)
if isinstance(result, Ok):
outcome = result.unwrap().result
print("Verification finished, result:", outcome)
elif isinstance(result, Err):
print("Error during verification:")
print(result.unwrap_err().stdout)
Running VNNCOMP Benchmarks
Auto-Verify supports reading benchmarks defined in VNNCOMP style, which are benchmarks with the following structure:
vnncomp2022
└── test_props
├── instances.csv
├── onnx
│ ├── test_nano.onnx
│ ├── test_sat.onnx
│ └── test_unsat.onnx
└── vnnlib
├── test_nano.vnnlib
└── test_prop.vnnlib
Where instances.csv
is a csv
file with 3 columns: network, property, timeout. For example, the test_props
directory contains the following 3 verification instaces:
onnx/test_sat.onnx,vnnlib/test_prop.vnnlib,60
onnx/test_unsat.onnx,vnnlib/test_prop.vnnlib,60
onnx/test_nano.onnx,vnnlib/test_nano.vnnlib,60
VNNCOMP Benchmarks can found at the following links: 2022, 2023. Make sure to unzip all files inside the benchmark after you have downloaded it.
Below is a code snippet that runs this benchmark. Note the Path
pointing to the benchmark location.
from pathlib import Path
from result import Err, Ok
from autoverify.util.instances import read_vnncomp_instances
from autoverify.verifier import Nnenum
test_props = read_vnncomp_instances(
"test_props", vnncomp_path=Path("../benchmark/vnncomp2022")
)
if __name__ == "__main__":
verifier = Nnenum()
for instance in test_props:
print(instance)
result = verifier.verify_instance(instance)
if isinstance(result, Ok):
outcome = result.unwrap().result
print("Verification finished, result:", outcome)
elif isinstance(result, Err):
print("Error during verification:")
print(result.unwrap_err().stdout)
Algorithm Configuration
Each of the verification tools comes equipped with a ConfigurationSpace
, which can be used to sample Configuration for a verification tool. For example:
from autoverify.verifier import Nnenum
if __name__ == "__main__":
verifier = Nnenum()
config = verifier.config_space.sample_configuration()
print(config)
SMAC Example
We can apply algorithm configuration techniques (or hyperparameter optimization) using SMAC. In the example below, we try to find a configuration for AB-CROWN on the first 10 instances of the mnist_fc
benchmark from VNNCOMP2022.
import sys
from pathlib import Path
from ConfigSpace import Configuration
from result import Err, Ok
from smac import AlgorithmConfigurationFacade, Scenario
from autoverify.util.instances import (
read_vnncomp_instances,
verification_instances_to_smac_instances,
)
from autoverify.util.smac import index_features
from autoverify.util.verification_instance import VerificationInstance
from autoverify.verifier import AbCrown
mnist = read_vnncomp_instances("mnist_fc", vnncomp_path=Path("../benchmark/vnncomp2022"))[:10]
verifier = AbCrown()
def target_function(config: Configuration, instance: str, seed: int):
seed += 1 # Mute unused var warnings; (cant rename to _)
verif_inst = VerificationInstance.from_str(instance)
result = verifier.verify_instance(verif_inst, config=config)
# SMAC handles exception by setting cost to `inf`
verification_result = result.unwrap_or_raise(Exception)
return float(verification_result.took)
if __name__ == "__main__":
cfg_space = verifier.config_space
name = verifier.name
instances = verification_instances_to_smac_instances(mnist)
scenario = Scenario(
cfg_space,
name="ab_tune",
instances=instances,
instance_features=index_features(instances),
walltime_limit=600,
output_directory=Path("ab_tune_out"),
n_trials=sys.maxsize, # Using walltime limit instead
)
smac = AlgorithmConfigurationFacade(
scenario, target_function, overwrite=True
)
inc = smac.optimize()
print(inc)
For more examples on how to use SMAC, please refer to the SMAC documentation.
Parallel Portfolios
Note
Custom verification tools are not yet supported for parallel portfolios.
Constructiong a Portfolio
Portfolios can be constructed as shown below. In this example, we try construct a portfolio using the Hydra
algorithm on the mnist_fc
benchmark from VNNCOMP2022. We include four verification tools that are able to be included and give the procedure a walltime limit of 24 hours.
from pathlib import Path
from autoverify.portfolio import Hydra, PortfolioScenario
from autoverify.util.instances import read_vnncomp_instances
benchmark = read_vnncomp_instances("mnist_fc", vnncomp_path=Path("../benchmark/vnncomp2022"))
if __name__ == "__main__":
pf_scenario = PortfolioScenario(
["nnenum", "abcrown", "ovalbab", "verinet"],
[
("nnenum", 0, 0),
("verinet", 0, 1),
("abcrown", 0, 1),
("ovalbab", 0, 1),
],
benchmark,
4,
(60 * 60 * 24) / 4,
alpha=0.9,
output_dir=Path("PF_mnist_fc"),
)
hydra = Hydra(pf_scenario)
pf = hydra.tune_portfolio()
pf.to_json(Path("mnist_fc_portfolio.json"))
Portfolios can be manually created as shown below. This example creates a portfolio of 2 verifiers (nnenum and AB-Crown), where nnenum is given 4 CPU cores and 0 GPUs and AB-Crown is given 4 cores and 1 GPU.
from autoverify.portfolio.portfolio import ConfiguredVerifier, Portfolio
from autoverify.util.verifiers import get_verifier_configspace
if __name__ == "__main__":
pf = Portfolio(
ConfiguredVerifier(
"nnenum",
get_verifier_configspace("nnenum").sample_configuration(),
(4, 0),
),
ConfiguredVerifier(
"abcrown",
get_verifier_configspace("abcrown").get_default_configuration(),
(4, 1),
),
)
print(pf)
Running a Portfolio
Portfolios can be read from a json
or by specifying the verification tools in Python code. Below is an example of how to run a portfolio in parallel on some instances. Lets take the portfolio we created in the previous example and run it on the same benchmark.
from pathlib import Path
from autoverify.portfolio import Portfolio, PortfolioRunner
from autoverify.util.instances import read_vnncomp_instances
benchmark = read_vnncomp_instances("mnist_fc", vnncomp_path=Path("../benchmark/vnncomp2022"))
if __name__ == "__main__":
mnist_pf = Portfolio.from_json(Path("mnist_fc_portfolio.json"))
pf_runner = PortfolioRunner(mnist_pf)
pf_runner.verify_instances(
benchmark,
out_csv=Path("PF_mnist_fc_results.csv"),
)