Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions samples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ endfunction()

add_application(circuit_test circuit_test.cpp)
add_application(observable_test observable_test.cpp)
add_application(target_test target_test.cpp)

if(QRMI_ROOT OR QISKIT_IBM_RUNTIME_C_ROOT OR SQC_ROOT)
add_application(sampler_test sampler_test.cpp)
Expand Down
60 changes: 60 additions & 0 deletions samples/target_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
# This code is part of Qiskit.
#
# (C) Copyright IBM 2024.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
*/

// Test program for local target

#define _USE_MATH_DEFINES
#include <iostream>
#include <cstdint>
#include <cstdlib>
#include <cmath>

#include "circuit/quantumcircuit.hpp"
#include "transpiler/target.hpp"
#include "transpiler/passmanager.hpp"
#include "transpiler/preset_passmanagers/generate_preset_pass_manager.hpp"

using namespace Qiskit::circuit;
using namespace Qiskit::transpiler;

int main()
{
QuantumRegister qr(4);
ClassicalRegister cr(4);
QuantumCircuit circ(qr, cr);

circ.h(0);
for (int i=1;i<4;i++) {
circ.cx(0, i);
}
for (int i=0;i<4;i++) {
circ.measure(i,i);
}

std::cout << "input circuit" << std::endl;
circ.print();


auto target = Target({"h", "cx"}, {{0, 1}, {1, 0}, {1, 3}, {3, 1}, {0, 2}, {2, 0}, {2, 3}, {3, 2}});
// auto target = Target({"cz", "id", "rx", "rz", "rzz", "sx", "x"}, {{0, 1}, {1, 0}, {1, 3}, {3, 1}, {0, 2}, {2, 0}, {2, 3}, {3, 2}});
auto pass = StagedPassManager({"init", "layout", "routing", "translation", "optimization"}, target);
//auto pass = generate_preset_pass_manager(2, {"h", "cx"}, {{0, 1}, {1, 0}, {1, 3}, {3, 1}, {0, 2}, {2, 0}, {2, 3}, {3, 2}}, 1.0, 1);
auto transpiled = pass.run(circ);

std::cout << "transpiled circuit" << std::endl;
transpiled.print();

return 0;
}

4 changes: 2 additions & 2 deletions src/circuit/controlflow/control_flow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class ControlFlowOp
{
protected:
// TO DO : this is temporary, make condition class to handle multiple conditions
Expr expr_;
//Expr expr_;
uint32_t clbit_;
uint32_t value_;
public:
Expand All @@ -44,7 +44,7 @@ class ControlFlowOp

/// @brief Create a new instruction.
/// @param (expr) expression
ControlFlowOp(Expr expr) : expr_(expr) {}
//ControlFlowOp(Expr expr) : expr_(expr) {}

virtual void add_control_flow_op(QuantumCircuit& circ) = 0;
};
Expand Down
14 changes: 11 additions & 3 deletions src/circuit/quantumcircuit_def.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@

#include "utils/types.hpp"
#include "circuit/parameter.hpp"
#include "circuit/classical/expr.hpp"
//#include "circuit/classical/expr.hpp"
#include "circuit/classicalregister.hpp"
#include "circuit/quantumregister.hpp"
#include "circuit/library/standard_gates/standard_gates.hpp"
#include "circuit/circuitinstruction.hpp"
#include "transpiler/target.hpp"

#include <complex>
#include "qiskit.h"
Expand Down Expand Up @@ -156,7 +155,7 @@ class QuantumCircuit
/// @param circ smart pointer to RUst circuit
/// @param map layout mapping
void set_qiskit_circuit(std::shared_ptr<rust_circuit> circ, const std::vector<uint32_t> &map);

/// @brief get qubit mapping
/// @return qubit mapping
const reg_t &get_qubit_map(void)
Expand Down Expand Up @@ -690,6 +689,15 @@ class QuantumCircuit
/// @brief print circuit (this is for debug)
void print(void) const;


/// @brief compare two circuits
/// @param other a circuit to be compared with this circuit
/// @return true if two circuits are the same
bool operator==(const QuantumCircuit& other) const;
bool operator!=(const QuantumCircuit& other) const
{
return !(*this == other);
}
protected:
void add_pending_control_flow_op(void);

Expand Down
63 changes: 63 additions & 0 deletions src/circuit/quantumcircuit_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@

#include <memory>
#include <functional>
#include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>
#include <cstring>
#include <cassert>

#include "controlflow/__init__.hpp"

