Skip to content

Commit ee12f8d

Browse files
authored
Merge pull request #529 from tensorflow/bf_channel
Added BF channel support.
2 parents 6e67c0e + 91c4d8a commit ee12f8d

File tree

5 files changed

+101
-2
lines changed

5 files changed

+101
-2
lines changed

tensorflow_quantum/core/serialize/serializer.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,37 @@ def _phase_flip_channel_deserializer():
398398
args=args)
399399

400400

401+
def _bit_flip_channel_serializer():
402+
"""Make standard serializer for BitFlip channel."""
403+
args = [
404+
# cirq channels can't contain symbols.
405+
cirq.google.SerializingArg(serialized_name="p",
406+
serialized_type=float,
407+
op_getter=lambda x: x.gate.p),
408+
cirq.google.SerializingArg(serialized_name="control_qubits",
409+
serialized_type=str,
410+
op_getter=lambda x: ''),
411+
cirq.google.SerializingArg(serialized_name="control_values",
412+
serialized_type=str,
413+
op_getter=lambda x: '')
414+
]
415+
return cirq.google.GateOpSerializer(gate_type=cirq.BitFlipChannel,
416+
serialized_gate_id="BF",
417+
args=args,
418+
can_serialize_predicate=_CONSTANT_TRUE)
419+
420+
421+
def _bit_flip_channel_deserializer():
422+
"""Make standard deserializer for BitFlip channel."""
423+
args = [
424+
cirq.google.DeserializingArg(serialized_name="p",
425+
constructor_arg_name="p")
426+
]
427+
return cirq.google.GateOpDeserializer(serialized_gate_id="BF",
428+
gate_constructor=cirq.BitFlipChannel,
429+
args=args)
430+
431+
401432
# Gates.
402433
def _eigen_gate_serializer(gate_type, serialized_id):
403434
"""Make standard serializer for eigen gates."""
@@ -699,6 +730,7 @@ def _scalar_combiner(exponent, global_shift, exponent_scalar,
699730
] + [
700731
_amplitude_damp_channel_serializer(),
701732
_asymmetric_depolarize_serializer(),
733+
_bit_flip_channel_serializer(),
702734
_depolarize_channel_serializer(),
703735
_fsim_gate_serializer(),
704736
_gad_channel_serializer(),
@@ -717,6 +749,7 @@ def _scalar_combiner(exponent, global_shift, exponent_scalar,
717749
] + [
718750
_amplitude_damp_channel_deserializer(),
719751
_asymmetric_depolarize_deserializer(),
752+
_bit_flip_channel_deserializer(),
720753
_depolarize_channel_deserializer(),
721754
_fsim_gate_deserializer(),
722755
_gad_channel_deserializer(),

tensorflow_quantum/core/serialize/serializer_test.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,11 @@ def _get_noise_proto_pairs():
432432

433433
# Phase flip.
434434
(cirq.Circuit(cirq.phase_flip(p=0.1)(q0)),
435-
_build_op_proto("PF", ['p'], [0.1], ['0_0']))
435+
_build_op_proto("PF", ['p'], [0.1], ['0_0'])),
436+
437+
# Bit flip.
438+
(cirq.Circuit(cirq.bit_flip(p=0.1)(q0)),
439+
_build_op_proto("BF", ['p'], [0.1], ['0_0']))
436440
]
437441
return pairs
438442

tensorflow_quantum/core/src/circuit_parser_qsim.cc

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,26 @@ inline Status PhaseFlipChannel(const Operation& op,
738738
return Status::OK();
739739
}
740740

741+
inline Status BitFlipChannel(const Operation& op, const unsigned int num_qubits,
742+
const unsigned int time,
743+
NoisyQsimCircuit* ncircuit) {
744+
int q;
745+
bool unused;
746+
float p;
747+
Status u;
748+
unused = absl::SimpleAtoi(op.qubits(0).id(), &q);
749+
750+
u = ParseProtoArg(op, "p", {}, &p);
751+
if (!u.ok()) {
752+
return u;
753+
}
754+
755+
auto chan =
756+
qsim::Cirq::BitFlipChannel<float>::Create(time, num_qubits - q - 1, p);
757+
ncircuit->channels.push_back(chan);
758+
return Status::OK();
759+
}
760+
741761
tensorflow::Status ParseAppendChannel(const Operation& op,
742762
const unsigned int num_qubits,
743763
const unsigned int time,
@@ -750,7 +770,7 @@ tensorflow::Status ParseAppendChannel(const Operation& op,
750770
{"DP", &DepolarizingChannel}, {"ADP", &AsymmetricDepolarizingChannel},
751771
{"GAD", &GADChannel}, {"AD", &AmplitudeDampingChannel},
752772
{"RST", &ResetChannel}, {"PD", &PhaseDampingChannel},
753-
{"PF", &PhaseFlipChannel}};
773+
{"PF", &PhaseFlipChannel}, {"BF", &BitFlipChannel}};
754774

