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
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
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
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
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
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)
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
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
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
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
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)