Skip to content
GitLab
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
50bee5de
Unverified
Commit
50bee5de
authored
Aug 20, 2021
by
Mccaskey, Alex
Committed by
GitHub
Aug 20, 2021
Browse files
Merge pull request #481 from tnguyen-ornl/tnguyen/ifstmt-to-extended-qasm2
Support IfStmt to OpenQASM2 generation
parents
b1cf4a2e
044bff71
Pipeline
#160431
passed with stage
in 34 minutes and 28 seconds
Changes
9
Pipelines
4
Hide whitespace changes
Inline
Side-by-side
quantum/gate/ir/CommonGates.hpp
View file @
50bee5de
...
...
@@ -76,6 +76,9 @@ public:
std
::
vector
<
InstructionParameter
>
getParameters
()
override
{
return
{
bufferName
};
}
std
::
vector
<
std
::
string
>
getBufferNames
()
override
{
return
{
bufferName
};
}
const
int
nParameters
()
override
{
return
1
;
}
const
int
nRequiredBits
()
const
override
{
return
1
;
}
...
...
quantum/plugins/ibm/aer/accelerator/aer_accelerator.cpp
View file @
50bee5de
...
...
@@ -832,6 +832,14 @@ IbmqNoiseModel::averageTwoQubitGateFidelity() const {
return
result
;
}
std
::
string
AerAccelerator
::
getNativeCode
(
std
::
shared_ptr
<
CompositeInstruction
>
program
,
const
HeterogeneousMap
&
config
)
{
auto
qobj_str
=
xacc_to_qobj
->
translate
(
program
);
nlohmann
::
json
j
=
nlohmann
::
json
::
parse
(
qobj_str
)[
"qObject"
];
return
j
.
dump
(
2
);
}
}
// namespace quantum
}
// namespace xacc
...
...
quantum/plugins/ibm/aer/accelerator/aer_accelerator.hpp
View file @
50bee5de
...
...
@@ -60,7 +60,8 @@ public:
void
apply
(
std
::
shared_ptr
<
AcceleratorBuffer
>
buffer
,
std
::
shared_ptr
<
Instruction
>
inst
)
override
;
bool
isInitialized
()
const
{
return
initialized
;
}
std
::
string
getNativeCode
(
std
::
shared_ptr
<
CompositeInstruction
>
program
,
const
HeterogeneousMap
&
config
=
{})
override
;
private:
static
double
calcExpectationValueZ
(
const
std
::
vector
<
std
::
pair
<
double
,
double
>>
&
in_stateVec
,
...
...
quantum/plugins/optimizers/simple/CircuitOptimizer.cpp
View file @
50bee5de
...
...
@@ -678,6 +678,19 @@ bool CircuitOptimizer::tryRotationMergingUsingPhasePolynomials(std::shared_ptr<C
}
}
else
if
(
instruction
->
bits
().
size
()
==
2
)
{
// If this gate not involved the qubits that we are checking
if
(
!
container
::
contains
(
qubits
,
instruction
->
bits
()[
0
])
&&
!
container
::
contains
(
qubits
,
instruction
->
bits
()[
1
]))
{
// Skip
continue
;
}
// This 2-q gate **involves** at least one qubit:
if
(
instruction
->
name
()
!=
"CNOT"
)
{
// Not a CNOT: we need to terminate, hence prune the subcircuit.
break
;
}
assert
(
instruction
->
name
()
==
"CNOT"
);
// If the control is *outside* the boundary, we need to terminate, hence prune the subcircuit.
const
auto
controlIdx
=
instruction
->
bits
()[
0
];
...
...
@@ -735,6 +748,8 @@ bool CircuitOptimizer::tryRotationMergingUsingPhasePolynomials(std::shared_ptr<C
}
}
}
// Move the instruction index
++
i
;
}
else
{
// Not a CNOT gate, continue
...
...
quantum/plugins/optimizers/simple/tests/CircuitOptimizerTester.cpp
View file @
50bee5de
...
...
@@ -818,6 +818,53 @@ measure q[3] -> c[3];
EXPECT_EQ
(
truthTableBefore
,
truthTableAfter
);
}
TEST
(
CircuitOptimizerTester
,
checkCZ
)
{
xacc
::
set_verbose
(
true
);
auto
compiler
=
xacc
::
getService
<
xacc
::
Compiler
>
(
"xasm"
);
auto
program
=
compiler
->
compile
(
R"(__qpu__ void testCz(qbit q) {
CNOT(q[0], q[1]);
CZ(q[0], q[1]);
Measure(q[0]);
Measure(q[1]);
})"
)
->
getComposites
()[
0
];
const
auto
before_xasm_str
=
program
->
toString
();
auto
optimizer
=
xacc
::
getService
<
IRTransformation
>
(
"circuit-optimizer"
);
optimizer
->
apply
(
program
,
nullptr
);
std
::
cout
<<
"FINAL CIRCUIT:
\n
"
<<
program
->
toString
()
<<
"
\n
"
;
const
auto
after_xasm_str
=
program
->
toString
();
EXPECT_EQ
(
before_xasm_str
,
after_xasm_str
);
}
// Check circuit with random gates
TEST
(
CircuitOptimizerTester
,
checkComplexCircuit
)
{
xacc
::
set_verbose
(
true
);
auto
compiler
=
xacc
::
getService
<
xacc
::
Compiler
>
(
"xasm"
);
auto
program
=
compiler
->
compile
(
R"(__qpu__ void testRandom(qbit q) {
X(q[0]);
H(q[1]);
CZ(q[0], q[1]);
H(q[1]);
CNOT(q[1], q[2]);
T(q[1]);
CZ(q[1], q[0]);
Measure(q[0]);
Measure(q[1]);
Measure(q[2]);
})"
)
->
getComposites
()[
0
];
const
auto
before_xasm_str
=
program
->
toString
();
auto
optimizer
=
xacc
::
getService
<
IRTransformation
>
(
"circuit-optimizer"
);
optimizer
->
apply
(
program
,
nullptr
);
std
::
cout
<<
"FINAL CIRCUIT:
\n
"
<<
program
->
toString
()
<<
"
\n
"
;
const
auto
after_xasm_str
=
program
->
toString
();
EXPECT_EQ
(
before_xasm_str
,
after_xasm_str
);
}
int
main
(
int
argc
,
char
**
argv
)
{
xacc
::
Initialize
(
argc
,
argv
);
::
testing
::
InitGoogleTest
(
&
argc
,
argv
);
...
...
quantum/plugins/staq/compiler/staq_compiler.cpp
View file @
50bee5de
...
...
@@ -428,27 +428,56 @@ std::shared_ptr<IR> StaqCompiler::compile(const std::string &src) {
const
std
::
string
StaqCompiler
::
translate
(
std
::
shared_ptr
<
xacc
::
CompositeInstruction
>
function
)
{
std
::
map
<
std
::
string
,
int
>
bufNamesToSize
;
std
::
map
<
std
::
string
,
int
>
cRegNamesToSize
;
InstructionIterator
iter
(
function
);
// First search buffer names and see if we have
while
(
iter
.
hasNext
())
{
auto
&
next
=
*
iter
.
next
();
if
(
next
.
isEnabled
())
{
for
(
int
i
=
0
;
i
<
next
.
nRequiredBits
();
i
++
)
{
auto
bufName
=
next
.
getBufferName
(
i
);
int
size
=
next
.
bits
()[
i
]
+
1
;
if
(
bufNamesToSize
.
count
(
bufName
))
{
if
(
bufNamesToSize
[
bufName
]
<
size
)
{
bufNamesToSize
[
bufName
]
=
size
;
if
(
!
next
.
isComposite
()
&&
next
.
isEnabled
())
{
if
(
next
.
name
()
==
"Measure"
)
{
xacc
::
quantum
::
Measure
&
m
=
(
xacc
::
quantum
::
Measure
&
)
next
;
if
(
m
.
hasClassicalRegAssignment
())
{
auto
cregName
=
next
.
getBufferName
(
1
);
int
size
=
m
.
getClassicalBitIndex
()
+
1
;
if
(
cRegNamesToSize
.
count
(
cregName
))
{
if
(
cRegNamesToSize
[
cregName
]
<
size
)
{
cRegNamesToSize
[
cregName
]
=
size
;
}
}
else
{
cRegNamesToSize
.
insert
({
cregName
,
size
});
}
}
else
{
bufNamesToSize
.
insert
({
bufName
,
size
});
auto
bufName
=
next
.
getBufferName
(
0
);
int
size
=
next
.
bits
()[
0
]
+
1
;
if
(
bufNamesToSize
.
count
(
bufName
))
{
if
(
bufNamesToSize
[
bufName
]
<
size
)
{
bufNamesToSize
[
bufName
]
=
size
;
}
}
else
{
bufNamesToSize
.
insert
({
bufName
,
size
});
}
}
}
else
{
for
(
int
i
=
0
;
i
<
next
.
nRequiredBits
();
i
++
)
{
auto
bufName
=
next
.
getBufferName
(
i
);
int
size
=
next
.
bits
()[
i
]
+
1
;
if
(
bufNamesToSize
.
count
(
bufName
))
{
if
(
bufNamesToSize
[
bufName
]
<
size
)
{
bufNamesToSize
[
bufName
]
=
size
;
}
}
else
{
bufNamesToSize
.
insert
({
bufName
,
size
});
}
}
}
}
}
auto
translate
=
std
::
make_shared
<
internal_staq
::
XACCToStaqOpenQasm
>
(
bufNamesToSize
);
cRegNamesToSize
.
empty
()
?
std
::
make_shared
<
internal_staq
::
XACCToStaqOpenQasm
>
(
bufNamesToSize
)
:
std
::
make_shared
<
internal_staq
::
XACCToStaqOpenQasm
>
(
bufNamesToSize
,
cRegNamesToSize
);
InstructionIterator
iter2
(
function
);
while
(
iter2
.
hasNext
())
{
auto
&
next
=
*
iter2
.
next
();
...
...
quantum/plugins/staq/compiler/tests/StaqCompilerTester.in.cpp
View file @
50bee5de
...
...
@@ -246,6 +246,31 @@ TEST(StaqCompilerTester, checkFloatingPointFormat) {
EXPECT_NEAR
(
rxInst
->
getParameter
(
0
).
as
<
double
>
(),
2.5e-07
,
1e-12
);
}
TEST
(
StaqCompilerTester
,
checkIfStatementTranslate
)
{
auto
xasmCompiler
=
xacc
::
getCompiler
(
"xasm"
);
auto
ir
=
xasmCompiler
->
compile
(
R"(__qpu__ void test(qbit q) {
Measure(q[0], c[0]);
if(c[0]) {
Rz(q[0], -pi/2);
}
H(q[0]);
Measure(q[0], c[1]);
CPhase(q[0], q[1], -5*pi/8);
if(c[0]) {
Rz(q[0], -pi/4);
}
if(c[1]) {
Rz(q[0], -pi/2);
}
})"
,
nullptr
);
auto
staq_compiler
=
xacc
::
getCompiler
(
"staq"
);
auto
qasm
=
staq_compiler
->
translate
(
ir
->
getComposites
()[
0
]);
std
::
cout
<<
"HOWDY:
\n
"
<<
qasm
<<
"
\n
"
;
// Check that If statements are translated.
EXPECT_TRUE
(
qasm
.
find
(
"if (c[0] == 1) rz"
)
!=
std
::
string
::
npos
);
EXPECT_TRUE
(
qasm
.
find
(
"if (c[1] == 1) rz"
)
!=
std
::
string
::
npos
);
}
int
main
(
int
argc
,
char
**
argv
)
{
xacc
::
Initialize
(
argc
,
argv
);
xacc
::
set_verbose
(
true
);
...
...
quantum/plugins/staq/utils/staq_visitors.cpp
View file @
50bee5de
...
...
@@ -24,6 +24,18 @@ XACCToStaqOpenQasm::XACCToStaqOpenQasm(std::map<std::string, int> bufNamesToSize
}
}
XACCToStaqOpenQasm
::
XACCToStaqOpenQasm
(
std
::
map
<
std
::
string
,
int
>
bufNamesToSize
,
std
::
map
<
std
::
string
,
int
>
cRegNameToSize
)
{
ss
<<
"OPENQASM 2.0;
\n
include
\"
qelib1.inc
\"
;
\n
"
;
for
(
auto
&
kv
:
bufNamesToSize
)
{
ss
<<
"qreg "
<<
kv
.
first
<<
"["
<<
kv
.
second
<<
"];
\n
"
;
}
for
(
auto
&
kv
:
cRegNameToSize
)
{
ss
<<
"creg "
<<
kv
.
first
<<
"["
<<
kv
.
second
<<
"];
\n
"
;
}
}
void
XACCToStaqOpenQasm
::
visit
(
Hadamard
&
h
)
{
ss
<<
"h "
<<
(
h
.
getBufferNames
().
empty
()
?
"q"
:
h
.
getBufferName
(
0
))
<<
h
.
bits
()
<<
";
\n
"
;
...
...
@@ -97,12 +109,38 @@ void XACCToStaqOpenQasm::visit(CPhase &cphase) {
<<
"["
<<
cphase
.
bits
()[
0
]
<<
"], "
<<
(
cphase
.
getBufferNames
().
empty
()
?
"q"
:
cphase
.
getBufferName
(
1
))
<<
"["
<<
cphase
.
bits
()[
1
]
<<
"];
\n
"
;
}
void
XACCToStaqOpenQasm
::
visit
(
Measure
&
m
)
{
ss
<<
"measure "
<<
(
m
.
getBufferNames
().
empty
()
?
"q"
:
m
.
getBufferName
(
0
))
<<
m
.
bits
()
<<
" -> "
<<
cregNames
[
m
.
getBufferName
(
0
)]
<<
m
.
bits
()
<<
";
\n
"
;
if
(
m
.
hasClassicalRegAssignment
())
{
ss
<<
"measure "
<<
(
m
.
getBufferNames
().
empty
()
?
"q"
:
m
.
getBufferName
(
0
))
<<
m
.
bits
()
<<
" -> "
<<
m
.
getBufferName
(
1
)
<<
"["
<<
m
.
getClassicalBitIndex
()
<<
"]"
<<
";
\n
"
;
}
else
{
ss
<<
"measure "
<<
(
m
.
getBufferNames
().
empty
()
?
"q"
:
m
.
getBufferName
(
0
))
<<
m
.
bits
()
<<
" -> "
<<
cregNames
[
m
.
getBufferName
(
0
)]
<<
m
.
bits
()
<<
";
\n
"
;
}
}
void
XACCToStaqOpenQasm
::
visit
(
Identity
&
i
)
{}
void
XACCToStaqOpenQasm
::
visit
(
U
&
u
)
{
ss
<<
"u3("
<<
std
::
fixed
<<
std
::
setprecision
(
16
)
<<
xacc
::
InstructionParameterToDouble
(
u
.
getParameter
(
0
))
<<
","
<<
xacc
::
InstructionParameterToDouble
(
u
.
getParameter
(
1
))
<<
","
<<
xacc
::
InstructionParameterToDouble
(
u
.
getParameter
(
2
))
<<
") "
<<
(
u
.
getBufferNames
().
empty
()
?
"q"
:
u
.
getBufferName
(
0
))
<<
u
.
bits
()
<<
";
\n
"
;
}
void
XACCToStaqOpenQasm
::
visit
(
IfStmt
&
ifStmt
)
{}
void
XACCToStaqOpenQasm
::
visit
(
IfStmt
&
ifStmt
)
{
// Note: QASM2 'if' must be inline (no braces)
// Note: this extended syntax: if (creg[k] == 1) is not supported by IBM.
// (IBM requires comparison to the full register value, not a bit check)
for
(
auto
i
:
ifStmt
.
getInstructions
())
{
// If statement was specified by the qreg name -> find the associated cReg
if
(
cregNames
.
find
(
ifStmt
.
getBufferNames
()[
0
])
!=
cregNames
.
end
())
{
ss
<<
"if ("
<<
cregNames
[
ifStmt
.
getBufferNames
()[
0
]]
<<
"["
<<
ifStmt
.
bits
()[
0
]
<<
"] == 1) "
;
}
else
{
// Explicit creg was used:
ss
<<
"if ("
<<
ifStmt
.
getBufferNames
()[
0
]
<<
"["
<<
ifStmt
.
bits
()[
0
]
<<
"] == 1) "
;
}
i
->
accept
(
this
);
}
}
}
// namespace internal_staq
}
// namespace xacc
\ No newline at end of file
quantum/plugins/staq/utils/staq_visitors.hpp
View file @
50bee5de
...
...
@@ -266,8 +266,13 @@ class XACCToStaqOpenQasm : public AllGateVisitor {
public:
std
::
stringstream
ss
;
std
::
map
<
std
::
string
,
std
::
string
>
cregNames
;
// Default: assume each qreg is accompanied by a creg of the same size
XACCToStaqOpenQasm
(
std
::
map
<
std
::
string
,
int
>
bufNamesToSize
);
// Explicit list of creg:
// e.g., IQPE algo: we requires a much larger creg than qreg to store all
// measurements.
XACCToStaqOpenQasm
(
std
::
map
<
std
::
string
,
int
>
bufNamesToSize
,
std
::
map
<
std
::
string
,
int
>
cRegNameToSize
);
void
visit
(
Hadamard
&
h
)
override
;
void
visit
(
CNOT
&
cnot
)
override
;
void
visit
(
Rz
&
rz
)
override
;
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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