Пример #1
0
    def test_sum_gt_one(self):
        op_graph = parse(artifact_dir / "sum_gt_one.onnx")
        output_op = op_graph.output_operations[0]  # gemm
        prefix = OperationGraph([output_op.a])
        op_graph_suffix = OperationGraph(op_graph.walk(DropPrefix(prefix)))
        x = np.ones((1, 1)).astype(np.float32)
        y = op_graph_suffix(x)
        y_expected = np.ones((1, 1))
        self.assertTrue((np.abs(y_expected - y) <= THRESHOLD).all())
        x = np.random.normal(size=(10, 1)).astype(np.float32)
        y = op_graph_suffix(x)
        y_expected = x.copy()
        self.assertTrue((np.abs(y_expected - y) <= THRESHOLD).all())

        prefix_output_op = prefix.output_operations[0]  # relu
        prefix = OperationGraph([prefix_output_op.x])
        op_graph_suffix = OperationGraph(op_graph.walk(DropPrefix(prefix)))
        x = np.ones((1, 1)).astype(np.float32)
        y = op_graph_suffix(x)
        y_expected = np.ones((1, 1))
        self.assertTrue((np.abs(y_expected - y) <= THRESHOLD).all())
        x = np.random.normal(size=(10, 1)).astype(np.float32)
        y = op_graph_suffix(x)
        y_expected = np.clip(x, 0.0, None)
        self.assertTrue((np.abs(y_expected - y) <= THRESHOLD).all())
Пример #2
0
def verify(dnn: OperationGraph, phi: Expression, **kwargs: Dict[str, Any]):
    logger = logging.getLogger(__name__)
    dnn = dnn.simplify()
    phi.networks[0].concretize(dnn)

    result = UNSAT
    property_extractor = ConvexPolytopeExtractor()
    with tempfile.TemporaryDirectory() as dirname:
        for prop in property_extractor.extract_from(phi):
            layers = prop.output_constraint.as_layers(
                prop.network,
                extra_layer_types=MIPVERIFY_LAYER_TYPES,
                translator_error=MIPVerifyTranslatorError,
            )
            input_interval = prop.input_constraint.as_hyperrectangle()
            mipverify_inputs = to_mipverify_inputs(
                input_interval,
                layers,
                dirname=dirname,
                translator_error=MIPVerifyTranslatorError,
            )
            logger.debug("Running mipverify")
            executor = CommandLineExecutor(
                "julia",
                mipverify_inputs["property_path"],
                verifier_error=MIPVerifyError,
            )
            out, err = executor.run()
            logger.debug("Parsing results")
            result |= parse_results(out, err)
            if result == SAT or result == UNKNOWN:
                return result

    return result
Пример #3
0
    def suffixed_op_graph(self) -> OperationGraph:
        import dnnv.nn.operations as operations

        if not isinstance(self.output_constraint, HalfspacePolytope):
            raise ValueError(
                f"{type(self.output_constraint).__name__} constraints are not yet supported"
            )
        if len(self.op_graph.output_operations) == 1:
            new_output_op = self.op_graph.output_operations[0]
        else:
            output_operations = [
                operations.Flatten(o) for o in self.op_graph.output_operations
            ]
            new_output_op = operations.Concat(output_operations, axis=1)
        size = self.output_constraint.size()
        k = len(self.output_constraint.halfspaces)
        W = np.zeros((size, k), dtype=np.float32)
        b = np.zeros(k, dtype=np.float32)
        for n, hs in enumerate(self.output_constraint.halfspaces):
            b[n] = -hs.b
            if hs.is_open:
                b[n] += 1e-6  # TODO : remove magic number
            for i, c in zip(hs.indices, hs.coefficients):
                W[i, n] = c
        new_output_op = operations.Add(operations.MatMul(new_output_op, W), b)
        new_output_op = operations.Relu(new_output_op)

        W_mask = np.zeros((k, 1), dtype=np.float32)
        b_mask = np.zeros(1, dtype=np.float32)
        for i in range(k):
            W_mask[i, 0] = 1
        new_output_op = operations.Add(
            operations.MatMul(new_output_op, W_mask), b_mask)
        return OperationGraph([new_output_op]).simplify()
