예제 #1
0
    def test_plain(self):
        optimizer = L_BFGS_B()
        mp = create_circuit(3, layer_size=2)
        mp_step = mp.copy()
        circuit = qml.QNode(
            plain_variational_circuit,
            device(mp.mask(Axis.WIRES).size),
        )

        def cost_fn(params):
            return plain_cost(
                params,
                circuit,
            )

        base_cost = cost_fn(mp.parameters)
        _params, final_cost, _gradient = optimizer.optimize(
            cost_fn, mp.parameters)
        params, step_cost, _gradient = optimizer.step_cost_and_grad(
            cost_fn, mp_step.parameters)
        assert final_cost < base_cost
        assert step_cost < base_cost
        assert final_cost < step_cost

        new_params = optimizer.step(cost_fn, mp_step.parameters)
        assert pnp.array_equal(params, new_params)
        new_params, new_cost = optimizer.step_and_cost(cost_fn, new_params)
        assert new_cost < step_cost
예제 #2
0
    def test_ensemble(self):
        random.seed(1234)
        pnp.random.seed(1234)
        optimizer = L_BFGS_B()
        ensemble = Ensemble(dropout=RANDOM)
        mp = create_circuit(3, layer_size=2)
        circuit = qml.QNode(variational_circuit,
                            device(mp.mask(Axis.WIRES).size))

        def cost_fn(params, masked_circuit=None):
            return cost(
                params,
                circuit,
                masked_circuit=masked_circuit,
            )

        base_cost = cost_fn(mp.parameters, masked_circuit=mp)
        for _ in range(5):
            result = ensemble.step(
                masked_circuit=mp,
                optimizer=optimizer,
                objective_fn=cost_fn,
                ensemble_steps=1,
            )
            assert result.cost < base_cost
예제 #3
0
    def test_ensemble_step(self, dropout):
        mp = create_circuit(3, layer_size=2)
        optimizer = ExtendedGradientDescentOptimizer()
        circuit = qml.QNode(variational_circuit,
                            device(mp.mask(Axis.WIRES).size))
        ensemble = Ensemble(dropout=dropout)

        def cost_fn(params, masked_circuit=None):
            return cost(
                params,
                circuit,
                masked_circuit,
            )

        # compare for different steps
        current_cost = 1.0
        for steps in range(3):
            random.seed(1234)
            pnp.random.seed(1234)
            result = ensemble.step(mp.copy(),
                                   optimizer,
                                   cost_fn,
                                   ensemble_steps=steps)
            if steps > 0:
                assert result.brutto_steps > result.netto_steps
            else:
                assert result.brutto_steps == 1
                assert result.netto_steps == 1
            assert result.netto_steps == steps + 1
            assert result.cost < current_cost
            current_cost = result.cost
예제 #4
0
    def test_growing(self):
        random.seed(1234)
        pnp.random.seed(1234)
        mp = create_circuit(3, layer_size=2)
        mp.mask(Axis.LAYERS)[1:] = True
        ensemble = Ensemble(dropout=GROWING)
        circuit = qml.QNode(variational_circuit,
                            device(mp.mask(Axis.WIRES).size))
        optimizer = ExtendedGradientDescentOptimizer()

        def cost_fn(params, masked_circuit=None):
            return cost(
                params,
                circuit,
                masked_circuit,
            )

        current_cost = 1.0
        assert pnp.sum(mp.mask(Axis.LAYERS)) == 2
        for _ in range(len(mp.mask(Axis.LAYERS)) - 1):
            result = ensemble.step(mp, optimizer, cost_fn)
            mp = result.branch
            current_cost = result.cost
        assert current_cost == pytest.approx(0.86318044)
        assert pnp.sum(mp.mask(Axis.LAYERS)) == 0
예제 #5
0
    def test_complex(self):
        random.seed(1234)
        pnp.random.seed(1234)
        mp = create_freezable_circuit(3, layer_size=2)
        circuit = qml.QNode(variational_circuit,
                            device(mp.mask(Axis.WIRES).size))
        optimizer = qml.GradientDescentOptimizer()

        def cost_fn(params, masked_circuit=None):
            return cost(
                params,
                circuit,
                masked_circuit,
            )

        mp.perturb(axis=Axis.LAYERS, amount=2, mode=Mode.SET, mask=FreezeMask)
        mp.perturb(axis=Axis.WIRES, amount=2, mode=Mode.SET, mask=FreezeMask)

        last_changeable = pnp.sum(mp.parameters[~mp._accumulated_mask()])
        frozen = pnp.sum(mp.parameters[mp._accumulated_mask()])
        for _ in range(10):
            params = optimizer.step(cost_fn,
                                    mp.differentiable_parameters,
                                    masked_circuit=mp)
            mp.differentiable_parameters = params
            current_changeable = pnp.sum(
                mp.parameters[~mp._accumulated_mask()])
            assert last_changeable - current_changeable != 0
            assert frozen - pnp.sum(mp.parameters[mp._accumulated_mask()]) == 0
            last_changeable = current_changeable
예제 #6
0
    def test_entangling_mask_application(self):
        size = 4
        mp = self._create_circuit_with_entangling_gates(size)
        rotations = [pnp.random.choice([0, 1, 2]) for _ in range(size * size)]
        circuit = qml.QNode(
            original_variational_circuit,
            device(mp.mask(Axis.WIRES).size),
        )

        circuit(mp.differentiable_parameters, rotations, mp)
        assert (qml.specs(circuit)(mp.differentiable_parameters, rotations,
                                   mp)["gate_types"]["CZ"] == 12)

        mp.perturb(axis=Axis.ENTANGLING, mode=Mode.SET, amount=6)
        circuit(mp.differentiable_parameters, rotations, mp)
        assert (qml.specs(circuit)(mp.differentiable_parameters, rotations,
                                   mp)["gate_types"]["CZ"] == 6)