Expand Down Expand Up @@ -1583,6 +1587,65 @@ std::string QuantumCircuit::to_qasm3(void)
return qasm3.str();
}


bool QuantumCircuit::operator==(const QuantumCircuit& other) const
{
if (global_phase_ != other.global_phase_) {
return false;
}

// compare instructions
uint_t nops;
uint_t nops_other;
nops = qk_circuit_num_instructions(rust_circuit_.get());
nops_other = qk_circuit_num_instructions(other.rust_circuit_.get());
if (nops != nops_other) {
return false;
}

for (uint_t i = 0; i < nops; i++) {
QkCircuitInstruction *op = new QkCircuitInstruction;
QkCircuitInstruction *op_other = new QkCircuitInstruction;
qk_circuit_get_instruction(rust_circuit_.get(), i, op);
qk_circuit_get_instruction(other.rust_circuit_.get(), i, op_other);

if (std::string(op->name) != std::string(op_other->name)) {
qk_circuit_instruction_clear(op);
qk_circuit_instruction_clear(op_other);
return false;
}
if (op->num_qubits != op_other->num_qubits || op->num_clbits != op_other->num_clbits || op->num_params != op_other->num_params) {
qk_circuit_instruction_clear(op);
qk_circuit_instruction_clear(op_other);
return false;
}
for (int j = 0; j < op->num_qubits; j++) {
if (op->qubits[j] != op_other->qubits[j]) {
qk_circuit_instruction_clear(op);
qk_circuit_instruction_clear(op_other);
return false;
}
}
for (int j = 0; j < op->num_params; j++) {
if (op->params[j] != op_other->params[j]) {
qk_circuit_instruction_clear(op);
qk_circuit_instruction_clear(op_other);
return false;
}
}
for (int j = 0; j < op->num_clbits; j++) {
if (op->clbits[j] != op_other->clbits[j]) {
qk_circuit_instruction_clear(op);
qk_circuit_instruction_clear(op_other);
return false;
}
}
}
return true;
}



} // namespace circuit
} // namespace Qiskit