Пример #4
0
def verify(dnn: OperationGraph, phi: Expression):
    logger = logging.getLogger(__name__)
    dnn = dnn.simplify()
    phi.networks[0].concretize(dnn)

    result = UNSAT
    property_extractor = ConvexPolytopeExtractor()
    with tempfile.TemporaryDirectory() as dirname:
        for prop in property_extractor.extract_from(phi):
            layers = prop.output_constraint.as_layers(
                prop.network, translator_error=ReluplexTranslatorError
            )
            input_interval = prop.input_constraint.as_hyperrectangle()
            nnet_file_name = to_nnet_file(
                input_interval,
                layers,
                dirname=dirname,
                translator_error=ReluplexTranslatorError,
            )
            logger.debug("Running reluplex")
            executor = CommandLineExecutor(
                "reluplex", f"{nnet_file_name}", verifier_error=ReluplexError
            )
            out, err = executor.run()
            logger.debug("Parsing results")
            result |= parse_results(out, err)
            if result == SAT:
                logger.debug("SAT! Validating counter example.")
                validate_counter_example(prop, out, err)
            if result == SAT or result == UNKNOWN:
                return result

    return result
Пример #5
0
def verify(dnn: OperationGraph, phi: Expression):
    dnn = dnn.simplify()
    phi.networks[0].concretize(dnn)

    result = UNSAT
    property_extractor = ConvexPolytopeExtractor()
    with tempfile.TemporaryDirectory() as dirname:
        for prop in property_extractor.extract_from(phi):
            layers = prop.output_constraint.as_layers(
                prop.network,
                extra_layer_types=PLANET_LAYER_TYPES,
                translator_error=PlanetTranslatorError,
            )
            input_interval = prop.input_constraint.as_hyperrectangle()
            rlv_file_name = to_rlv_file(
                input_interval,
                layers,
                dirname=dirname,
                translator_error=PlanetTranslatorError,
            )
            executor = CommandLineExecutor("planet",
                                           f"{rlv_file_name}",
                                           verifier_error=PlanetError)
            out, err = executor.run()
            result |= parse_results(out, err)
            if result == SAT:
                validate_counter_example(prop, out, err)
            if result == SAT or result == UNKNOWN:
                return result

    return result
Пример #6
0
def verify(dnn: OperationGraph, phi: Expression):
    dnn = dnn.simplify()
    phi.networks[0].concretize(dnn)

    result = UNSAT
    property_extractor = HalfspacePolytopePropertyExtractor(
        HyperRectangle, HalfspacePolytope)
    with tempfile.TemporaryDirectory() as dirname:
        for prop in property_extractor.extract_from(~phi):
            if prop.input_constraint.num_variables > 1:
                raise PlanetTranslatorError(
                    "Unsupported network: More than 1 input variable")
            layers = as_layers(
                prop.suffixed_op_graph(),
                extra_layer_types=PLANET_LAYER_TYPES,
                translator_error=PlanetTranslatorError,
            )
            rlv_file_name = to_rlv_file(
                prop.input_constraint,
                layers,
                dirname=dirname,
                translator_error=PlanetTranslatorError,
            )
            executor = CommandLineExecutor("planet",
                                           f"{rlv_file_name}",
                                           verifier_error=PlanetError)
            out, err = executor.run()
            result |= parse_results(out, err)
            if result == SAT:
                validate_counter_example(prop, out, err)
            if result == SAT or result == UNKNOWN:
                return result

    return result
Пример #7
0
def verify(dnn: OperationGraph, phi: Expression, **kwargs):
    dnn = dnn.simplify()
    phi.networks[0].concretize(dnn)

    result = UNSAT
    property_extractor = HalfspacePolytopePropertyExtractor(
        HyperRectangle, HalfspacePolytope
    )
    with tempfile.TemporaryDirectory() as dirname:
        for prop in property_extractor.extract_from(~phi):
            if prop.input_constraint.num_variables > 1:
                raise BabTranslatorError(
                    "Unsupported network: More than 1 input variable"
                )
            layers = as_layers(
                prop.suffixed_op_graph(), translator_error=BabTranslatorError,
            )
            rlv_file_path = to_rlv_file(
                prop.input_constraint,
                layers,
                dirname=dirname,
                translator_error=BabTranslatorError,
            )
            result |= check(rlv_file_path, **kwargs)
            if result == SAT or result == UNKNOWN:
                return result

    return result
