Skip to content

add DAG to model converter - #21

Closed
guanqin-123 wants to merge 1 commit into
SVF-tools:mainfrom
guanqin-123:fix
Closed

guanqin-123 wants to merge 1 commit into
SVF-tools:mainfrom
guanqin-123:fix

Conversation

@guanqin-123

@guanqin-123 guanqin-123 commented Jan 17, 2026 •

Copy link
Copy Markdown
Contributor
  • add DAG to torch2act, enable resNet-like networks that has DAG structure that uses torch.fx
  • processing the nodes should be in the topological order and process the merge points (so added necessary parameter for ADD operator)

Comment thread act/back_end/layer_schema.py
@yuleisui

Copy link
Copy Markdown
Collaborator

Describe what this pull request is and why we need this one.

Comment thread act/back_end/interval_tf/tf_cnn.py Outdated

# -------- Helper Functions --------

def _normalize_to_tuple(value: Union[int, Tuple[int, ...]], n: int = 2) -> Tuple[int, ...]:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is unclear to me why we need a tuple here. The conversation should be general enough for all types of NNs not only resnet. Also this method should be moved to layer_util if we really need this one.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This patch looks ad hoc. What is difference between previous recursively parse the torch model and dag one? Why do we need a dag parser?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the previous version, recursive parse doesnot support the skipping, especically with the two incoming edge on the operator concat. The predecessor is always one.
I could do a clean approach on graph-based parsing for once.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we do this in the front-end while building the torch model? Do we need to change the nn.sequential before getting to torch2act.py

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By now, I believe we have to change. nn.sequentail cannot fully preserve the information on ResNet. But for the onnx to torch loading, we are using the torch_model, so I think it is ok. It is well preserved the model information.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is your dag used to convert to nn.sequential? We need a more unified nn.model for both front and back ends then

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the new updates, we already unified to VerifiableModule(nn.Module) which wraps any nn.Module, not just Sequential. The old VerifiableModel(nn.Sequential) with index-based access has been deleted.

Both front-end (fuzzing) and back-end (verification) now use this unified VerifiableModule

Comment thread act/pipeline/verification/torch2act.py Outdated
Comment on lines +147 to +161
self.is_dag_model: bool = False # Flag for DAG mode
self.node_outputs: Dict[str, List[int]] = {} # node_name -> out_vars
self.node_shapes: Dict[str, Tuple[int, ...]] = {} # node_name -> shape
self.node_to_layer_id: Dict[str, int] = {} # node_name -> layer_id
self.graph_edges: Dict[str, List[str]] = {} # node_name -> [predecessor_node_names]
self.fx_graph: Optional[fx.Graph] = None # torch.fx graph if available
self.fx_modules: Dict[str, nn.Module] = {} # module_name -> module (from traced model)

# ONNX-specific DAG state (for onnx2pytorch models)
self.is_onnx_dag: bool = False # Flag for ONNX-based DAG mode
self.onnx_model: Optional[Any] = None # ONNX ModelProto
self.onnx_graph: Optional[Any] = None # ONNX GraphProto
self.onnx_mapping: Dict[str, Any] = {} # onnx2pytorch node mapping
self.onnx_modules: Dict[str, nn.Module] = {} # module_name -> module
self.onnx_output_to_node: Dict[str, Any] = {} # output_name -> ONNX node

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better not to create specific fields for DAG and onnx. It would be good to be done in the front-end.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. please check the updated one. We don't need that.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI failed, need to fix.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@guanqin-123
guanqin-123 force-pushed the fix branch 2 times, most recently from 9b7e7df to 19fa351 Compare January 18, 2026 00:39
Comment thread act/util/model_inference.py Outdated
with torch.no_grad():
output = model(input_tensor)
# Extract tensor if model returns dict (VerifiableModel)
# Extract tensor if model returns dict (VerifiableModule)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VerifiableModule => VerifiableModel
make sure all revert this name back.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, already replaced back to VerifiableModel

Comment thread act/back_end/interval_tf/tf_cnn.py Outdated
# -------- Helper Functions --------


