# Converting Neural Networks to VNNLib Format with VERONA: A Complete Guide

> Convert ONNX neural networks to VNNLib format with VERONA. Verify model robustness against adversarial attacks using modular property generators. Get the complete guide now.

- Repository: [ADA research/verona](https://github.com/ada-research/verona)
- Tags: how-to-guide
- Published: 2026-02-23

---

**VERONA converts ONNX neural networks into VNNLib property files using modular property generators, enabling formal verification of model robustness against adversarial perturbations.**

VERONA (from the `ada-research/verona` repository) provides a streamlined pipeline for converting neural network classifiers into VNNLib specifications. Converting neural networks to VNNLib format for VERONA involves three core components that transform an input image, its true label, and a perturbation radius into a formal property file ready for verification tools like Marabou or ERAN.

## The VERONA Conversion Architecture

The conversion pipeline relies on three interconnected components implemented in the VERONA source code:

- **Property generators** (`One2OnePropertyGenerator` and `One2AnyPropertyGenerator`) located in `ada_verona/verification_module/property_generator/` create the VNNLib logic
- **`VNNLibProperty`** dataclass in [`ada_verona/database/vnnlib_property.py`](https://github.com/ada-research/verona/blob/main/ada_verona/database/vnnlib_property.py) stores the generated specification
- **`VerificationContext`** in [`ada_verona/database/verification_context.py`](https://github.com/ada-research/verona/blob/main/ada_verona/database/verification_context.py) orchestrates file I/O and workflow management

This modular design allows you to take any ONNX-compatible network, specify an input data point and epsilon radius, and obtain a `.vnnlib` file that encodes the robustness property.

## Property Generators: Creating VNNLib Specifications

Property generators inherit from the abstract `PropertyGenerator` base class defined in [`ada_verona/verification_module/property_generator/property_generator.py`](https://github.com/ada-research/verona/blob/main/ada_verona/verification_module/property_generator/property_generator.py). Each generator implements the `create_vnnlib_property` method to produce platform-agnostic verification constraints.

### One2OnePropertyGenerator (Targeted Verification)

The `One2OnePropertyGenerator` creates properties that check whether a specific target class can outrank the true class under perturbation. Located in [`ada_verona/verification_module/property_generator/one2one_property_generator.py`](https://github.com/ada-research/verona/blob/main/ada_verona/verification_module/property_generator/one2one_property_generator.py), this generator produces assertions like:

```text
(assert (or (and (>= Y_target Y_true))))

```

Use this when verifying whether an adversary can force a specific misclassification (e.g., making the network classify a "7" as a "3").

### One2AnyPropertyGenerator (Untargeted Verification)

The `One2AnyPropertyGenerator` in [`ada_verona/verification_module/property_generator/one2any_property_generator.py`](https://github.com/ada-research/verona/blob/main/ada_verona/verification_module/property_generator/one2any_property_generator.py) creates untargeted properties that are violated when **any** non-true class beats the true class:

```text
(assert (or
    (and (>= Y_i Y_true))   ; for every i ≠ true class
))

```

Both generators perform the same preprocessing steps: clipping and normalizing the image with epsilon bounds, declaring input variables `X_i` and output variables `Y_i`, and adding bound constraints for each input dimension before appending the output condition.

## The VNNLibProperty Dataclass

Generated specifications are wrapped in the `VNNLibProperty` dataclass from [`ada_verona/database/vnnlib_property.py`](https://github.com/ada-research/verona/blob/main/ada_verona/database/vnnlib_property.py):

```python
@dataclass
class VNNLibProperty:
    name: str                # e.g. "property_3_0_01"

    content: str             # raw VNNLib script

    path: Path = None        # populated after saving to disk

```

This lightweight structure is serializable and database-friendly, allowing properties to persist across process boundaries without losing their raw VNNLib text content.

## Managing Workflows with VerificationContext

The `VerificationContext` class in [`ada_verona/database/verification_context.py`](https://github.com/ada-research/verona/blob/main/ada_verona/database/verification_context.py) bundles all verification metadata:

- `network`: An `ONNXNetwork` instance loaded from [`ada_verona/database/machine_learning_model/onnx_network.py`](https://github.com/ada-research/verona/blob/main/ada_verona/database/machine_learning_model/onnx_network.py)
- `data_point`: A labeled input from [`ada_verona/database/dataset/data_point.py`](https://github.com/ada-research/verona/blob/main/ada_verona/database/dataset/data_point.py)
- `tmp_path`: Temporary directory for VNNLib file output
- `property_generator`: The selected generator instance
- `save_epsilon_results`: Boolean flag for CSV logging

Key methods include `save_vnnlib_property(vnnlib_property)`, which writes the content to `<tmp>/<name>.vnnlib` and updates the path attribute, and `get_dict_for_epsilon_result()`, which merges context metadata with generator-specific dictionaries for epsilon-search logging.

The context is fully serializable via `to_dict()` and `from_dict()`, using dynamic imports to reconstruct the correct property generator class.

## Step-by-Step: Converting an ONNX Model to VNNLib

Follow these steps to convert a neural network to VNNLib format using VERONA.

### 1. Load the ONNX Network

```python
from pathlib import Path
from ada_verona.database.machine_learning_model.onnx_network import ONNXNetwork

network_path = Path("examples/example_experiment/data/networks/mnist-net_256x2.onnx")
network = ONNXNetwork(network_path)  # lazy loading; model read on demand

```

### 2. Prepare the Data Point

```python
from ada_verona.database.dataset.data_point import DataPoint
import numpy as np

image = np.load("examples/example_experiment/data/images/0.npy")  # shape (1, 28, 28)

image = image.astype(np.float32)
data_point = DataPoint(id="img_0", label=7, data=image)

```

### 3. Select a Property Generator

```python
from ada_verona.verification_module.property_generator.one2one_property_generator import One2OnePropertyGenerator

# Targeted: force misclassification to class 3

prop_gen = One2OnePropertyGenerator(target_class=3, number_classes=10)

# For untargeted verification, use:

# from ada_verona.verification_module.property_generator.one2any_property_generator import One2AnyPropertyGenerator

# prop_gen = One2AnyPropertyGenerator(number_classes=10)

```

### 4. Create the Verification Context

```python
from ada_verona.database.verification_context import VerificationContext

tmp_dir = Path("tmp_verification")
ctx = VerificationContext(
    network=network,
    data_point=data_point,
    tmp_path=tmp_dir,
    property_generator=prop_gen,
    save_epsilon_results=False
)

```

### 5. Generate and Save the Property

```python
epsilon = 0.02
vnnlib = prop_gen.create_vnnlib_property(
    image=data_point.data,
    image_class=data_point.label,
    epsilon=epsilon,
)

ctx.save_vnnlib_property(vnnlib)  # writes tmp_verification/property_7_0_02.vnnlib

print(f"VNNLib file saved at: {vnnlib.path}")

```

### 6. Verify with a VNNLib-Compatible Tool

```bash
marabou tmp_verification/property_7_0_02.vnnlib network.onnx

```

### 7. Serialize for Later Reuse (Optional)

```python
import json

ctx_dict = ctx.to_dict()
json.dump(ctx_dict, open("verif_config.json", "w"), indent=2)

# Reload later

loaded_ctx = VerificationContext.from_dict(json.load(open("verif_config.json")))

```

## Summary

- VERONA's conversion pipeline uses **property generators** to create VNNLib text, **`VNNLibProperty`** to package results, and **`VerificationContext`** to handle file operations and serialization
- **`One2OnePropertyGenerator`** creates targeted properties for specific misclassifications, while **`One2AnyPropertyGenerator`** handles untargeted robustness verification
- Generated `.vnnlib` files comply with the VNNLib specification and work with verifiers like Marabou and ERAN
- The entire verification configuration can be serialized and deserialized using the context's `to_dict()` and `from_dict()` methods

## Frequently Asked Questions

### What is the VNNLib format used for in VERONA?

VNNLib is a standardized format for encoding neural network verification properties using SMT-LIB syntax. In VERONA, it expresses constraints that define whether a neural network is robust to epsilon-bounded perturbations for a specific input, allowing external verification engines to formally prove or disprove safety properties.

### How does VERONA handle targeted versus untargeted verification?

VERONA handles targeted verification through `One2OnePropertyGenerator`, which generates properties asserting that a specific target class exceeds the true class score. For untargeted verification, `One2AnyPropertyGenerator` creates properties asserting that any non-true class can exceed the true class score, representing general adversarial robustness without specifying the destination class.

### Can I reuse verification configurations across different machines?

Yes. The `VerificationContext` class provides `to_dict()` and `from_dict()` methods that serialize the entire verification setup, including the network reference, data point, property generator type, and parameters. The deserialization process dynamically imports the correct generator class, making configurations fully portable.

### Which neural network formats does VERONA support for conversion?

VERONA primarily supports **ONNX** format through the `ONNXNetwork` wrapper in [`ada_verona/database/machine_learning_model/onnx_network.py`](https://github.com/ada-research/verona/blob/main/ada_verona/database/machine_learning_model/onnx_network.py). The system uses lazy loading and can convert ONNX models to PyTorch internally, but the VNNLib conversion pipeline accepts any network format that VERONA's `Network` abstract base class can wrap.