Пример #8
0
    def test_a_gt_b(self):
        op_graph = parse(artifact_dir / "a_gt_b.onnx")
        output_op = op_graph.output_operations[0]  # softmax
        prefix = OperationGraph([output_op.x])
        op_graph_suffix = OperationGraph(op_graph.walk(DropPrefix(prefix)))
        x = np.random.normal(size=(10, 2)).astype(np.float32)
        y = op_graph_suffix(x)
        a_gt_b = x[:, 0] > x[:, 1]
        y_0_gt_1 = y[:, 0] > y[:, 1]
        self.assertTrue(np.all(~(a_gt_b ^ y_0_gt_1)))

        prefix_output_op = prefix.output_operations[0]  # gemm
        prefix = OperationGraph([prefix_output_op.a])
        op_graph_suffix = OperationGraph(op_graph.walk(DropPrefix(prefix)))
        x = np.clip(np.random.normal(size=(10, 2)), 0.0,
                    None).astype(np.float32)
        y = op_graph_suffix(x)
        a_gt_b = x[:, 0] > x[:, 1]
        y_0_gt_1 = y[:, 0] > y[:, 1]
        self.assertTrue(np.all(~(a_gt_b ^ y_0_gt_1)))
Пример #9
0
def verify(dnn: OperationGraph,
           phi: Expression,
           domain="deeppoly",
           timeout_lp=1.0,
           timeout_milp=1.0,
           use_area_heuristic=True,
           **kwargs: Dict[str, Any]):
    logger = logging.getLogger(__name__)
    dnn = dnn.simplify()
    phi.networks[0].concretize(dnn)

    result = UNSAT
    property_extractor = HalfspacePolytopePropertyExtractor(
        HyperRectangle, HalfspacePolytope)
    for prop in property_extractor.extract_from(~phi):
        if prop.input_constraint.num_variables > 1:
            raise ERANTranslatorError(
                "Unsupported network: More than 1 input variable")
        with tf.Session(graph=tf.Graph()) as tf_session:
            layers = as_layers(
                prop.suffixed_op_graph(),
                extra_layer_types=ERAN_LAYER_TYPES,
                translator_error=ERANTranslatorError,
            )
            input_interval = prop.input_constraint

            spec_lb = input_interval.lower_bounds[0]
            spec_ub = input_interval.upper_bounds[0]
            if len(spec_lb.shape) == 4:
                spec_lb = spec_lb.transpose((0, 2, 3, 1))
                spec_ub = spec_ub.transpose((0, 2, 3, 1))
            tf_graph = as_tf(layers, translator_error=ERANTranslatorError)
            eran_model = ERAN(tf_graph, session=tf_session)
            _, nn, nlb, nub = eran_model.analyze_box(spec_lb.flatten().copy(),
                                                     spec_ub.flatten().copy(),
                                                     domain, timeout_lp,
                                                     timeout_milp,
                                                     use_area_heuristic,
                                                     **kwargs)
            output_lower_bound = np.asarray(nlb[-1])
            output_upper_bound = np.asarray(nub[-1])
            logger.debug("output lower bound: %s", output_lower_bound)
            logger.debug("output upper bound: %s", output_upper_bound)
            result |= check(output_lower_bound, output_upper_bound)
        if result == SAT or result == UNKNOWN:
            return result

    return result
Пример #10
0
def verify(dnn: OperationGraph, phi: Expression, **kwargs: Dict[str, Any]):
    logger = logging.getLogger(__name__)
    dnn = dnn.simplify()
    phi.networks[0].concretize(dnn)

    result = UNSAT
    property_extractor = HalfspacePolytopePropertyExtractor(
        HyperRectangle, HalfspacePolytope)
    with tempfile.TemporaryDirectory() as dirname:
        for prop in property_extractor.extract_from(~phi):
            if prop.input_constraint.num_variables > 1:
                raise NeurifyTranslatorError(
                    "Unsupported network: More than 1 input variable")
            layers = as_layers(
                prop.suffixed_op_graph(),
                translator_error=NeurifyTranslatorError,
            )
            neurify_inputs = to_neurify_inputs(
                prop.input_constraint,
                layers,
                dirname=dirname,
                translator_error=NeurifyTranslatorError,
            )
            logger.debug("Running neurify")
            executor = CommandLineExecutor(
                "neurify",
                "-n",
                neurify_inputs["nnet_path"],
                "-x",
                neurify_inputs["input_path"],
                "-sl",
                "0.0000000000001",  # TODO: remove magic number
                "-I",
                neurify_inputs["input_interval_path"],
                "-v",
                *[f"--{k}={v}" for k, v in kwargs.items() if v is not None],
                verifier_error=NeurifyError,
            )
            out, err = executor.run()
            logger.debug("Parsing results")
            result |= parse_results(out, err)
            if result == SAT:
                logger.debug("SAT! Validating counter example.")
                validate_counter_example(prop, out, err)
            if result == SAT or result == UNKNOWN:
                return result

    return result