Expand Down
17 changes: 7 additions & 10 deletions src/compiler/transpiler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ namespace compiler {
circuit::QuantumCircuit transpile(circuit::QuantumCircuit &circ, providers::BackendV2 &backend, int optimization_level = 2, double approximation_degree = 1.0, int seed_transpiler = -1)
{
auto target = backend.target();
if (target == nullptr)
{
return circ;
auto capi_target = target.rust_target();
if (capi_target == nullptr) {
std::cerr << "transpile error : Target object for the backend is not valid." << std::endl;
return circ.copy();
}

QkTranspileOptions options = qk_transpiler_default_options();
Expand All @@ -47,12 +48,10 @@ circuit::QuantumCircuit transpile(circuit::QuantumCircuit &circ, providers::Back
QkTranspileResult result;
char *error;

QkExitCode ret = qk_transpile(circ.get_rust_circuit().get(), target->rust_target(), &options, &result, &error);
if (ret != QkExitCode_Success)
{
QkExitCode ret = qk_transpile(circ.get_rust_circuit().get(), capi_target, &options, &result, &error);
if (ret != QkExitCode_Success) {
std::cerr << "transpile error (" << ret << ") : " << error << std::endl;
target.reset();
return circ;
return circ.copy();
}

// save qubit map after transpile
Expand All @@ -63,8 +62,6 @@ circuit::QuantumCircuit transpile(circuit::QuantumCircuit &circ, providers::Back
transpiled.set_qiskit_circuit(std::shared_ptr<rust_circuit>(result.circuit, qk_circuit_free), layout_map);

qk_transpile_layout_free(result.layout);
target.reset();

return transpiled;
}

Expand Down
1 change: 1 addition & 0 deletions src/primitives/backend_sampler_job.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#define __qiskitcpp_primitives_qrmi_qiskit_ibm_runtime_job_def_hpp__

#ifdef _MSC_VER
#define NOMINMAX
#include <windows.h>
#else
#include <thread>
Expand Down
2 changes: 1 addition & 1 deletion src/providers/backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class BackendV2 {

/// @brief Return a target properties for this backend
/// @return a target class
virtual std::shared_ptr<transpiler::Target> target(void) = 0;
virtual const transpiler::Target& target(void) = 0;

/// @brief Run and collect samples from each pub.
/// @param pubs An iterable of pub-like objects.
Expand Down
12 changes: 5 additions & 7 deletions src/providers/qkrt_backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class QkrtBackend : public BackendV2 {
std::string primitive_name_ = "sampler";
qkrt_Backend* backend_ = nullptr;
std::shared_ptr<qkrt_Service> service_;
std::shared_ptr<transpiler::Target> target_ = nullptr;
transpiler::Target target_;
public:
/// @brief Create a new QkrtBackend
QkrtBackend() {}
Expand Down Expand Up @@ -72,24 +72,22 @@ class QkrtBackend : public BackendV2 {
{
if (service_)
service_.reset();
if (target_)
target_.reset();
}

/// @brief Return a target properties for this backend
/// @return a target class
std::shared_ptr<transpiler::Target> target(void) override
const transpiler::Target& target(void) override
{
if (target_) {
if (target_.is_set()) {
return target_;
}

QkTarget *target = qkrt_get_backend_target(service_.get(), backend_);
if (target == nullptr) {
std::cerr << "ERROR: failed to get target for the backend " << name_ << std::endl;
return nullptr;
return target_;
}
target_ = std::make_shared<transpiler::Target>(target);
target_ = transpiler::Target(target);
return target_;
}

Expand Down
13 changes: 6 additions & 7 deletions src/providers/qrmi_backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class QRMIBackend : public BackendV2 {
std::string primitive_name_ = "sampler";
std::string acc_token_;
std::shared_ptr<QrmiQuantumResource> qrmi_ = nullptr;
std::shared_ptr<transpiler::Target> target_ = nullptr;
transpiler::Target target_;
public:
/// @brief Create a new QRMIBackend
QRMIBackend() {}
Expand Down Expand Up @@ -68,22 +68,21 @@ class QRMIBackend : public BackendV2 {

/// @brief Return a target properties for this backend
/// @return a target class
std::shared_ptr<transpiler::Target> target(void) override
const transpiler::Target& target(void) override
{
if (target_) {
if (target_.is_set()) {
return target_;
}
transpiler::Target target;

char *target_str = NULL;
QrmiReturnCode rc = qrmi_resource_target(qrmi_.get(), &target_str);
if (rc != QRMI_RETURN_CODE_SUCCESS) {
return nullptr;
return target_;
}
nlohmann::ordered_json json_target = nlohmann::ordered_json::parse(target_str);
qrmi_string_free((char *)target_str);
target_ = std::make_shared<transpiler::Target>();
target_->from_json(json_target);
target_ = transpiler::Target();
target_.from_json(json_target);
return target_;
}

Expand Down
17 changes: 8 additions & 9 deletions src/providers/sqc_backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ std::string replace_all(std::string s, const std::string& from, const std::strin
class SQCBackend : public BackendV2 {
private:
const sqcBackend backend_type_;
std::shared_ptr<transpiler::Target> target_;
transpiler::Target target_;

public:
/// @brief Create a new SQCBackend. Internally this initializes SQC.
Expand All @@ -64,27 +64,26 @@ class SQCBackend : public BackendV2 {

/// @brief Return a target properties for this backend.
/// @return a target class (nullptr)
std::shared_ptr<transpiler::Target> target(void) override
const transpiler::Target& target(void) override
{
if(target_) return target_;
if (target_.is_set()) {
return target_;
}

// Create a dummy circuit to get target json files
std::unique_ptr<sqcQC, decltype(&sqcDestroyQuantumCircuit)> qc_handle(sqcQuantumCircuit(0), &sqcDestroyQuantumCircuit);
if(sqcIbmdTranspileInfo(qc_handle.get(), backend_type_) != SQC_RESULT_OK) {
std::cerr << "Failed to get the target information" << std::endl;
return nullptr;
return target_;
}

nlohmann::ordered_json target_json;
target_json["configuration"] = nlohmann::ordered_json::parse(qc_handle->backend_config_json);
target_json["properties"] = nlohmann::ordered_json::parse(qc_handle->backend_props_json);
auto target = std::make_shared<transpiler::Target>();
if(!target->from_json(target_json)) {
target_ = transpiler::Target();
if(!target_.from_json(target_json)) {
std::cerr << "Failed to create a target from json files" << std::endl;
return nullptr;
}
target_ = target;

return target_;
}

Expand Down
1 change: 1 addition & 0 deletions src/service/qiskit_runtime_service_c.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "providers/qkrt_backend.hpp"

#ifdef _MSC_VER
#define NOMINMAX
#include <windows.h>
#else
#include <thread>
Expand Down
1 change: 1 addition & 0 deletions src/service/qiskit_runtime_service_qrmi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "providers/qrmi_backend.hpp"

#ifdef _MSC_VER
#define NOMINMAX
#include <windows.h>
#else
#include <thread>
Expand Down
Loading