forked from ProjectQ-Framework/ProjectQ
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path_printer.py
More file actions
executable file
·123 lines (105 loc) · 4.86 KB
/
Copy path_printer.py
File metadata and controls
executable file
·123 lines (105 loc) · 4.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# -*- coding: utf-8 -*-
# Copyright 2017 ProjectQ-Framework (www.projectq.ch)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Contains a compiler engine which prints commands to stdout prior to sending them on to the next engines."""
import sys
from builtins import input
from projectq.cengines import BasicEngine, LastEngineException
from projectq.meta import LogicalQubitIDTag, get_control_count
from projectq.ops import FlushGate, Measure
from projectq.types import WeakQubitRef
class CommandPrinter(BasicEngine):
"""
Compiler engine that prints command to the standard output.
CommandPrinter is a compiler engine which prints commands to stdout prior to sending them on to the next compiler
engine.
"""
def __init__(self, accept_input=True, default_measure=False, in_place=False):
"""
Initialize a CommandPrinter.
Args:
accept_input (bool): If accept_input is true, the printer queries the user to input measurement results if
the CommandPrinter is the last engine. Otherwise, all measurements yield default_measure.
default_measure (bool): Default measurement result (if accept_input is False).
in_place (bool): If in_place is true, all output is written on the same line of the terminal.
"""
super().__init__()
self._accept_input = accept_input
self._default_measure = default_measure
self._in_place = in_place
def is_available(self, cmd):
"""
Test whether a Command is supported by a compiler engine.
Specialized implementation of is_available: Returns True if the CommandPrinter is the last engine (since it
can print any command).
Args:
cmd (Command): Command of which to check availability (all Commands can be printed).
Returns:
availability (bool): True, unless the next engine cannot handle the Command (if there is a next engine).
"""
try:
return BasicEngine.is_available(self, cmd)
except LastEngineException:
return True
def _print_cmd(self, cmd):
"""
Print a command.
Print a command or, if the command is a measurement instruction and the CommandPrinter is the last engine in
the engine pipeline: Query the user for the measurement result (if accept_input = True) / Set the result to 0
(if it's False).
Args:
cmd (Command): Command to print.
"""
if self.is_last_engine and cmd.gate == Measure:
if get_control_count(cmd) != 0:
raise ValueError('Cannot have control qubits with a measurement gate!')
print(cmd)
for qureg in cmd.qubits:
for qubit in qureg:
if self._accept_input:
meas = None
while meas not in ('0', '1', 1, 0):
prompt = "Input measurement result (0 or 1) for qubit " + str(qubit) + ": "
meas = input(prompt)
else:
meas = self._default_measure
meas = int(meas)
# Check there was a mapper and redirect result
logical_id_tag = None
for tag in cmd.tags:
if isinstance(tag, LogicalQubitIDTag):
logical_id_tag = tag
if logical_id_tag is not None:
qubit = WeakQubitRef(qubit.engine, logical_id_tag.logical_qubit_id)
self.main_engine.set_measurement_result(qubit, meas)
else:
if self._in_place: # pragma: no cover
sys.stdout.write("\0\r\t\x1b[K" + str(cmd) + "\r")
else:
print(cmd)
def receive(self, command_list):
"""
Receive a list of commands.
Receive a list of commands from the previous engine, print the
commands, and then send them on to the next engine.
Args:
command_list (list<Command>): List of Commands to print (and
potentially send on to the next engine).
"""
for cmd in command_list:
if not cmd.gate == FlushGate():
self._print_cmd(cmd)
# (try to) send on
if not self.is_last_engine:
self.send([cmd])