def _infer_spatial_from_flat(flat_size: int, channels: int) -> Tuple[int, int]:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is unclear why we need to revert this flattening, as the tensors have already been flattened before the backend tfs stage. The core ACT net design was supposed to handle flat tensors.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the helper functions are in layer_util.py.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I believe, we don't need this.

Comment thread act/front_end/model_synthesis.py Outdated
output_spec: OutputSpec
) -> Tuple[VerifiableModel, WrapReport]:
output_spec: OutputSpec,
) -> Tuple[nn.Module, WrapReport]:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return should be VerifiableModel as the function name says.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, fixed.

Comment thread act/pipeline/verification/act2torch.py Outdated
model = VerifiableModel(*torch_layers)
model.eval() # Set to evaluation mode by default
# Build the core model as nn.Sequential
core_model = nn.Sequential(*torch_layers)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why nn.Sequential still the core model?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed, and now nn.Sequential is discard.

Comment thread ipynb/vnnlib_verify.ipynb Outdated
Comment on lines +26 to +28
"[ACT] Auto-detecting project root: /data1/guanqin/newACT/fix/ACT\n",
"[WARN] Gurobi license not found at: /data1/guanqin/newACT/fix/ACT/modules/gurobi/gurobi.lic\n",
"[INFO] Please ensure gurobi.lic is placed in: /data1/guanqin/newACT/fix/ACT/modules/gurobi\n",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove path information and use relative path.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment thread act/front_end/verifiable_model.py
Comment thread act/front_end/verifiable_model.py Outdated
return False, f"OUTPUT: Misclassified (pred={pred}, true={y_true})"
return True, f"OUTPUT: Spec kind {spec.kind} (not checked)"

def to_net(self):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to_net => to_act_net

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed.

Comment thread act/front_end/verifiable_model.py Outdated
self._net = self._build_net()
return self._net

def _build_net(self):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_build_net => _build_act_net

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed.

Comment thread act/pipeline/verification/torch2act.py Outdated
net.assert_last_is_validation()
return net

def _build_preds_succs_from_tracer(self) -> Tuple[Dict[int, List[int]], Dict[int, List[int]]]:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does tracer mean here? better to have the explicit and understandable name.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about _build_layer_graph() ?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where ModelTracer is defined? This function should return act Net?

Comment thread ipynb/vnnlib_fuzzer.ipynb Outdated
@@ -12,27 +12,35 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 2,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to do local runs for the two ipynb files and update them in the pull request.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re-runned

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI failed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's wired, it passed locally
📊 Final Results:
✅ Conversions: 96/96 (100.0%)

Comment thread act/front_end/verifiable_model.py Outdated

def _build_net(self):
"""Build ACT Net from model and specifications."""
from act.pipeline.verification.model_tracer import ModelTracer

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is model_tracer? I didn't find this class

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the forced pushed, losed. now added back.

Comment on lines +9 to +16
# Purpose:
# Traces nn.Module to extract computation graph and convert to ACT layers.
# Works with any nn.Module (sequential or DAG structures).
#
# Key Features:
# - Generic: Works with any nn.Module
# - Unified: Single graph-based parsing for both sequential and DAG models
# - Supports torch.fx tracing and ONNX fallback for onnx2pytorch models

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks redundant to me. Could we only include necessary methods in act2torch and remove this file?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has lots of post-fixing and uncessary alignment which should be fixed either in front-end or during act2torch.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I merged and re-run

Comment thread act/pipeline/verification/torch2act.py Outdated
Comment on lines +135 to +140
# ONNX-specific state (for onnx2pytorch models)
self.onnx_model: Optional[Any] = None
self.onnx_graph: Optional[Any] = None
self.onnx_mapping: Dict[str, Any] = {}
self.onnx_modules: Dict[str, nn.Module] = {}
self.onnx_output_to_node: Dict[str, Any] = {}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These states can be mapped to all the graph processing states? If so, we could remove these redundant data structures.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, now removed

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good, this torch2act is an important file. Could you try to optimise and remove any redundancy to make it more readable and robust. It is still a bit complicated now

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i used mapped lambda for processing onnx_handlers, nested the converters and added necessary comments

