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
bb877d5c
Commit
bb877d5c
authored
Apr 18, 2017
by
Mccaskey, Alex
Browse files
implemented gateqir read and write. documentation throughout
parent
3a9222a2
Changes
12
Hide whitespace changes
Inline
Side-by-side
quantum/gate/gateqir/GateFunction.cpp
View file @
bb877d5c
...
...
@@ -56,13 +56,10 @@ void GateFunction::replaceInstruction(int instId, InstPtr replacingInst) {
}
const
std
::
string
GateFunction
::
toString
(
const
std
::
string
bufferVarName
)
{
std
::
string
retStr
=
""
;
for
(
auto
i
:
instructions
)
{
retStr
+=
i
->
toString
(
bufferVarName
)
+
"
\n
"
;
}
return
retStr
;
}
...
...
quantum/gate/gateqir/GateFunction.hpp
View file @
bb877d5c
...
...
@@ -32,26 +32,54 @@
#define QUANTUM_GATEQIR_QFUNCTION_HPP_
#include
"QFunction.hpp"
#include
"GateInstruction.hpp"
namespace
xacc
{
namespace
quantum
{
/**
* The GateFunction is a QFunction for gate-model
* quantum computing. It is composed of QInstructions that
* are themselves derivations of the GateInstruction class.
*/
class
GateFunction
:
public
virtual
QFunction
{
protected:
/**
* The list of QInstructions that this GateFunction
* contains.
*/
std
::
vector
<
std
::
shared_ptr
<
QInstruction
>>
instructions
;
/**
* The name of this function
*/
std
::
string
functionName
;
/**
* The unique id integer for this function
*/
int
functionId
;
/**
* The list of qubits this function acts on.
*/
std
::
vector
<
int
>
qbits
;
public:
/**
* The nullary constructor.
*/
GateFunction
();
/**
* The constructor, takes the function unique id and its name.
*
* @param id
* @param name
*/
GateFunction
(
int
id
,
const
std
::
string
name
);
/**
...
...
@@ -82,16 +110,43 @@ public:
virtual
void
replaceInstruction
(
int
instId
,
InstPtr
replacingInst
);
/**
* Return the id of this function
* @return
*/
virtual
const
int
getId
();
/**
* Return the name of this function
* @return
*/
virtual
const
std
::
string
getName
();
/**
* Return the qubits this function acts on.
* @return
*/
virtual
const
std
::
vector
<
int
>
qubits
();
/**
* Return an assembly-like string representation for this function .
* @param bufferVarName
* @return
*/
virtual
const
std
::
string
toString
(
const
std
::
string
bufferVarName
);
/**
* This method should simply be implemented to invoke the
* visit() method on the provided QInstructionVisitor.
*
* @param visitor
*/
virtual
void
accept
(
QInstructionVisitor
&
visitor
);
/**
* Return the number of instructions in this function.
* @return
*/
const
int
nInstructions
();
};
}
...
...
quantum/gate/gateqir/GateInstruction.hpp
View file @
bb877d5c
...
...
@@ -37,40 +37,95 @@ namespace xacc {
namespace
quantum
{
/**
*
* The GateInstruction is an implementation of QInstruction
* for gate-model quantum computing.
*/
class
GateInstruction
:
public
virtual
QInstruction
{
protected:
/**
* Reference to this instructions id
*/
int
gateId
;
/**
* Reference to this instructions name
*/
std
::
string
gateName
;
/**
* Reference to the circuit layer for this instruction.
*/
int
circuitLayer
;
/**
* Reference to the qubits this instruction acts on
*/
std
::
vector
<
int
>
qbits
;
public:
/**
* The nullary contructor.
*/
GateInstruction
()
:
gateId
(
0
),
gateName
(
"UNKNOWN"
),
circuitLayer
(
0
),
qbits
(
std
::
vector
<
int
>
{
})
{
}
/**
* The constructor, takes the id, name, layer, and qubits
* this instruction acts on.
*
* @param id
* @param layer
* @param name
* @param qubts
*/
GateInstruction
(
int
id
,
int
layer
,
std
::
string
name
,
std
::
vector
<
int
>
qubts
)
:
gateId
(
id
),
circuitLayer
(
layer
),
gateName
(
name
),
qbits
(
qubts
)
{
}
/**
* Return the unique instruction id.
* @return
*/
virtual
const
int
getId
()
{
return
gateId
;
}
/**
* Return the instruction name.
* @return
*/
virtual
const
std
::
string
getName
()
{
return
gateName
;
}
/**
* Return the instruction layer.
*
* @return
*/
virtual
const
int
layer
()
{
return
circuitLayer
;
}
/**
* Return the list of qubits this instruction acts on.
* @return
*/
virtual
const
std
::
vector
<
int
>
qubits
()
{
return
qbits
;
}
/**
* Return this instruction's assembly-like string
* representation.
* @param bufferVarName
* @return
*/
virtual
const
std
::
string
toString
(
const
std
::
string
bufferVarName
)
{
auto
str
=
gateName
+
" "
;
for
(
auto
q
:
qubits
())
{
...
...
@@ -83,6 +138,9 @@ public:
return
str
;
}
/**
* The destructor
*/
virtual
~
GateInstruction
()
{
}
};
...
...
quantum/gate/gateqir/GateQIR.cpp
View file @
bb877d5c
...
...
@@ -29,16 +29,211 @@
*
**********************************************************************************/
#include
"GateQIR.hpp"
#include
<boost/algorithm/string.hpp>
#include
<regex>
namespace
xacc
{
namespace
quantum
{
void
GateQIR
::
generateGraph
()
{
// Local Declarations
auto
flatQasmStr
=
toString
();
std
::
map
<
std
::
string
,
int
>
qubitVarNameToId
;
std
::
vector
<
std
::
string
>
qasmLines
;
std
::
vector
<
int
>
allQbitIds
;
std
::
regex
newLineDelim
(
"
\n
"
),
spaceDelim
(
" "
);
std
::
regex
qubitDeclarations
(
"
\\
s*qubit
\\
s*
\\
w+"
);
std
::
sregex_token_iterator
first
{
flatQasmStr
.
begin
(),
flatQasmStr
.
end
(),
newLineDelim
,
-
1
},
last
;
int
nQubits
=
0
,
qbitId
=
0
,
layer
=
1
,
gateId
=
1
;
std
::
string
qubitVarName
;
qasmLines
=
{
first
,
last
};
// Let's now loop over the qubit declarations,
// and construct a mapping of qubit var names to integer id,
// and get the total number of qubits
for
(
auto
i
=
std
::
sregex_iterator
(
flatQasmStr
.
begin
(),
flatQasmStr
.
end
(),
qubitDeclarations
);
i
!=
std
::
sregex_iterator
();
++
i
)
{
std
::
string
qubitLine
=
(
*
i
).
str
();
qubitLine
.
erase
(
std
::
remove
(
qubitLine
.
begin
(),
qubitLine
.
end
(),
'\n'
),
qubitLine
.
end
());
std
::
sregex_token_iterator
first
{
qubitLine
.
begin
(),
qubitLine
.
end
(),
spaceDelim
,
-
1
},
last
;
std
::
vector
<
std
::
string
>
splitQubitLine
=
{
first
,
last
};
qubitVarNameToId
[
splitQubitLine
[
1
]]
=
qbitId
;
splitQubitLine
[
1
].
erase
(
std
::
remove_if
(
splitQubitLine
[
1
].
begin
(),
splitQubitLine
[
1
].
end
(),
&
isdigit
),
splitQubitLine
[
1
].
end
());
qubitVarName
=
splitQubitLine
[
1
];
allQbitIds
.
push_back
(
qbitId
);
qbitId
++
;
}
// Set the number of qubits
nQubits
=
qubitVarNameToId
.
size
();
// First create a starting node for the initial
// wave function - it should have nQubits outgoing
// edges
addVertex
(
"InitialState"
,
0
,
0
,
allQbitIds
,
true
,
std
::
vector
<
std
::
string
>
{});
std
::
vector
<
CircuitNode
>
gateOperations
;
for
(
auto
line
:
qasmLines
)
{
// If this is a gate line...
if
(
!
boost
::
contains
(
line
,
"qubit"
)
&&
!
boost
::
contains
(
line
,
"cbit"
))
{
// Create a new CircuitNode
CircuitNode
node
;
// Split the current qasm command at the spaces
std
::
sregex_token_iterator
first
{
line
.
begin
(),
line
.
end
(),
spaceDelim
,
-
1
},
last
;
std
::
vector
<
std
::
string
>
gateCommand
=
{
first
,
last
};
// Set the gate as a lowercase gate name string
auto
g
=
boost
::
to_lower_copy
(
gateCommand
[
0
]);
boost
::
trim
(
g
);
if
(
g
==
"measz"
)
g
=
"measure"
;
std
::
get
<
0
>
(
node
.
properties
)
=
g
;
// If not a 2 qubit gate, and if the acting
// qubit is different than the last one, then
// keep the layer the same, otherwise increment
if
(
incrementLayer
(
gateCommand
,
qubitVarNameToId
,
gateOperations
,
layer
))
{
layer
++
;
}
// Set the current layer
std
::
get
<
1
>
(
node
.
properties
)
=
layer
;
// Set the gate vertex id
std
::
get
<
2
>
(
node
.
properties
)
=
gateId
;
gateId
++
;
// Set the qubits this gate acts on
std
::
vector
<
int
>
actingQubits
;
if
(
!
boost
::
contains
(
gateCommand
[
1
],
","
))
{
actingQubits
.
push_back
(
qubitVarNameToId
[
gateCommand
[
1
]]);
}
else
{
// FIXME Need to differentiate between qubits and parameters here
// First we need the qubit register variable name
int
counter
=
0
;
std
::
vector
<
std
::
string
>
splitComma
,
props
;
boost
::
split
(
splitComma
,
gateCommand
[
1
],
boost
::
is_any_of
(
","
));
for
(
auto
segment
:
splitComma
)
{
if
(
boost
::
contains
(
segment
,
qubitVarName
))
{
actingQubits
.
push_back
(
qubitVarNameToId
[
segment
]);
}
else
{
// This is not a qubit, it must be a parameter for gate
props
.
push_back
(
"PARAM_"
+
std
::
to_string
(
counter
));
std
::
get
<
5
>
(
node
.
properties
)
=
props
;
counter
++
;
}
}
}
// Set the acting qubits
std
::
get
<
3
>
(
node
.
properties
)
=
actingQubits
;
// Add this gate to the local vector
// and to the graph
gateOperations
.
push_back
(
node
);
addVertex
(
node
);
}
}
// Add a final layer for the graph sink
CircuitNode
finalNode
;
std
::
get
<
0
>
(
finalNode
.
properties
)
=
"FinalState"
;
std
::
get
<
1
>
(
finalNode
.
properties
)
=
layer
+
1
;
std
::
get
<
2
>
(
finalNode
.
properties
)
=
gateId
;
std
::
get
<
3
>
(
finalNode
.
properties
)
=
allQbitIds
;
std
::
get
<
4
>
(
finalNode
.
properties
)
=
true
;
addVertex
(
finalNode
);
gateOperations
.
push_back
(
finalNode
);
// Set how many layers are in this circuit
int
maxLayer
=
layer
+
1
;
generateEdgesFromLayer
(
1
,
gateOperations
,
0
);
return
;
}
std
::
string
GateQIR
::
toString
()
{
void
GateQIR
::
generateEdgesFromLayer
(
const
int
layer
,
std
::
vector
<
CircuitNode
>&
gateOperations
,
int
initialStateId
)
{
int
nQubits
=
std
::
get
<
3
>
(
getVertexProperties
(
0
)).
size
();
int
maxLayer
=
std
::
get
<
1
>
(
gateOperations
[
gateOperations
.
size
()
-
1
].
properties
);
std
::
map
<
int
,
int
>
qubitToCurrentGateId
;
for
(
int
i
=
0
;
i
<
nQubits
;
i
++
)
{
qubitToCurrentGateId
[
i
]
=
initialStateId
;
}
int
currentLayer
=
layer
;
while
(
currentLayer
<=
maxLayer
)
{
std
::
vector
<
CircuitNode
>
currentLayerGates
;
std
::
copy_if
(
gateOperations
.
begin
(),
gateOperations
.
end
(),
std
::
back_inserter
(
currentLayerGates
),
[
&
](
const
CircuitNode
&
c
)
{
return
std
::
get
<
1
>
(
c
.
properties
)
==
currentLayer
;});
for
(
auto
n
:
currentLayerGates
)
{
std
::
vector
<
int
>
actingQubits
=
std
::
get
<
3
>
(
n
.
properties
);
for
(
auto
qubit
:
actingQubits
)
{
int
currentQubitGateId
=
qubitToCurrentGateId
[
qubit
];
addEdge
(
currentQubitGateId
,
std
::
get
<
2
>
(
n
.
properties
));
qubitToCurrentGateId
[
qubit
]
=
std
::
get
<
2
>
(
n
.
properties
);
}
}
currentLayer
++
;
}
}
bool
GateQIR
::
incrementLayer
(
const
std
::
vector
<
std
::
string
>&
gateCommand
,
std
::
map
<
std
::
string
,
int
>&
qubitVarNameToId
,
const
std
::
vector
<
CircuitNode
>&
gates
,
const
int
&
currentLayer
)
{
bool
oneQubitGate
=
!
boost
::
contains
(
gateCommand
[
1
],
","
),
noGateAtQOnL
=
true
;
auto
g
=
boost
::
to_lower_copy
(
gateCommand
[
0
]);
boost
::
trim
(
g
);
if
(
g
==
"measz"
)
g
=
"measure"
;
std
::
vector
<
CircuitNode
>
thisLayerGates
;
std
::
copy_if
(
gates
.
begin
(),
gates
.
end
(),
std
::
back_inserter
(
thisLayerGates
),
[
&
](
const
CircuitNode
&
c
)
{
return
std
::
get
<
1
>
(
c
.
properties
)
==
currentLayer
;});
for
(
auto
layerGate
:
thisLayerGates
)
{
std
::
vector
<
int
>
qubits
=
std
::
get
<
3
>
(
layerGate
.
properties
);
for
(
auto
q
:
qubits
)
{
if
(
qubitVarNameToId
[
gateCommand
[
1
]]
==
q
)
{
noGateAtQOnL
=
false
;
}
}
}
if
(
!
oneQubitGate
)
{
return
true
;
}
else
if
(
!
noGateAtQOnL
)
{
return
true
;
}
else
if
(
!
gates
.
empty
()
&&
(
std
::
get
<
0
>
(
gates
[
gates
.
size
()
-
1
].
properties
)
==
"measure"
)
&&
g
!=
"measure"
)
{
return
true
;
}
return
false
;
}
std
::
string
GateQIR
::
toString
()
{
int
nQubits
=
buffer
->
size
();
auto
bufVarName
=
buffer
->
name
();
std
::
string
retStr
=
""
;
...
...
@@ -48,27 +243,92 @@ std::string GateQIR::toString() {
for
(
auto
f
:
kernels
)
{
retStr
+=
f
->
toString
(
bufVarName
);
}
return
retStr
;
}
void
GateQIR
::
persist
(
std
::
ostream
&
outStream
)
{
write
(
outStream
);
}
// FOR IR
void
GateQIR
::
load
(
std
::
istream
&
inStream
)
{
read
(
inStream
);
}
// FOR GRAPH
void
GateQIR
::
read
(
std
::
istream
&
stream
)
{
}
// IMPLEMENT GRAPH READ STUFF
std
::
string
content
{
std
::
istreambuf_iterator
<
char
>
(
stream
),
std
::
istreambuf_iterator
<
char
>
()
};
}
}
std
::
vector
<
std
::
string
>
lines
,
sections
;
boost
::
split
(
sections
,
content
,
boost
::
is_any_of
(
"}"
));
// Sections should be size 2 for a valid dot file
boost
::
split
(
lines
,
sections
[
0
],
boost
::
is_any_of
(
"
\n
"
));
for
(
auto
line
:
lines
)
{
if
(
boost
::
contains
(
line
,
"label"
))
{
CircuitNode
v
;
auto
firstBracket
=
line
.
find_first_of
(
'['
);
line
=
line
.
substr
(
firstBracket
+
1
,
line
.
size
()
-
2
);
boost
::
replace_all
(
line
,
";"
,
""
);
boost
::
replace_all
(
line
,
"["
,
""
);
boost
::
replace_all
(
line
,
"]"
,
""
);
boost
::
replace_all
(
line
,
"
\"
"
,
""
);
boost
::
replace_all
(
line
,
"label="
,
""
);
boost
::
trim
(
line
);
std
::
vector
<
std
::
string
>
labelLineSplit
,
removeId
;
boost
::
split
(
labelLineSplit
,
line
,
boost
::
is_any_of
(
","
));
for
(
auto
a
:
labelLineSplit
)
{
std
::
vector
<
std
::
string
>
eqsplit
;
boost
::
split
(
eqsplit
,
a
,
boost
::
is_any_of
(
"="
));
if
(
eqsplit
[
0
]
==
"Gate"
)
{
std
::
get
<
0
>
(
v
.
properties
)
=
eqsplit
[
1
];
}
else
if
(
eqsplit
[
0
]
==
"Circuit Layer"
)
{
std
::
get
<
1
>
(
v
.
properties
)
=
std
::
stoi
(
eqsplit
[
1
]);
}
else
if
(
eqsplit
[
0
]
==
"Gate Vertex Id"
)
{
std
::
get
<
2
>
(
v
.
properties
)
=
std
::
stoi
(
eqsplit
[
1
]);
}
else
if
(
eqsplit
[
0
]
==
"Gate Acting Qubits"
)
{
auto
qubitsStr
=
eqsplit
[
1
];
boost
::
replace_all
(
qubitsStr
,
"["
,
""
);
boost
::
replace_all
(
qubitsStr
,
"["
,
""
);
std
::
vector
<
std
::
string
>
elementsStr
;
std
::
vector
<
int
>
qubits
;
boost
::
split
(
elementsStr
,
qubitsStr
,
boost
::
is_any_of
(
" "
));
for
(
auto
element
:
elementsStr
)
{
qubits
.
push_back
(
std
::
stoi
(
element
));
}
std
::
get
<
3
>
(
v
.
properties
)
=
qubits
;
}
else
if
(
eqsplit
[
0
]
==
"Enabled"
)
{
std
::
get
<
4
>
(
v
.
properties
)
=
(
bool
)
std
::
stoi
(
eqsplit
[
1
]);
}
}
addVertex
(
v
);
}
}
// Now add the edges
lines
.
clear
();
boost
::
split
(
lines
,
sections
[
1
],
boost
::
is_any_of
(
";
\n
"
));
for
(
auto
line
:
lines
)
{
boost
::
trim
(
line
);
if
(
line
==
"}"
||
line
.
empty
())
continue
;
boost
::
trim
(
line
);
boost
::
replace_all
(
line
,
"--"
,
" "
);
std
::
vector
<
std
::
string
>
vertexPairs
;
boost
::
split
(
vertexPairs
,
line
,
boost
::
is_any_of
(
" "
));
addEdge
(
std
::
stoi
(
vertexPairs
[
0
]),
std
::
stoi
(
vertexPairs
[
1
]));
}
}
}
}
quantum/gate/gateqir/GateQIR.hpp
View file @
bb877d5c
...
...
@@ -63,6 +63,9 @@ public:
};
/**
* The GateQIR is an implementation of the QIR for gate model quantum
* computing. It provides a Graph node type that models a quantum
* circuit gate (CircuitNode).
*
*/
class
GateQIR
:
public
virtual
xacc
::
quantum
::
QIR
<
xacc
::
quantum
::
CircuitNode
>
{
...
...
@@ -70,24 +73,39 @@ class GateQIR: public virtual xacc::quantum::QIR<xacc::quantum::CircuitNode> {
protected:
/**
*
* Reference to the AcceleratorBuffer that this
* QIR operates on.
*/
std
::
shared_ptr
<
AcceleratorBuffer
>
buffer
;
public:
/**
* The nullary Constructor
*/
GateQIR
()
{
}
/**
* The constructor, takes an accelerator buffer at construction.
* @param buf
*/
GateQIR
(
std
::
shared_ptr
<
AcceleratorBuffer
>
buf
)
:
buffer
(
buf
)
{
}
/**
* Provide a new AcceleratorBuffer for this Gate QIR.
* @param buf
*/
virtual
void
setAcceleratorBuffer
(
std
::
shared_ptr
<
AcceleratorBuffer
>
buf
)
{
buffer
=
buf
;
}
/**
*
* This method takes the list of quantum instructions that this
* QIR contains and creates a graph representation of the
* quantum circuit.
*/
virtual
void
generateGraph
();
...
...
@@ -130,6 +148,45 @@ public:
virtual
~
GateQIR
()
{
}
private:
/**
* This method determines if a new layer should be added to the circuit.
*
* @param gateCommand
* @param qubitVarNameToId
* @param gates
* @param currentLayer
* @return
*/
bool
incrementLayer
(
const
std
::
vector
<
std
::
string
>&
gateCommand
,
std
::
map
<
std
::
string
,
int
>&
qubitVarNameToId
,
const
std
::
vector
<
CircuitNode
>&
gates
,
const
int
&
currentLayer
);
/**
* Generate all edges for the circuit graph starting at
* the given layer.
*
* @param layer
* @param graph
* @param gateOperations
* @param initialStateId
*/
void
generateEdgesFromLayer
(
const
int
layer
,
std
::
vector
<
CircuitNode
>&
gateOperations
,
int
initialStateId
);
/**