755775
auto build_f = chan_func_map.find(op.gate().id());
756776
if (build_f == chan_func_map.end()) {

tensorflow_quantum/core/src/circuit_parser_qsim_test.cc

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1495,6 +1495,42 @@ TEST(QsimCircuitParserTest, PhaseFlip) {
14951495
ASSERT_EQ(test_circuit.num_qubits, 1);
14961496
}
14971497

1498+
TEST(QsimCircuitParserTest, BitFlip) {
1499+
float p = 0.1234;
1500+
auto reference = qsim::Cirq::BitFlipChannel<float>::Create(0, 0, p);
1501+
Program program_proto;
1502+
Circuit* circuit_proto = program_proto.mutable_circuit();
1503+
circuit_proto->set_scheduling_strategy(circuit_proto->MOMENT_BY_MOMENT);
1504+
Moment* moments_proto = circuit_proto->add_moments();
1505+
1506+
// Add channel.
1507+
Operation* operations_proto = moments_proto->add_operations();
1508+
Gate* gate_proto = operations_proto->mutable_gate();
1509+
gate_proto->set_id("BF");
1510+
1511+
// Set the args.
1512+
google::protobuf::Map<std::string, Arg>* args_proto =
1513+
operations_proto->mutable_args();
1514+
(*args_proto)["p"] = MakeArg(p);
1515+
1516+
// Set the control args.
1517+
(*args_proto)["control_qubits"] = MakeControlArg("");
1518+
(*args_proto)["control_values"] = MakeControlArg("");
1519+
1520+
// Set the qubits.
1521+
Qubit* qubits_proto = operations_proto->add_qubits();
1522+
qubits_proto->set_id("0");
1523+
1524+
NoisyQsimCircuit test_circuit;
1525+
1526+
ASSERT_EQ(
1527+
NoisyQsimCircuitFromProgram(program_proto, {}, 1, false, &test_circuit),
1528+
tensorflow::Status::OK());
1529+
AssertChannelEqual(test_circuit.channels[0], reference);
1530+
ASSERT_EQ(test_circuit.channels.size(), 1);
1531+
ASSERT_EQ(test_circuit.num_qubits, 1);
1532+
}
1533+
14981534
TEST(QsimCircuitParserTest, NoisyEmpty) {
14991535
Program program_proto;
15001536
Circuit* circuit_proto = program_proto.mutable_circuit();

tensorflow_quantum/python/util.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
cirq.ResetChannel,
3636
cirq.PhaseDampingChannel,
3737
cirq.PhaseFlipChannel,
38+
cirq.BitFlipChannel,
3839
]
3940

4041

@@ -84,6 +85,7 @@ def get_supported_channels():
8485
channel_mapping[cirq.ResetChannel()] = 1
8586
channel_mapping[cirq.PhaseDampingChannel(0.01)] = 1
8687
channel_mapping[cirq.PhaseFlipChannel(0.01)] = 1
88+
channel_mapping[cirq.BitFlipChannel(0.01)] = 1
8789

8890
return channel_mapping
8991

@@ -534,6 +536,10 @@ def _channel_approx_eq(op_true, op_deser, atol=1e-5):
534536
if isinstance(op_deser, cirq.PhaseFlipChannel):
535537
return abs(op_true.p - op_deser.p) < atol
536538

539+
if isinstance(op_true, cirq.BitFlipChannel):
540+
if isinstance(op_deser, cirq.BitFlipChannel):
541+
return abs(op_true.p - op_deser.p) < atol
542+
537543
return False
538544

539545

0 commit comments

Comments
 (0)