in tensorflow_quantum/core/src/program_resolution.cc [85:180]
Status ResolveQubitIds(Program* program, unsigned int* num_qubits,
std::vector<PauliSum>* p_sums /*=nullptr*/,
bool swap_endianness /*=false*/) {
if (program->circuit().moments().empty()) {
// (#679) Just ignore empty program.
// Number of qubits in empty programs is zero.
*num_qubits = 0;
return Status::OK();
}
absl::flat_hash_set<std::pair<std::pair<int, int>, std::string>> id_set;
for (const Moment& moment : program->circuit().moments()) {
for (const Operation& operation : moment.operations()) {
Status s;
for (const Qubit& qubit : operation.qubits()) {
s = RegisterQubits(qubit.id(), &id_set);
if (!s.ok()) {
return s;
}
}
s = RegisterQubits(
operation.args().at("control_qubits").arg_value().string_value(),
&id_set);
if (!s.ok()) {
return s;
}
}
}
*num_qubits = id_set.size();
// call to std::sort will do (r1 < r2) || ((r1 == r2) && c1 < c2)
std::vector<std::pair<std::pair<int, int>, std::string>> ids(id_set.begin(),
id_set.end());
std::sort(ids.begin(), ids.end());
// reverse endian.
if (swap_endianness) {
std::reverse(ids.begin(), ids.end());
}
absl::flat_hash_map<std::string, std::string> id_to_index;
for (size_t i = 0; i < ids.size(); i++) {
id_to_index[ids[i].second] = absl::StrCat(i);
}
// Replace the Program Qubit ids with the indices.
for (Moment& moment : *program->mutable_circuit()->mutable_moments()) {
for (Operation& operation : *moment.mutable_operations()) {
// Resolve qubit ids.
for (Qubit& qubit : *operation.mutable_qubits()) {
qubit.set_id(id_to_index.at(qubit.id()));
}
// reverse endian.
if (swap_endianness) {
std::reverse(operation.mutable_qubits()->begin(),
operation.mutable_qubits()->end());
}
// Resolve control qubit ids found in the control_qubits arg.
absl::string_view control_qubits =
operation.args().at("control_qubits").arg_value().string_value();
// explicit empty value set in serializer.py.
if (control_qubits.empty()) {
continue;
}
std::vector<absl::string_view> control_ids =
absl::StrSplit(control_qubits, ',');
std::vector<std::string> control_indexs;
control_indexs.reserve(control_ids.size());
for (auto id : control_ids) {
control_indexs.push_back(id_to_index.at(id));
}
operation.mutable_args()
->at("control_qubits")
.mutable_arg_value()
->set_string_value(absl::StrJoin(control_indexs, ","));
}
}
if (p_sums) {
for (size_t i = 0; i < p_sums->size(); i++) {
// Replace the PauliSum Qubit ids with the indices.
for (PauliTerm& term : *(p_sums->at(i)).mutable_terms()) {
for (PauliQubitPair& pair : *term.mutable_paulis()) {
const auto result = id_to_index.find(pair.qubit_id());
if (result == id_to_index.end()) {
return Status(
tensorflow::error::INVALID_ARGUMENT,
"Found a Pauli sum operating on qubits not found in circuit.");
}
pair.set_qubit_id(result->second);
}
}
}
}
return Status::OK();
}