Comment thread act/pipeline/verification/torch2act.py Outdated
self.onnx_modules: Dict[str, nn.Module] = {}
self.onnx_output_to_node: Dict[str, Any] = {}

def trace(self) -> Tuple[List[Layer], Dict[int, List[int]], Dict[int, List[int]]]:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name trace looks odd as this is building the graph not dynamic tracing.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still lots of trace keywords and the lambda is unnecessarily complex. Better to simplify the code in torch2act to make it more readable.

net.assert_last_is_validation()
return net

def _build_layer_graph(self) -> Tuple[Dict[int, List[int]], Dict[int, List[int]]]:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this graph strictly a DAG graph? Can the graph have cycles? Please make comments and necessarily assertions if necessary.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i added a _assert_dag function.

@guanqin-123
guanqin-123 force-pushed the fix branch 3 times, most recently from be6978c to d15def0 Compare January 18, 2026 10:05
@yuleisui

Copy link
Copy Markdown
Collaborator

torch2act CI keeps failing, it needs to be fixed.

Comment thread ipynb/vnnlib_fuzzer.ipynb

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this fuzzer ipynb, there are too many output here and here, try to make output concise.

The counterexample towards the end of this file shows only one image for now. Please add more images and counterexamples. Also make sure when printing the label, not only the number of cifar, but only the name of the class.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ignored the debug log. the fuzzing before the report can already generate serval counterexamples.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to also generate counterexamples based on multiple images.

@guanqin-123
guanqin-123 force-pushed the fix branch 3 times, most recently from 82d782d to 71450d0 Compare January 19, 2026 03:03
- name: Run Torch2ACT Pipeline Tests - MNIST Simple CNN
run: |
cd ${{ github.workspace }}
python -m act.pipeline --verify torch2act --device cpu --dtype float64 No newline at end of file

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks that many are not exercised in the CI. Could you compare and try to include as many as possible as the previous CI.

@guanqin-123 guanqin-123 Jan 19, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧬 Synthesizing models from 10 spec result(s)...
✓ CIFAR10 + resnet18: Created 24 wrapped model(s)
✓ CIFAR10 + resnet34: Created 24 wrapped model(s)
✓ CIFAR10 + resnet50: Created 24 wrapped model(s)
✓ CIFAR10 + vgg16: Created 24 wrapped model(s)
✓ CIFAR10 + mobilenet_v2: Created 24 wrapped model(s)
✓ CIFAR10 + efficientnet_b0: Created 24 wrapped model(s)
✓ MNIST + simple_cnn: Created 24 wrapped model(s)
✓ MNIST + lenet5: Created 24 wrapped model(s)
✓ MNIST + resnet18: Created 24 wrapped model(s)
✓ MNIST + efficientnet_b0: Created 24 wrapped model(s)

🎉 Synthesized 240 wrapped models from specs!

For now, only skip the Resnet 34 with cifar10. Because it gives a "134" issue from git actions, which is over time indicator.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CI still failed, and need to be fixed before merging

Comment thread act/back_end/solver/solver_gurobi.py

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try to simplify this file as much as possible, current the file is a bit too large to review.

Comment thread act/pipeline/cli.py

try:
torch2act.main()
_run_torch2act_with_filter(dataset_filter=dataset_filter, model_filter=model_filter)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure why we need this filter function if we have data and models specified in the terminal cli.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filter to accept the specific model and dataset.

@guanqin-123
guanqin-123 force-pushed the fix branch 4 times, most recently from b687b46 to ba3e1c1 Compare January 19, 2026 05:45
Comment thread .github/workflows/act-frontend-2.yml Outdated
@@ -0,0 +1,79 @@
name: ACT Frontend Tests -2

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a testing CI yml? We can only keep on yml for the front-end testing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revised. leave one only

@guanqin-123

Copy link
Copy Markdown
Contributor Author

Finalized in three Phase. Upgrade done.

@guanqin-123
guanqin-123 deleted the fix branch July 6, 2026 00:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants