Hybrid quantum - classical function definition
| 45 | |
| 46 | |
| 47 | class QuantumFunction(Function): |
| 48 | """ Hybrid quantum - classical function definition """ |
| 49 | |
| 50 | @staticmethod |
| 51 | def forward(ctx, input, q_circuit, shift): |
| 52 | """ Forward pass computation """ |
| 53 | ctx.shift = shift |
| 54 | ctx.q_circuit = q_circuit |
| 55 | theta_batch = input[0].tolist() |
| 56 | expectation = ctx.q_circuit.run(theta_batch=theta_batch) |
| 57 | result = torch.tensor([expectation]) |
| 58 | ctx.save_for_backward(input, result) |
| 59 | |
| 60 | return result |
| 61 | |
| 62 | @staticmethod |
| 63 | def backward(ctx, grad_output): |
| 64 | """ Backward pass computation """ |
| 65 | input, expectation = ctx.saved_tensors |
| 66 | theta_batch = np.array(input.tolist()) |
| 67 | |
| 68 | shift_right = theta_batch + np.ones(theta_batch.shape) * ctx.shift |
| 69 | shift_left = theta_batch - np.ones(theta_batch.shape) * ctx.shift |
| 70 | |
| 71 | gradients = [] |
| 72 | for i in range(len(theta_batch)): |
| 73 | expectation_right = ctx.q_circuit.run(shift_right[i]) |
| 74 | expectation_left = ctx.q_circuit.run(shift_left[i]) |
| 75 | |
| 76 | gradient = torch.tensor([expectation_right]) - torch.tensor([expectation_left]) |
| 77 | gradients.append(gradient) |
| 78 | gradients = np.array([gradients]).T |
| 79 | return torch.tensor([gradients]).float() * grad_output.float(), None, None |
| 80 | |
| 81 | |
| 82 | class QuantumLayer(nn.Module): |
nothing calls this directly
no outgoing calls
no test coverage detected