Пример #11
0
def verify(dnn: OperationGraph, phi: Expression, **kwargs: Dict[str, Any]):
    logger = logging.getLogger(__name__)
    dnn = dnn.simplify()
    phi.networks[0].concretize(dnn)

    result = UNSAT
    property_extractor = ConvexPolytopeExtractor()
    with tempfile.TemporaryDirectory() as dirname:
        for prop in property_extractor.extract_from(phi):
            layers = prop.output_constraint.as_layers(
                prop.network, translator_error=NeurifyTranslatorError)
            input_interval = prop.input_constraint.as_hyperrectangle()
            neurify_inputs = to_neurify_inputs(
                input_interval,
                layers,
                dirname=dirname,
                translator_error=NeurifyTranslatorError,
            )
            epsilon = neurify_inputs["epsilon"]
            logger.debug("Running neurify")
            executor = CommandLineExecutor(
                "neurify",
                "-n",
                neurify_inputs["nnet_path"],
                "-x",
                neurify_inputs["input_path"],
                "-sl",
                "0.000000000001",  # TODO: remove magic number
                f"--linf={epsilon}",
                "-v",
                *[f"--{k}={v}" for k, v in kwargs.items() if v is not None],
                verifier_error=NeurifyError,
            )
            out, err = executor.run()
            logger.debug("Parsing results")
            result |= parse_results(out, err)
            if result == SAT:
                logger.debug("SAT! Validating counter example.")
                validate_counter_example(prop, out, err)
            if result == SAT or result == UNKNOWN:
                return result

    return result
Пример #12
0
    def test_resnet50_multi_output(self):
        op_graph = parse(artifact_dir / "resnet50.onnx")

        first_half = op_graph[:83]
        self.assertEqual(len(first_half.output_operations), 2,
                         "Expected 2 output operations.")
        self.assertIsInstance(
            first_half.output_operations[0],
            operations.BatchNormalization,
            "Expected first output operation to be BatchNormalization.",
        )
        self.assertIsInstance(
            first_half.output_operations[1],
            operations.BatchNormalization,
            "Expected second output operation to be BatchNormalization.",
        )
        second_half = op_graph[84:]
        self.assertEqual(len(second_half.output_operations), 1,
                         "Only 1 output operation expected.")
        self.assertIsInstance(
            second_half.output_operations[0],
            operations.Gemm,
            "Expected first slice to end with Gemm.",
        )

        self.assert_composition_equals(
            op_graph,
            (
                first_half,
                OperationGraph([
                    operations.Add(
                        operations.Input((-1, 1024, 14, 14), np.float32),
                        operations.Input((-1, 1024, 14, 14), np.float32),
                    )
                ]),
                second_half,
            ),
        )
Пример #13
0
def verify(dnn: OperationGraph, phi: Expression, **kwargs: Dict[str, Any]):
    logger = logging.getLogger(__name__)
    dnn = dnn.simplify()
    phi.networks[0].concretize(dnn)

    result = UNSAT
    property_extractor = HalfspacePolytopePropertyExtractor(
        HyperRectangle, HalfspacePolytope)
    with tempfile.TemporaryDirectory() as dirname:
        for prop in property_extractor.extract_from(~phi):
            if prop.input_constraint.num_variables > 1:
                raise MIPVerifyTranslatorError(
                    "Unsupported network: More than 1 input variable")
            layers = as_layers(
                prop.suffixed_op_graph(),
                extra_layer_types=MIPVERIFY_LAYER_TYPES,
                translator_error=MIPVerifyTranslatorError,
            )
            mipverify_inputs = to_mipverify_inputs(
                prop.input_constraint,
                layers,
                dirname=dirname,
                translator_error=MIPVerifyTranslatorError,
            )
            logger.debug("Running mipverify")
            executor = CommandLineExecutor(
                "julia",
                mipverify_inputs["property_path"],
                verifier_error=MIPVerifyError,
            )
            out, err = executor.run()
            logger.debug("Parsing results")
            result |= parse_results(out, err)
            if result == SAT or result == UNKNOWN:
                return result

    return result
Пример #14
0
 def merge(self, operation_graphs: List[OperationGraph]):
     for op_graph in operation_graphs:
         for op in op_graph.output_operations:
             self.output_operations.append(self.visit(op))
     return OperationGraph(self.output_operations)