예제 #7
0
    def test_step(self, dropout):
        random.seed(1234)
        pnp.random.seed(1234)
        mp = create_circuit(3, layer_size=2)
        optimizer = ExtendedGradientDescentOptimizer()
        circuit = qml.QNode(variational_circuit,
                            device(mp.mask(Axis.WIRES).size))
        simple_ensemble = Ensemble(dropout=None)
        adaptive_ensemble = AdaptiveEnsemble(dropout=dropout,
                                             size=3,
                                             epsilon=0.01)

        def cost_fn(params, masked_circuit=None):
            return cost(
                params,
                circuit,
                masked_circuit,
            )

        # train for four steps and assert that interval ensemble is better
        simple_costs = []
        simple_mp = mp.copy()
        for _ in range(4):
            result = simple_ensemble.step(simple_mp,
                                          optimizer,
                                          cost_fn,
                                          ensemble_steps=1)
            simple_mp = result.branch
            simple_costs.append(result.cost)
        adaptive_mp = mp.copy()
        for i in range(3):
            result = adaptive_ensemble.step(adaptive_mp,
                                            optimizer,
                                            cost_fn,
                                            ensemble_steps=1)
            adaptive_mp = result.branch
            assert simple_costs[i] == result.cost
        # last step should be better
        result = adaptive_ensemble.step(adaptive_mp,
                                        optimizer,
                                        cost_fn,
                                        ensemble_steps=1)
        assert simple_costs[-1] > result.cost
예제 #8
0
    def test_step(self, dropout):
        interval = 3
        mp = create_circuit(3, layer_size=2)
        optimizer = ExtendedGradientDescentOptimizer()
        circuit = qml.QNode(variational_circuit,
                            device(mp.mask(Axis.WIRES).size))
        simple_ensemble = Ensemble(dropout=None)
        interval_ensemble = IntervalEnsemble(dropout=dropout,
                                             interval=interval)

        def cost_fn(params, masked_circuit=None):
            return cost(
                params,
                circuit,
                masked_circuit,
            )

        # train for three steps and assert that interval ensemble is better
        simple_costs = []
        simple_mp = mp.copy()
        for _ in range(interval):
            result = simple_ensemble.step(simple_mp,
                                          optimizer,
                                          cost_fn,
                                          ensemble_steps=1)
            simple_mp = result.branch
            simple_costs.append(result.cost)
        interval_mp = mp.copy()
        for i in range(interval - 1):
            result = interval_ensemble.step(interval_mp,
                                            optimizer,
                                            cost_fn,
                                            ensemble_steps=1)
            interval_mp = result.branch
            assert simple_costs[i] == result.cost
        # last step should be better
        result = interval_ensemble.step(interval_mp,
                                        optimizer,
                                        cost_fn,
                                        ensemble_steps=1)
        assert simple_costs[-1] > result.cost
예제 #9
0
    def test_mask(self):
        optimizer = L_BFGS_B()
        mp = create_circuit(3, layer_size=2)
        mp_step = mp.copy()
        circuit = qml.QNode(variational_circuit,
                            device(mp.mask(Axis.WIRES).size))

        def cost_fn(params, masked_circuit=None):
            return cost(
                params,
                circuit,
                masked_circuit=masked_circuit,
            )

        base_cost = cost_fn(mp.parameters, masked_circuit=mp)
        _params, final_cost, _gradient = optimizer.optimize(
            cost_fn, mp.differentiable_parameters, masked_circuit=mp)
        params, step_cost, _gradient = optimizer.step_cost_and_grad(
            cost_fn, mp_step.differentiable_parameters, masked_circuit=mp_step)
        assert final_cost < base_cost
        assert step_cost < base_cost
        assert final_cost < step_cost
예제 #10
0
    def test_shape(self):
        optimizer = L_BFGS_B()
        original_optimizer = ExtendedGradientDescentOptimizer()
        mp = create_circuit(3, layer_size=2)
        mp_original = mp.copy()
        circuit = qml.QNode(
            plain_variational_circuit,
            device(mp.mask(Axis.WIRES).size),
        )

        def cost_fn(params):
            return plain_cost(
                params,
                circuit,
            )

        params, _cost, _gradient = optimizer.step_cost_and_grad(
            cost_fn, mp.parameters)
        original_params, _cost, _gradient = original_optimizer.step_cost_and_grad(
            cost_fn, mp_original.parameters)
        assert mp.parameters.shape == params.shape
        assert original_params.shape == params.shape
예제 #11
0
    def test_qhack(self):
        random.seed(1234)
        pnp.random.seed(1234)
        mp = create_circuit(3, layer_size=2)
        ensemble = Ensemble(dropout=QHACK)
        circuit = qml.QNode(variational_circuit,
                            device(mp.mask(Axis.WIRES).size))
        optimizer = ExtendedGradientDescentOptimizer()

        def cost_fn(params, masked_circuit=None):
            return cost(
                params,
                circuit,
                masked_circuit,
            )

        current_cost = 1.0
        for _ in range(10):
            result = ensemble.step(mp, optimizer, cost_fn)
            mp = result.branch
            current_cost = result.cost
        assert current_cost == pytest.approx(0.63792393)