Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
ORNL Quantum Computing Institute
xacc
Commits
5fb42d71
Unverified
Commit
5fb42d71
authored
Aug 09, 2021
by
Mccaskey, Alex
Committed by
GitHub
Aug 09, 2021
Browse files
Merge pull request #476 from tnguyen-ornl/tnguyen/getNativeCode
First pass of implementing Accelerator::getNativeCode
parents
f820332d
c61dbb6d
Pipeline
#158333
failed with stage
in 11 minutes and 51 seconds
Changes
6
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
python/examples/ibm_get_native_code.py
0 → 100644
View file @
5fb42d71
import
xacc
xacc
.
qasm
(
'''
.compiler xasm
.circuit iterative_qpe
.qbit q
H(q[0]);
X(q[1]);
// Prepare the state:
CPhase(q[0], q[1], -5*pi/8);
CPhase(q[0], q[1], -5*pi/8);
CPhase(q[0], q[1], -5*pi/8);
CPhase(q[0], q[1], -5*pi/8);
CPhase(q[0], q[1], -5*pi/8);
CPhase(q[0], q[1], -5*pi/8);
CPhase(q[0], q[1], -5*pi/8);
CPhase(q[0], q[1], -5*pi/8);
H(q[0]);
// Measure and reset
Measure(q[0], c[0]);
Reset(q[0]);
H(q[0]);
CPhase(q[0], q[1], -5*pi/8);
CPhase(q[0], q[1], -5*pi/8);
CPhase(q[0], q[1], -5*pi/8);
CPhase(q[0], q[1], -5*pi/8);
// Conditional rotation
if(c[0]) {
Rz(q[0], -pi/2);
}
H(q[0]);
Measure(q[0], c[1]);
Reset(q[0]);
H(q[0]);
CPhase(q[0], q[1], -5*pi/8);
CPhase(q[0], q[1], -5*pi/8);
if(c[0]) {
Rz(q[0], -pi/4);
}
if(c[1]) {
Rz(q[0], -pi/2);
}
H(q[0]);
Measure(q[0], c[2]);
Reset(q[0]);
H(q[0]);
CPhase(q[0], q[1], -5*pi/8);
if(c[0]) {
Rz(q[0], -pi/8);
}
if(c[1]) {
Rz(q[0], -pi/4);
}
if(c[2]) {
Rz(q[0], -pi/2);
}
H(q[0]);
Measure(q[0], c[3]);
'''
)
f
=
xacc
.
getCompiled
(
'iterative_qpe'
)
qpu
=
xacc
.
getAccelerator
(
'ibm:ibmq_manhattan'
)
# Note: this QASM represents the circuit in the *native* gateset of the backend:
# e.g. {sx, rz, cx}
print
(
'HOWDY QASM:
\n
'
,
qpu
.
getNativeCode
(
f
,
{
'format'
:
'qasm'
}))
# we can also see the native circuit as a QObj json
print
(
'HOWDY QObj:
\n
'
,
qpu
.
getNativeCode
(
f
,
{
'format'
:
'QObj'
}))
# Make sure the native QASM is valid by recompiling with Qiskit.
from
qiskit
import
QuantumCircuit
qiskit_qc
=
QuantumCircuit
.
from_qasm_str
(
qpu
.
getNativeCode
(
f
,
{
'format'
:
'qasm'
}))
qiskit_qc
.
draw
()
python/py_accelerator.cpp
View file @
5fb42d71
...
...
@@ -112,6 +112,24 @@ void bind_accelerator(py::module &m) {
xacc
::
Accelerator
::
updateConfiguration
,
""
)
.
def
(
"getConnectivity"
,
&
xacc
::
Accelerator
::
getConnectivity
,
""
)
.
def
(
"getNativeCode"
,
[](
xacc
::
Accelerator
&
qpu
,
std
::
shared_ptr
<
CompositeInstruction
>
f
)
{
return
qpu
.
getNativeCode
(
f
);
},
""
)
.
def
(
"getNativeCode"
,
[](
xacc
::
Accelerator
&
qpu
,
std
::
shared_ptr
<
CompositeInstruction
>
f
,
PyHeterogeneousMap
&
options
)
{
HeterogeneousMap
m
;
for
(
auto
&
item
:
options
)
{
PyHeterogeneousMap2HeterogeneousMap
vis
(
m
,
item
.
first
);
mpark
::
visit
(
vis
,
item
.
second
);
}
return
qpu
.
getNativeCode
(
f
,
m
);
},
""
)
.
def
(
"configurationKeys"
,
&
xacc
::
Accelerator
::
configurationKeys
,
""
)
.
def
(
"contributeInstructions"
,
&
xacc
::
Accelerator
::
contributeInstructions
,
""
);
...
...
quantum/plugins/ibm/accelerator/IBMAccelerator.cpp
View file @
5fb42d71
...
...
@@ -1237,6 +1237,125 @@ void IBMAccelerator::put(const std::string &_url, const std::string &postStr,
return
;
}
std
::
string
IBMAccelerator
::
getNativeCode
(
std
::
shared_ptr
<
CompositeInstruction
>
program
,
const
HeterogeneousMap
&
config
)
{
std
::
string
format
=
"QObj"
;
// QObj/QASM
if
(
config
.
stringExists
(
"format"
))
{
format
=
config
.
getString
(
"format"
);
}
// Handle different ways to specify the format:
if
(
format
==
"QObj"
||
format
==
"QOBJ"
||
format
==
"JSON"
)
{
chosenBackend
=
availableBackends
[
backend
];
auto
connectivity
=
getConnectivity
();
// Get the correct QObject Generator
auto
qobjGen
=
xacc
::
getService
<
QObjGenerator
>
(
mode
);
// Generate the QObject JSON
auto
jsonStr
=
qobjGen
->
getQObjJsonStr
(
{
program
},
shots
,
chosenBackend
,
getBackendPropsResponse
,
connectivity
,
json
::
parse
(
defaults_response
));
return
jsonStr
;
}
else
if
(
format
==
"qasm"
||
format
==
"Qasm"
||
format
==
"QASM"
||
format
==
"OpenQASM"
||
format
==
"OPENQASM"
)
{
chosenBackend
=
availableBackends
[
backend
];
const
auto
basis_gates
=
chosenBackend
[
"basis_gates"
].
get
<
std
::
vector
<
std
::
string
>>
();
// If the gate set has "u3" -> old gateset.
const
auto
gateSet
=
(
xacc
::
container
::
contains
(
basis_gates
,
"u3"
))
?
QObjectExperimentVisitor
::
GateSet
::
U_CX
:
QObjectExperimentVisitor
::
GateSet
::
RZ_SX_CX
;
std
::
stringstream
ss
;
InstructionIterator
it
(
program
);
int
memSlots
=
0
;
std
::
map
<
std
::
string
,
std
::
string
>
cbit_reg_map
;
while
(
it
.
hasNext
())
{
auto
nextInst
=
it
.
next
();
if
(
nextInst
->
isEnabled
()
&&
!
nextInst
->
isComposite
())
{
auto
visitor
=
std
::
make_shared
<
QObjectExperimentVisitor
>
(
program
->
name
(),
program
->
nLogicalBits
(),
gateSet
);
visitor
->
maxMemorySlots
=
memSlots
;
nextInst
->
accept
(
visitor
);
if
(
nextInst
->
name
()
==
"Measure"
)
{
++
memSlots
;
}
auto
experiment
=
visitor
->
getExperiment
();
for
(
auto
&
inst
:
experiment
.
get_instructions
())
{
// std::cout << "HOWDY: " << inst.toString() << "\n";
ss
<<
inst
.
toString
()
<<
"
\n
"
;
}
}
else
if
(
nextInst
->
name
()
==
"ifstmt"
)
{
auto
ifStmt
=
std
::
dynamic_pointer_cast
<
xacc
::
CompositeInstruction
>
(
nextInst
);
// !! NOTE!! OpenQASM2 doesn't allow multi-statement if block
// so need to wrap each statement individually.
if
(
ifStmt
)
{
for
(
auto
&
i
:
ifStmt
->
getInstructions
())
{
auto
visitor
=
std
::
make_shared
<
QObjectExperimentVisitor
>
(
program
->
name
(),
program
->
nLogicalBits
(),
gateSet
);
i
->
accept
(
visitor
);
auto
experiment
=
visitor
->
getExperiment
();
// Note: OpenQASM2 cannot express conditional on a single cbit
// e.g., if (c[k] == 1) (c is a multi-bit register)
// Ref:
// https://quantumcomputing.stackexchange.com/questions/17901/if-statement-in-openqasm2-0-on-ibm-quantum-experience-error/17902#17902
// Also see: https://github.com/Qiskit/qiskit-terra/pull/6018
// qc.qasm() breaks when circuit qc contains gates with classical conditioning on a single cbit
// Please note that this is a limitation of **OpenQASM** only,
// i.e., qiskit's QuantumCircuit and QObj can both handle classical conditioning on a single cbit.
// Our native code gen strategy here is to
// convert multi-qreg indexing into multiple single-cbit registers:
// i.e., c[3] -> c3 (single-bit register)
// This only happens when classical conditioning on a single cbit is needed.
for
(
auto
&
inst
:
experiment
.
get_instructions
())
{
// std::cout << "HOWDY: " << inst.toString() << "\n";
const
std
::
string
orig_reg_name
=
"c["
+
std
::
to_string
(
nextInst
->
bits
()[
0
])
+
"]"
;
if
(
cbit_reg_map
.
find
(
orig_reg_name
)
!=
cbit_reg_map
.
end
())
{
const
std
::
string
single_reg_name
=
cbit_reg_map
[
orig_reg_name
];
ss
<<
"if ("
+
single_reg_name
+
" == 1) "
;
}
else
{
const
std
::
string
single_reg_name
=
"cReg"
+
std
::
to_string
(
cbit_reg_map
.
size
());
cbit_reg_map
[
orig_reg_name
]
=
single_reg_name
;
ss
<<
"if ("
+
single_reg_name
+
" == 1) "
;
}
ss
<<
inst
.
toString
()
<<
"
\n
"
;
}
}
}
}
}
const
auto
replaceAll
=
[](
const
std
::
string
&
t
,
const
std
::
string
&
s
,
std
::
string
&
str
)
{
std
::
string
::
size_type
n
=
0
;
while
((
n
=
str
.
find
(
s
,
n
))
!=
std
::
string
::
npos
)
{
str
.
replace
(
n
,
s
.
size
(),
t
);
n
+=
t
.
size
();
}
};
std
::
string
preAmple
=
R"(OPENQASM 2.0;
include "qelib1.inc";
qreg q[)"
+
std
::
to_string
(
program
->
nLogicalBits
())
+
"];
\n
creg c["
+
std
::
to_string
(
memSlots
)
+
"];
\n
"
;
auto
qasm_body
=
ss
.
str
();
for
(
const
auto
&
[
org_name
,
new_name
]
:
cbit_reg_map
)
{
const
std
::
string
creg_decl
=
"creg "
+
new_name
+
"[1];
\n
"
;
preAmple
+=
creg_decl
;
// Replace the target of the measurement as well.
replaceAll
(
new_name
,
org_name
,
qasm_body
);
}
return
preAmple
+
qasm_body
;
}
xacc
::
error
(
"Unknown native code format '"
+
format
+
"'"
);
return
""
;
}
std
::
string
IBMAccelerator
::
get
(
const
std
::
string
&
_url
,
const
std
::
string
&
path
,
std
::
map
<
std
::
string
,
std
::
string
>
headers
,
...
...
quantum/plugins/ibm/accelerator/IBMAccelerator.hpp
View file @
5fb42d71
...
...
@@ -131,6 +131,8 @@ public:
std
::
vector
<
std
::
pair
<
int
,
int
>>
getConnectivity
()
override
;
std
::
string
getNativeCode
(
std
::
shared_ptr
<
CompositeInstruction
>
program
,
const
HeterogeneousMap
&
config
)
override
;
// Return the name of an IRTransformation of type Placement that is
// preferred for this Accelerator
const
std
::
string
defaultPlacementTransformation
()
override
{
...
...
quantum/plugins/ibm/accelerator/json/QObject.hpp
View file @
5fb42d71
...
...
@@ -399,6 +399,33 @@ public:
std
::
optional
<
int64_t
>
get_condition_reg_id
()
const
{
return
conditional
;
}
void
set_condition_reg_id
(
int64_t
value
)
{
this
->
conditional
=
value
;
}
std
::
string
toString
()
const
{
std
::
stringstream
ss
;
ss
<<
name
;
if
(
!
params
.
empty
())
{
ss
<<
"("
;
for
(
int
i
=
0
;
i
<
params
.
size
();
++
i
)
{
ss
<<
params
[
i
];
if
(
i
!=
params
.
size
()
-
1
)
{
ss
<<
", "
;
}
}
ss
<<
")"
;
}
for
(
int
i
=
0
;
i
<
qubits
.
size
();
++
i
)
{
ss
<<
" q["
<<
qubits
[
i
]
<<
"]"
;
if
(
i
!=
qubits
.
size
()
-
1
)
{
ss
<<
", "
;
}
}
if
(
!
get_memory
().
empty
())
{
ss
<<
" -> c["
<<
get_memory
()[
0
]
<<
"]"
;
}
ss
<<
";"
;
return
ss
.
str
();
}
};
class
Experiment
{
...
...
xacc/accelerator/Accelerator.hpp
View file @
5fb42d71
...
...
@@ -106,6 +106,14 @@ public:
return
std
::
vector
<
std
::
pair
<
int
,
int
>>
{};
}
// Get circuit representation that the backend would be submitting to the
// physical QPU
virtual
std
::
string
getNativeCode
(
std
::
shared_ptr
<
CompositeInstruction
>
program
,
const
HeterogeneousMap
&
config
=
{})
{
return
program
->
toString
();
}
virtual
const
std
::
vector
<
std
::
complex
<
double
>>
getAcceleratorState
(
std
::
shared_ptr
<
CompositeInstruction
>
program
)
{
return
std
::
vector
<
std
::
complex
<
double
>>
{};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment