vnnlib 1.0.0__cp311-cp311-macosx_10_15_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
vnnlib/__init__.py ADDED
@@ -0,0 +1,76 @@
1
+ """
2
+ VNNLib Python Bindings
3
+
4
+ Modern Python bindings for the VNNLib verification language parser.
5
+ Built with pybind11 for direct access to the BNFC-generated C++ AST.
6
+
7
+ Basic Usage:
8
+ import vnnlib
9
+
10
+ # Parse a VNNLIB file
11
+ query = vnnlib.parse_query_file("path/to/file.vnnlib")
12
+
13
+ # Access networks and constraints
14
+ for network in query.networks:
15
+ print(f"Network: {network.name}")
16
+
17
+ # Use compatibility module for reachability format
18
+ import vnnlib.compat
19
+ cases = vnnlib.compat.transform(query)
20
+ """
21
+
22
+ from ._core import (
23
+ # Parsing functions
24
+ parse_query_file, parse_query_string,
25
+
26
+ # Core AST node types
27
+ Query, Network, Assertion,
28
+ InputDefinition, OutputDefinition, HiddenDefinition,
29
+ Version,
30
+
31
+ # Expression types
32
+ ArithExpr, BoolExpr,
33
+ Var, Literal, Float, Int, Negate, Plus, Minus, Multiply,
34
+ Comparison, GreaterThan, GreaterEqual, LessThan, LessEqual, Equal, NotEqual,
35
+ Connective, And, Or,
36
+
37
+ # Linear arithmetic
38
+ LinearArithExpr, Term,
39
+
40
+ # Enums and data types
41
+ DType, SymbolKind,
42
+
43
+ # Exceptions
44
+ VNNLibException,
45
+ )
46
+
47
+ # Module metadata
48
+ __version__ = "1.0.0-dev"
49
+ __author__ = "Allen Antony"
50
+ __description__ = "Python bindings for VNNLib verification language"
51
+ __url__ = "https://github.com/VNNLIB/VNNLIB-Standard"
52
+
53
+ __all__ = [
54
+ # Parsing functions
55
+ "parse_query_file", "parse_query_string",
56
+
57
+ # Core AST nodes
58
+ "Query", "Network", "Assertion",
59
+ "InputDefinition", "OutputDefinition", "HiddenDefinition",
60
+ "Version",
61
+
62
+ # Expression types
63
+ "ArithExpr", "BoolExpr",
64
+ "Var", "Literal", "Float", "Int", "Negate", "Plus", "Minus", "Multiply",
65
+ "Comparison", "GreaterThan", "GreaterEqual", "LessThan", "LessEqual", "Equal", "NotEqual",
66
+ "Connective", "And", "Or",
67
+
68
+ # Linear arithmetic
69
+ "LinearArithExpr", "Term",
70
+
71
+ # Enums and data types
72
+ "DType", "SymbolKind",
73
+
74
+ # Exceptions
75
+ "VNNLibException",
76
+ ]
vnnlib/__init__.pyi ADDED
@@ -0,0 +1,3 @@
1
+ """Type stubs for VNNLib Python bindings"""
2
+
3
+ from ._core import *
vnnlib/_core.cpp ADDED
@@ -0,0 +1,287 @@
1
+ #include <pybind11/pybind11.h>
2
+ #include <pybind11/stl.h>
3
+ #include <memory>
4
+ #include <exception>
5
+ #include <string>
6
+ #include <vector>
7
+
8
+ #include "VNNLib.h"
9
+ #include "TypeChecker.h"
10
+ #include "TypedAST.h"
11
+ #include "TypedBuilder.h"
12
+ #include "LinearArithExpr.h"
13
+ #include "DNFConverter.h"
14
+ #include "CompatTransformer.h"
15
+ #include "Error.hpp"
16
+
17
+ namespace py = pybind11;
18
+
19
+ PYBIND11_MODULE(_core, m) {
20
+ m.doc() = "Python bindings for VNNLib parsing and AST traversal";
21
+
22
+ py::register_exception<VNNLibException>(m, "VNNLibException");
23
+
24
+ // Helper Types
25
+ py::enum_<TDataType>(m, "DType")
26
+ .value("Real", TDataType::Real)
27
+ .value("F16", TDataType::F16).value("F32", TDataType::F32).value("F64", TDataType::F64).value("BF16", TDataType::BF16)
28
+ .value("F8E4M3FN", TDataType::F8E4M3FN).value("F8E5M2", TDataType::F8E5M2)
29
+ .value("F8E4M3FNUZ", TDataType::F8E4M3FNUZ).value("F8E5M2FNUZ", TDataType::F8E5M2FNUZ)
30
+ .value("F4E2M1", TDataType::F4E2M1)
31
+ .value("I8", TDataType::I8).value("I16", TDataType::I16).value("I32", TDataType::I32).value("I64", TDataType::I64)
32
+ .value("U8", TDataType::U8).value("U16", TDataType::U16).value("U32", TDataType::U32).value("U64", TDataType::U64)
33
+ .value("C64", TDataType::C64).value("C128", TDataType::C128)
34
+ .value("Bool", TDataType::Bool).value("String", TDataType::String)
35
+ .value("Unknown", TDataType::Unknown)
36
+ .value("NegativeIntConstant", TDataType::NegativeIntConstant)
37
+ .value("PositiveIntConstant", TDataType::PositiveIntConstant)
38
+ .value("FloatConstant", TDataType::FloatConstant);
39
+
40
+ py::enum_<SymbolKind>(m, "SymbolKind")
41
+ .value("Input", SymbolKind::Input)
42
+ .value("Hidden", SymbolKind::Hidden)
43
+ .value("Output", SymbolKind::Output)
44
+ .value("Unknown", SymbolKind::Unknown);
45
+
46
+ py::class_<TNode>(m, "Node")
47
+ .def("__str__", [](const TNode& n){ return n.toString(); })
48
+ .def("children", [](py::object self){
49
+ const TNode& n = self.cast<const TNode&>();
50
+ std::vector<const TNode*> children;
51
+ n.children(children);
52
+ py::tuple out(children.size());
53
+
54
+ for (int i = 0; i < children.size(); ++i) {
55
+ out[i] = py::cast(children[i], py::return_value_policy::reference_internal, self);
56
+ }
57
+ return out;
58
+ });
59
+
60
+ // --- LinearArithExpr ---
61
+ py::class_<LinearArithExpr::Term>(m, "Term")
62
+ .def_property_readonly("coeff", [](const LinearArithExpr::Term& t){ return t.coeff; })
63
+ .def_property_readonly("var", [](const LinearArithExpr::Term& t){ return t.var; }, py::return_value_policy::reference_internal)
64
+ .def_property_readonly("var_name", [](const LinearArithExpr::Term& t){ return t.varName; });
65
+
66
+ py::class_<LinearArithExpr>(m, "LinearArithExpr")
67
+ .def_property_readonly("terms", [](const LinearArithExpr& e){ return e.getTerms(); })
68
+ .def_property_readonly("constant", [](const LinearArithExpr& e){ return e.getConstant(); });
69
+
70
+ // --- Arithmetic Operations ---
71
+ py::class_<TArithExpr, TNode>(m, "ArithExpr")
72
+ .def_property_readonly("dtype", [](const TArithExpr& e){ return e.dtype; })
73
+ .def("to_linear_expr", [](const TArithExpr& e){
74
+ auto lin_expr = linearize(&e);
75
+ return py::cast(lin_expr.release(), py::return_value_policy::take_ownership);
76
+ });
77
+
78
+ py::class_<TVarExpr, TArithExpr>(m, "Var")
79
+ .def_property_readonly("name", [](const TVarExpr& v){ return v.symbol ? v.symbol->name : std::string{}; })
80
+ .def_property_readonly("onnx_name", [](const TVarExpr& v)->py::object{
81
+ if (v.symbol->onnxName.empty()) return py::none();
82
+ return py::str(v.symbol->onnxName);
83
+ })
84
+ .def_property_readonly("dtype", [](const TVarExpr& v){ return v.symbol->dtype; })
85
+ .def_property_readonly("shape", [](const TVarExpr& v){ return v.symbol->shape; })
86
+ .def_property_readonly("kind", [](const TVarExpr& v){ return v.symbol->kind; })
87
+ .def_property_readonly("network_name",[](const TVarExpr& v){ return v.symbol->networkName; })
88
+ .def_property_readonly("indices", [](const TVarExpr& v){ return v.indices; })
89
+ .def_property_readonly("line", [](const TVarExpr& v){ return v.line; });
90
+
91
+ py::class_<TLiteral, TArithExpr>(m, "Literal")
92
+ .def_property_readonly("lexeme", [](const TLiteral& e){ return e.lexeme; })
93
+ .def_property_readonly("line", [](const TLiteral& e){ return e.line; });
94
+
95
+ py::class_<TFloat, TLiteral>(m, "Float")
96
+ .def_property_readonly("value", [](const TFloat& n){ return n.value; });
97
+
98
+ py::class_<TInt, TLiteral>(m, "Int")
99
+ .def_property_readonly("value", [](const TInt& n){ return n.value; });
100
+
101
+ py::class_<TNegate, TArithExpr>(m, "Negate")
102
+ .def_property_readonly("expr", [](const TNegate& n){ return n.expr.get(); }, py::return_value_policy::reference_internal);
103
+
104
+ py::class_<TPlus, TArithExpr>(m, "Plus")
105
+ .def_property_readonly("args", [](const TPlus& n){
106
+ py::tuple args_tuple(n.args.size());
107
+ for (size_t i = 0; i < n.args.size(); ++i)
108
+ args_tuple[i] = py::cast(n.args[i].get(), py::return_value_policy::reference_internal, py::cast(&n));
109
+ return args_tuple;
110
+ });
111
+
112
+ py::class_<TMinus, TArithExpr>(m, "Minus")
113
+ .def_property_readonly("head", [](const TMinus& n){ return n.head.get(); }, py::return_value_policy::reference_internal)
114
+ .def_property_readonly("rest", [](const TMinus& n){
115
+ py::tuple rest_tuple(n.rest.size());
116
+ for (size_t i = 0; i < n.rest.size(); ++i)
117
+ rest_tuple[i] = py::cast(n.rest[i].get(), py::return_value_policy::reference_internal, py::cast(&n));
118
+ return rest_tuple;
119
+ });
120
+
121
+ py::class_<TMultiply, TArithExpr>(m, "Multiply")
122
+ .def_property_readonly("args", [](const TMultiply& n){
123
+ py::tuple args_tuple(n.args.size());
124
+ for (size_t i = 0; i < n.args.size(); ++i)
125
+ args_tuple[i] = py::cast(n.args[i].get(), py::return_value_policy::reference_internal, py::cast(&n));
126
+ return args_tuple;
127
+ });
128
+
129
+ // ---------- Boolean Operations ----------
130
+ py::class_<TBoolExpr, TNode>(m, "BoolExpr")
131
+ .def("to_dnf", [](const TBoolExpr& e){
132
+ DNF dnf = toDNF(&e);
133
+ py::list py_dnf;
134
+
135
+ for (size_t i = 0; i < dnf.size(); ++i) {
136
+ auto& clause = dnf[i];
137
+ py::list py_clause;
138
+ for (auto* lit : clause) {
139
+ py_clause.append(py::cast(lit, py::return_value_policy::reference_internal, py::cast(&e)));
140
+ }
141
+ py_dnf.append(py_clause);
142
+ }
143
+ return py_dnf;
144
+ });
145
+
146
+ py::class_<TCompare, TBoolExpr>(m, "Comparison")
147
+ .def_property_readonly("lhs", [](const TCompare& n){ return n.lhs.get(); }, py::return_value_policy::reference_internal)
148
+ .def_property_readonly("rhs", [](const TCompare& n){ return n.rhs.get(); }, py::return_value_policy::reference_internal);
149
+
150
+ py::class_<TGreaterThan, TCompare>(m, "GreaterThan");
151
+ py::class_<TEqual, TCompare>(m, "Equal");
152
+ py::class_<TLessThan, TCompare>(m, "LessThan");
153
+ py::class_<TGreaterEqual, TCompare>(m, "GreaterEqual");
154
+ py::class_<TLessEqual, TCompare>(m, "LessEqual");
155
+ py::class_<TNotEqual, TCompare>(m, "NotEqual");
156
+
157
+ py::class_<TConnective, TBoolExpr>(m, "Connective")
158
+ .def_property_readonly("args", [](const TConnective& n){
159
+ py::tuple args_tuple(n.args.size());
160
+ for (size_t i = 0; i < n.args.size(); ++i)
161
+ args_tuple[i] = py::cast(n.args[i].get(), py::return_value_policy::reference_internal, py::cast(&n));
162
+ return args_tuple;
163
+ });
164
+
165
+ py::class_<TAnd, TConnective>(m, "And");
166
+ py::class_<TOr, TConnective>(m, "Or");
167
+
168
+ // --- Assertion ---
169
+ py::class_<TAssertion, TNode>(m, "Assertion")
170
+ .def_property_readonly("expr", [](const TAssertion& a){ return a.cond.get(); }, py::return_value_policy::reference_internal);
171
+
172
+ // --- Definitions ---
173
+ py::class_<TInputDefinition, TNode>(m, "InputDefinition")
174
+ .def_property_readonly("name", [](const TInputDefinition& d){ return d.symbol ? d.symbol->name : std::string{}; })
175
+ .def_property_readonly("onnx_name", [](const TInputDefinition& d)->py::object{
176
+ if (d.symbol->onnxName.empty()) return py::none();
177
+ return py::str(d.symbol->onnxName);
178
+ })
179
+ .def_property_readonly("dtype", [](const TInputDefinition& d){ return d.symbol ? d.symbol->dtype : TDataType::Unknown; })
180
+ .def_property_readonly("shape", [](const TInputDefinition& d){ return d.symbol ? d.symbol->shape : Shape{}; })
181
+ .def_property_readonly("kind", [](const TInputDefinition& d){ return d.symbol ? d.symbol->kind : SymbolKind::Unknown; })
182
+ .def_property_readonly("network_name", [](const TInputDefinition& d){ return d.symbol ? d.symbol->networkName : std::string{}; });
183
+
184
+ py::class_<THiddenDefinition, TNode>(m, "HiddenDefinition")
185
+ .def_property_readonly("name", [](const THiddenDefinition& d){ return d.symbol ? d.symbol->name : std::string{}; })
186
+ .def_property_readonly("onnx_name", [](const THiddenDefinition& d)->py::object{
187
+ if (d.symbol->onnxName.empty()) return py::none();
188
+ return py::str(d.symbol->onnxName);
189
+ })
190
+ .def_property_readonly("dtype", [](const THiddenDefinition& d){ return d.symbol ? d.symbol->dtype : TDataType::Unknown; })
191
+ .def_property_readonly("shape", [](const THiddenDefinition& d){ return d.symbol ? d.symbol->shape : Shape{}; })
192
+ .def_property_readonly("kind", [](const THiddenDefinition& d){ return d.symbol ? d.symbol->kind : SymbolKind::Unknown; })
193
+ .def_property_readonly("network_name", [](const THiddenDefinition& d){ return d.symbol ? d.symbol->networkName : std::string{}; });
194
+
195
+ py::class_<TOutputDefinition, TNode>(m, "OutputDefinition")
196
+ .def_property_readonly("name", [](const TOutputDefinition& d){ return d.symbol ? d.symbol->name : std::string{}; })
197
+ .def_property_readonly("onnx_name", [](const TOutputDefinition& d)->py::object{
198
+ if (d.symbol->onnxName.empty()) return py::none();
199
+ return py::str(d.symbol->onnxName);
200
+ })
201
+ .def_property_readonly("dtype", [](const TOutputDefinition& d){ return d.symbol ? d.symbol->dtype : TDataType::Unknown; })
202
+ .def_property_readonly("shape", [](const TOutputDefinition& d){ return d.symbol ? d.symbol->shape : Shape{}; })
203
+ .def_property_readonly("kind", [](const TOutputDefinition& d){ return d.symbol ? d.symbol->kind : SymbolKind::Unknown; })
204
+ .def_property_readonly("network_name", [](const TOutputDefinition& d){ return d.symbol ? d.symbol->networkName : std::string{}; });
205
+
206
+ // --- Network ---
207
+ py::class_<TNetworkDefinition, TNode>(m, "Network")
208
+ .def_property_readonly("name", [](const TNetworkDefinition& n){ return n.networkName; })
209
+ .def_property_readonly("isometric_to", [](const TNetworkDefinition& n){ return n.isometricTo; })
210
+ .def_property_readonly("equal_to", [](const TNetworkDefinition& n){ return n.equalTo; })
211
+ .def_property_readonly("inputs", [](const TNetworkDefinition& n){
212
+ py::tuple input_tuple(n.inputs.size());
213
+ for (size_t i = 0; i < n.inputs.size(); ++i)
214
+ input_tuple[i] = py::cast(n.inputs[i].get(), py::return_value_policy::reference_internal, py::cast(&n));
215
+ return input_tuple;
216
+ })
217
+ .def_property_readonly("hidden", [](const TNetworkDefinition& n){
218
+ py::tuple hidden_tuple(n.hidden.size());
219
+ for (size_t i = 0; i < n.hidden.size(); ++i)
220
+ hidden_tuple[i] = py::cast(n.hidden[i].get(), py::return_value_policy::reference_internal, py::cast(&n));
221
+ return hidden_tuple;
222
+ })
223
+ .def_property_readonly("outputs", [](const TNetworkDefinition& n){
224
+ py::tuple output_tuple(n.outputs.size());
225
+ for (size_t i = 0; i < n.outputs.size(); ++i)
226
+ output_tuple[i] = py::cast(n.outputs[i].get(), py::return_value_policy::reference_internal, py::cast(&n));
227
+ return output_tuple;
228
+ });
229
+
230
+ // --- Version ---
231
+ py::class_<TVersion, TNode>(m, "Version")
232
+ .def_property_readonly("major", [](const TVersion& v){ return v.major; })
233
+ .def_property_readonly("minor", [](const TVersion& v){ return v.minor; });
234
+
235
+ // --- Query ---
236
+ py::class_<TQuery, TNode>(m, "Query")
237
+ .def_property_readonly("networks", [](const TQuery& q){
238
+ py::tuple network_tuple(q.networks.size());
239
+ for (size_t i = 0; i < q.networks.size(); ++i)
240
+ network_tuple[i] = py::cast(q.networks[i].get(), py::return_value_policy::reference_internal, py::cast(&q));
241
+ return network_tuple;
242
+ })
243
+ .def_property_readonly("assertions", [](const TQuery& q){
244
+ py::tuple assertion_tuple(q.assertions.size());
245
+ for (size_t i = 0; i < q.assertions.size(); ++i)
246
+ assertion_tuple[i] = py::cast(q.assertions[i].get(), py::return_value_policy::reference_internal, py::cast(&q));
247
+ return assertion_tuple;
248
+ });
249
+
250
+ // --- CompatTransformer ---
251
+ py::class_<Polytope>(m, "Polytope")
252
+ .def_property_readonly("coeff_matrix", [](const Polytope& p){ return p.coeffMatrix; })
253
+ .def_property_readonly("rhs", [](const Polytope& p){ return p.rhs; });
254
+
255
+ py::class_<SpecCase>(m, "SpecCase")
256
+ .def_property_readonly("input_box", [](const SpecCase& c){ return c.inputBox; })
257
+ .def_property_readonly("output_constraints", [](const SpecCase& c){ return c.outputConstraints; },
258
+ py::return_value_policy::reference_internal);
259
+
260
+ // --- API ---
261
+ m.def("parse_query_file", [](const std::string& path) {
262
+ return parseQueryFile(path);
263
+ },
264
+ py::return_value_policy::move,
265
+ py::arg("path"));
266
+
267
+ m.def("parse_query_string", [](const std::string& content) {
268
+ return parseQueryString(content);
269
+ },
270
+ py::return_value_policy::move,
271
+ py::arg("content"));
272
+
273
+ m.def("transform_to_compat", [](const TQuery& query) {
274
+ CompatTransformer transformer(&query);
275
+ const auto& cases = transformer.transform();
276
+
277
+ py::list py_cases;
278
+ for (const auto& c : cases) {
279
+ py_cases.append(py::cast(c, py::return_value_policy::move));
280
+ }
281
+ return py_cases;
282
+ },
283
+ py::arg("query"));
284
+
285
+ m.attr("__version__") = "0.2.0";
286
+ }
287
+
Binary file
vnnlib/_core.pyi ADDED
@@ -0,0 +1,270 @@
1
+ """Type stubs for VNNLib (typed AST)"""
2
+
3
+ from __future__ import annotations
4
+ from typing import List, Tuple, Optional, Any
5
+ from enum import Enum
6
+
7
+ # --- Exceptions --------------------------------------------------------------
8
+
9
+ class VNNLibException(Exception): ...
10
+
11
+
12
+ # --- Enums / Aliases --------------------------------------------------------
13
+
14
+ class DType(Enum):
15
+ F16: DType
16
+ F32: DType
17
+ F64: DType
18
+ BF16: DType
19
+ F8E4M3FN: DType
20
+ F8E5M2: DType
21
+ F8E4M3FNUZ: DType
22
+ F8E5M2FNUZ: DType
23
+ F4E2M1: DType
24
+ I8: DType
25
+ I16: DType
26
+ I32: DType
27
+ I64: DType
28
+ U8: DType
29
+ U16: DType
30
+ U32: DType
31
+ U64: DType
32
+ C64: DType
33
+ C128: DType
34
+ Bool: DType
35
+ String: DType
36
+ Unknown: DType
37
+ NegativeIntConstant: DType
38
+ PositiveIntConstant: DType
39
+ FloatConstant: DType
40
+
41
+ class SymbolKind(Enum):
42
+ Input: SymbolKind
43
+ Hidden: SymbolKind
44
+ Output: SymbolKind
45
+ Unknown: SymbolKind
46
+
47
+ Shape = List[int]
48
+
49
+
50
+ # --- Base node ---------------------------------------------------------------
51
+
52
+ class Node:
53
+ def __str__(self) -> str: ...
54
+ def children(self) -> Tuple[Node, ...]: ...
55
+
56
+
57
+ # --- Arithmetic --------------------------------------------------------------
58
+
59
+ class ArithExpr(Node):
60
+ @property
61
+ def dtype(self) -> DType: ...
62
+ def to_linear_expr(self) -> LinearArithExpr: ...
63
+
64
+ class Var(ArithExpr):
65
+ @property
66
+ def name(self) -> str: ...
67
+ @property
68
+ def indices(self) -> List[int]: ...
69
+ @property
70
+ def dtype(self) -> DType: ...
71
+ @property
72
+ def shape(self) -> Shape: ...
73
+ @property
74
+ def kind(self) -> SymbolKind: ...
75
+ @property
76
+ def onnx_name(self) -> Optional[str]: ...
77
+ @property
78
+ def network_name(self) -> str: ...
79
+ @property
80
+ def line(self) -> int: ...
81
+
82
+ class Literal(ArithExpr):
83
+ @property
84
+ def lexeme(self) -> str: ...
85
+ @property
86
+ def line(self) -> int: ...
87
+
88
+ class Float(ArithExpr):
89
+ @property
90
+ def value(self) -> float: ...
91
+
92
+ class Int(ArithExpr):
93
+ @property
94
+ def value(self) -> int: ...
95
+
96
+ class IntExpr(ArithExpr):
97
+ @property
98
+ def value(self) -> int: ...
99
+ @property
100
+ def lexeme(self) -> str: ...
101
+
102
+ class Negate(ArithExpr):
103
+ @property
104
+ def expr(self) -> ArithExpr: ...
105
+
106
+ class Plus(ArithExpr):
107
+ @property
108
+ def args(self) -> Tuple[ArithExpr, ...]: ...
109
+
110
+ class Minus(ArithExpr):
111
+ @property
112
+ def head(self) -> ArithExpr: ...
113
+ @property
114
+ def rest(self) -> Tuple[ArithExpr, ...]: ...
115
+
116
+ class Multiply(ArithExpr):
117
+ @property
118
+ def args(self) -> Tuple[ArithExpr, ...]: ...
119
+
120
+
121
+ # --- Linear Arithmetic -------------------------------------------------------
122
+
123
+ class Term:
124
+ @property
125
+ def coeff(self) -> float: ...
126
+ @property
127
+ def var_name(self) -> str: ...
128
+ @property
129
+ def var(self) -> Var: ...
130
+
131
+ class LinearArithExpr:
132
+ @property
133
+ def terms(self) -> List[Term]: ...
134
+ @property
135
+ def constant(self) -> float: ...
136
+
137
+
138
+ # --- Boolean -----------------------------------------------------------------
139
+
140
+ class BoolExpr(Node):
141
+ def to_dnf(self) -> List[List[Comparison]]: ...
142
+
143
+ class Comparison(BoolExpr):
144
+ @property
145
+ def lhs(self) -> ArithExpr: ...
146
+ @property
147
+ def rhs(self) -> ArithExpr: ...
148
+
149
+ class GreaterThan(Comparison): ...
150
+ class LessThan(Comparison): ...
151
+ class GreaterEqual(Comparison): ...
152
+ class LessEqual(Comparison): ...
153
+ class Equal(Comparison): ...
154
+ class NotEqual(Comparison): ...
155
+
156
+ class Connective(BoolExpr):
157
+ @property
158
+ def args(self) -> Tuple[BoolExpr, ...]: ...
159
+
160
+ class And(Connective): ...
161
+ class Or(Connective): ...
162
+
163
+
164
+ # --- Assertions --------------------------------------------------------------
165
+
166
+ class Assertion(Node):
167
+ @property
168
+ def expr(self) -> BoolExpr: ...
169
+
170
+
171
+ # --- Declarations ------------------------------------------------------------
172
+
173
+ class InputDefinition(Node):
174
+ @property
175
+ def name(self) -> str: ...
176
+ @property
177
+ def dtype(self) -> DType: ...
178
+ @property
179
+ def shape(self) -> Shape: ...
180
+ @property
181
+ def kind(self) -> SymbolKind: ...
182
+ @property
183
+ def onnx_name(self) -> Optional[str]: ...
184
+ @property
185
+ def network_name(self) -> str: ...
186
+
187
+ class HiddenDefinition(Node):
188
+ @property
189
+ def name(self) -> str: ...
190
+ @property
191
+ def dtype(self) -> DType: ...
192
+ @property
193
+ def shape(self) -> Shape: ...
194
+ @property
195
+ def kind(self) -> SymbolKind: ...
196
+ @property
197
+ def onnx_name(self) -> Optional[str]: ...
198
+ @property
199
+ def network_name(self) -> str: ...
200
+
201
+ class OutputDefinition(Node):
202
+ @property
203
+ def name(self) -> str: ...
204
+ @property
205
+ def dtype(self) -> DType: ...
206
+ @property
207
+ def shape(self) -> Shape: ...
208
+ @property
209
+ def kind(self) -> SymbolKind: ...
210
+ @property
211
+ def onnx_name(self) -> Optional[str]: ...
212
+ @property
213
+ def network_name(self) -> str: ...
214
+
215
+
216
+ # --- Network ---------------------------------------------------------
217
+
218
+ class Network(Node):
219
+ @property
220
+ def name(self) -> str: ...
221
+ @property
222
+ def equal_to(self) -> str: ...
223
+ @property
224
+ def isometric_to(self) -> str: ...
225
+ @property
226
+ def inputs(self) -> Tuple[InputDefinition, ...]: ...
227
+ @property
228
+ def hidden(self) -> Tuple[HiddenDefinition, ...]: ...
229
+ @property
230
+ def outputs(self) -> Tuple[OutputDefinition, ...]: ...
231
+
232
+
233
+ # --- Version -----------------------------------------------------------
234
+
235
+ class Version(Node):
236
+ @property
237
+ def major(self) -> int: ...
238
+ @property
239
+ def minor(self) -> int: ...
240
+
241
+
242
+ class Query(Node):
243
+ @property
244
+ def networks(self) -> Tuple[Network, ...]: ...
245
+ @property
246
+ def assertions(self) -> Tuple[Assertion, ...]: ...
247
+
248
+
249
+ # --- Compatibility (Reachability Format) ------------------------------------
250
+
251
+ class Polytope:
252
+ @property
253
+ def coeff_matrix(self) -> List[List[float]]: ...
254
+ @property
255
+ def rhs(self) -> List[float]: ...
256
+
257
+ class SpecCase:
258
+ @property
259
+ def input_box(self) -> List[Tuple[float, float]]: ...
260
+ @property
261
+ def output_constraints(self) -> List[Polytope]: ...
262
+
263
+
264
+ # --- Parse API (typed) -------------------------------------------------------
265
+
266
+ def parse_query_file(path: str) -> Query: ...
267
+ def parse_query_string(content: str) -> Query: ...
268
+ def transform_to_compat(query: Query) -> List[SpecCase]: ...
269
+
270
+ __version__: str
@@ -0,0 +1,54 @@
1
+ """
2
+ VNNLib Compatibility Module
3
+
4
+ This module provides classes and functions for converting VNNLib specifications
5
+ to reachability format compatible with reachability analysis tools.
6
+
7
+ The reachability format represents verification problems as:
8
+ 1. Input constraints as box bounds (lower/upper bounds per input dimension)
9
+ 2. Output constraints as polytopes in the form Ay ≤ b
10
+ """
11
+
12
+ from .._core import Polytope, SpecCase, transform_to_compat
13
+
14
+ __all__ = [
15
+ "Polytope",
16
+ "SpecCase",
17
+ "transform",
18
+ ]
19
+
20
+ def transform(query):
21
+ """
22
+ Transform a VNNLib Query to reachability format.
23
+
24
+ This function converts VNNLib specifications into a list of reachability cases.
25
+ Each case consists of:
26
+ 1. Input box bounds: lower and upper bounds for each input dimension
27
+ 2. Output polytopes: constraints in the form Ay ≤ b representing disjunctions
28
+
29
+ Parameters
30
+ ----------
31
+ query : vnnlib.Query
32
+ The parsed VNNLib Query object to transform
33
+
34
+ Returns
35
+ -------
36
+ List[SpecCase]
37
+ A list of reachability cases with input bounds and output constraints
38
+
39
+ Raises
40
+ ------
41
+ VNNLibException
42
+ If the specification cannot be converted to reachability format.
43
+
44
+ Example
45
+ -------
46
+ >>> import vnnlib
47
+ >>> import vnnlib.compat
48
+ >>> query = vnnlib.parse_query_string(content)
49
+ >>> cases = vnnlib.compat.transform(query)
50
+ >>> case = cases[0]
51
+ >>> print(f"Input bounds: {case.input_box}")
52
+ >>> print(f"Output polytopes: {len(case.output_constraints)}")
53
+ """
54
+ return transform_to_compat(query)
vnnlib/compat/py.typed ADDED
File without changes
vnnlib/libVNNLib.dylib ADDED
Binary file
vnnlib/py.typed ADDED
@@ -0,0 +1 @@
1
+ """Stub-only package"""
@@ -0,0 +1,48 @@
1
+ Metadata-Version: 2.2
2
+ Name: vnnlib
3
+ Version: 1.0.0
4
+ Summary: Python bindings for VNNLib parsing and AST manipulation
5
+ Author-Email: Allen Antony <allenantony2001@gmail.com>
6
+ License: MIT
7
+ Requires-Python: >=3.7
8
+ Requires-Dist: pybind11>=2.6.0
9
+ Description-Content-Type: text/markdown
10
+
11
+ # VNN-LIB Python
12
+
13
+ A Python package for parsing and manipulating neural network properties in the updated [VNN-LIB format](https://www.vnnlib.org/).
14
+
15
+ ## Features
16
+
17
+ Features include:
18
+ - Parsing: Convert VNN-LIB file or string into a type-checked AST
19
+ - AST traversal: Access, traverse, and convert the AST back to a string.
20
+ - Transformers:
21
+ - Linearise arithmetic expressions
22
+ - Convert boolean expressions to Disjunctive Normal Form (DNF)
23
+ - Transform spec to reachability format used in prior VNN-COMPs.
24
+
25
+ ## Installation
26
+
27
+ Install the latest stable version via PyPi:
28
+ ```bash
29
+ pip install vnnlib
30
+ ```
31
+
32
+ ## Basic Usage
33
+
34
+ ```python
35
+ import vnnlib
36
+
37
+ # Parse a VNN-LIB specification
38
+ query = vnnlib.parse_query_file("path/to/spec.vnnlib")
39
+
40
+ for assertion in query.assertions:
41
+ print(assertion)
42
+ ```
43
+
44
+ ## Version compatibility
45
+
46
+ | VNNLIB-Python version | VNNLIB version |
47
+ | --- | --- |
48
+ | v1.0 | v2.0 |
@@ -0,0 +1,13 @@
1
+ vnnlib-1.0.0.dist-info/RECORD,,
2
+ vnnlib-1.0.0.dist-info/WHEEL,sha256=_zINgRxDmPoJWl94R6FZTGt8Bzncj3Uu9X9upp27784,143
3
+ vnnlib-1.0.0.dist-info/METADATA,sha256=wnjLAqg4wr6n4vhRvMk3n7JSaorccIUrswfn5L16WMI,1171
4
+ vnnlib-1.0.0.dist-info/licenses/LICENSE,sha256=aRYsrTcINTRh5FTXvbHARWhog18NPO_tjECDhbAOzR0,1086
5
+ vnnlib/libVNNLib.dylib,sha256=iFgVLr4nzrOE2Sg8kfzx3UTXZH_iJYF8WLv_9YIge3g,367264
6
+ vnnlib/__init__.pyi,sha256=YChDCtUFDV14VsSrt5Bz8stAebymJI0wZDULC-qUopU,66
7
+ vnnlib/_core.pyi,sha256=3FZcIOvRfm9LN7VwttvNUrRH5wky1Ug0oeAX-8KUGRg,6219
8
+ vnnlib/_core.cpp,sha256=ILh96cmpasRhqMZFkz60Z9w7lOMAekoFGUv0WR-QOvk,13238
9
+ vnnlib/__init__.py,sha256=-TtOOw7D9hk8tXZyyMStBJwnkdxN0eulf3OVPHlk1PI,1990
10
+ vnnlib/py.typed,sha256=wedgqpT4WwmZzs6C28NAC9NiqQc0Yvpd-7QizLn4QFo,24
11
+ vnnlib/_core.cpython-311-darwin.so,sha256=KtEF15dsvbQ1J45HFZAO2zKQHg086h3DcnqxH48kNX0,346448
12
+ vnnlib/compat/__init__.py,sha256=FY8SajqtUAVDliUfrFV19QEd5IOomeSjE3T3DLd_qL8,1597
13
+ vnnlib/compat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -0,0 +1,6 @@
1
+ Wheel-Version: 1.0
2
+ Generator: scikit-build-core 0.11.6
3
+ Root-Is-Purelib: false
4
+ Tag: cp311-cp311-macosx_10_15_x86_64
5
+ Generator: delocate 0.13.0
6
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Allen Anthony, Matthew Daggitt
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.