libqasm
library for handling cQASM files
qasm_semantic.hpp
Go to the documentation of this file.
1 #pragma once
2 #ifndef AST_SEMANTIC_HPP
3 
4 #include <stdio.h>
5 #include <string.h>
6 #include <vector>
7 #include <exception>
8 #include "qasm_ast.hpp"
9 #include "qasm_data.hpp"
10 #ifndef SWIG
11 #include "qasm_new_to_old.hpp"
12 #endif
13 
14 namespace compiler
15 {
17  {
18  public:
19  QasmSemanticChecker(const char* qasm_str_input)
20  {
21  if (!qasm_str_input) {
22  throw std::invalid_argument("received null string");
23  }
24  new_to_old::handle_parse_result(
25  qasm_, cqasm::parser::parse_string(qasm_str_input));
28  }
29 
30  QasmSemanticChecker(FILE* qasm_file)
31  {
32  if (!qasm_file) {
33  throw std::invalid_argument("received null file pointer");
34  }
35  new_to_old::handle_parse_result(
36  qasm_, cqasm::parser::parse_file(qasm_file));
39  }
40 
41  int parseResult() const
42  {
43  return parse_result_;
44  }
45 
47  {
48  return qasm_;
49  }
50 
51  protected:
53  size_t maxNumQubit_;
55 
56  int doChecks()
57  {
58  int checkResult = 0;
59  for (auto subcircuit : qasm_.getSubCircuits().getAllSubCircuits())
60  {
61  if (subcircuit.numberIterations() < 1)
62  {
63  std::string base_error_message("Iteration count invalid for subcircuit");
64  std::string entire_error_message = base_error_message +
65  " " + subcircuit.nameSubCircuit() +
66  " on Line: " +
67  std::to_string(subcircuit.getLineNumber());
68  throw std::runtime_error(entire_error_message);
69  }
70  for (auto ops_cluster : subcircuit.getOperationsCluster())
71  {
72  int linenumber = ops_cluster->getLineNumber();
73  for (auto ops : ops_cluster->getOperations())
74  {
75  checkQubits(*ops, checkResult, linenumber);
76  }
77  }
78  }
79 
80  if (checkResult)
81  throw std::runtime_error(std::string("Qasm file invalid\n"));
82  return checkResult;
83  }
84 
85  void checkQubits(compiler::Operation& op, int& result, int linenumber)
86  {
87  std::string type_ = op.getType();
88  if (type_ == "measure_parity")
89  {
90  result = checkMeasureParity(op, linenumber);
91  }
92  else if (type_ == "u")
93  {
94  result = checkUnitaryGate(op, linenumber);
95  }
96  else if (type_ == "cnot" || type_ == "cz" || type_ == "swap" || type_ == "cr" || type_ == "crk")
97  {
98  result = checkTwoQubits(op, linenumber);
99  }
100  else if (type_ == "toffoli")
101  {
102  result = checkToffoli(op, linenumber);
103  }
104  else if (type_ == "measure_all")
105  {
106  result = checkMeasureAll(op, linenumber);
107  }
108  else if (type_ == "reset-averaging")
109  {
110  result = checkResetAveraging(op, linenumber);
111  }
112  else if (type_ == "skip" || type_ == "wait" || type_ == "display" || type_ == "display_binary" || type_ == "not" || type_ == "load_state")
113  {
114  result = checkWaitDisplayNot(op, linenumber);
115  }
116  else
117  // No other special operations. Left with single qubits
118  {
119  try
120  {
121  result = checkSingleQubit(op, linenumber);
122  }
123  catch (...)
124  {
125  throw std::runtime_error(std::string("Operation invalid.") + std::string(" Line: ") + std::to_string(linenumber));
126  }
127  }
128  if (result > 0)
129  throw std::runtime_error(std::string("Operation invalid. ") + "Line " + std::to_string(linenumber));
130 
131  }
132 
133  int checkQubitList(const compiler::Qubits& qubits, int linenumber) const
134  {
135  auto indices = qubits.getSelectedQubits().getIndices();
136  if (indices.back() < maxNumQubit_)
137  return 0;
138  else
139  throw std::runtime_error(std::string("Qubit indices exceed the number in qubit register. Line: ")
140  + std::to_string(linenumber));
141  }
142 
144  const compiler::Qubits& qubits2,
145  int linenumber) const
146  // This function ensures that the lengths of the qubit lists are the same for the different pairs involved in the operation
147  {
148  (void)linenumber;
149  int retnum = 1;
150  if (qubits1.getSelectedQubits().getIndices().size() ==
151  qubits2.getSelectedQubits().getIndices().size())
152  {
153  retnum = 0;
154  }
155  return retnum;
156  }
157 
158  int checkUnitaryGate(const compiler::Operation& op, int linenumber) const
159  {
160  int result = 1;
161  int resultlist = checkQubitList(op.getQubitsInvolved(), linenumber);
162  if (resultlist > 0)
163  {
164  std::string base_error_message("Matrix is not unitary. Line: ");
165  std::string entire_error_message = base_error_message +
166  std::to_string(linenumber);
167  throw std::runtime_error(entire_error_message);
168  }
169  result *= resultlist;
170  return result;
171  }
172 
173  int checkSingleQubit(const compiler::Operation& op, int linenumber) const
174  {
175  return checkQubitList(op.getQubitsInvolved(), linenumber);
176  }
177 
178  int checkWaitDisplayNot(const compiler::Operation& op, int linenumber) const
179  {
180  (void)op;
181  (void)linenumber;
182  return 0;
183  }
184 
185  int checkResetAveraging(const compiler::Operation& op, int linenumber) const
186  {
187  int result = 1;
188  if (op.allQubitsBits())
189  result = 0;
190  else
191  result = checkQubitList(op.getQubitsInvolved(), linenumber);
192  return result;
193  }
194 
195  int checkMeasureAll(const compiler::Operation& op, int linenumber) const
196  {
197  (void)op;
198  (void)linenumber;
199  return 0;
200  }
201 
202  int checkToffoli(const compiler::Operation& op, int linenumber) const
203  {
204  int result = 1;
205  int resultlist = checkQubitList(op.getToffoliQubitPairs().first, linenumber);
206  resultlist += checkQubitList(op.getToffoliQubitPairs().second.first, linenumber);
207  resultlist += checkQubitList(op.getToffoliQubitPairs().second.second, linenumber);
208  resultlist += checkQubitListLength(op.getQubitsInvolved(1), op.getQubitsInvolved(2), linenumber);
209  resultlist += checkQubitListLength(op.getQubitsInvolved(2), op.getQubitsInvolved(3), linenumber);
210  if (resultlist > 0)
211  {
212  std::string base_error_message("Mismatch in the qubit pair sizes. Line: ");
213  std::string entire_error_message = base_error_message +
214  std::to_string(linenumber);
215  throw std::runtime_error(entire_error_message);
216  }
217  result *= resultlist;
218  return result;
219  }
220 
221  int checkTwoQubits(const compiler::Operation& op, int linenumber) const
222  {
223  int result = 1;
224  int resultlist = checkQubitList(op.getTwoQubitPairs().first, linenumber);
225  resultlist += checkQubitList(op.getTwoQubitPairs().second, linenumber);
226  resultlist += checkQubitListLength(op.getQubitsInvolved(1), op.getQubitsInvolved(2), linenumber);
227  if (resultlist > 0)
228  {
229  std::string base_error_message("Mismatch in the qubit pair sizes. Line: ");
230  std::string entire_error_message = base_error_message +
231  std::to_string(linenumber);
232  throw std::runtime_error(entire_error_message);
233  }
234  result *= resultlist;
235  return result;
236  }
237 
238  int checkMeasureParity(const compiler::Operation& op, int linenumber) const
239  {
240  int result = 1;
241  auto measureParityProperties = op.getMeasureParityQubitsAndAxis();
242  int resultlist = checkQubitList(measureParityProperties.first.first, linenumber);
243  resultlist += checkQubitList(measureParityProperties.first.second, linenumber);
244  result *= resultlist;
245  return result;
246  }
247 
248 
249  }; // class QasmSemanticChecker
250 
251 } // namespace compiler
252 
253 #endif
int checkWaitDisplayNot(const compiler::Operation &op, int linenumber) const
compiler::QasmRepresentation qasm_
QasmSemanticChecker(FILE *qasm_file)
int checkTwoQubits(const compiler::Operation &op, int linenumber) const
int checkQubitListLength(const compiler::Qubits &qubits1, const compiler::Qubits &qubits2, int linenumber) const
SubCircuits & getSubCircuits()
Definition: qasm_ast.hpp:638
const compiler::QasmRepresentation & getQasmRepresentation() const
const std::pair< Qubits, std::pair< Qubits, Qubits > > & getToffoliQubitPairs() const
Definition: qasm_ast.hpp:276
int checkUnitaryGate(const compiler::Operation &op, int linenumber) const
const NumericalIdentifiers & getSelectedQubits() const
Definition: qasm_ast.hpp:83
const Qubits & getQubitsInvolved() const
Definition: qasm_ast.hpp:223
const std::vector< SubCircuit > & getAllSubCircuits() const
Definition: qasm_ast.hpp:597
const std::pair< std::pair< Qubits, Qubits >, std::pair< std::string, std::string > > getMeasureParityQubitsAndAxis() const
Definition: qasm_ast.hpp:265
Namespace used for most of the original API.
Definition: qasm_ast.hpp:18
int checkMeasureParity(const compiler::Operation &op, int linenumber) const
int checkToffoli(const compiler::Operation &op, int linenumber) const
std::string getType() const
Definition: qasm_ast.hpp:213
const std::pair< Qubits, Qubits > & getTwoQubitPairs() const
Definition: qasm_ast.hpp:271
int checkQubitList(const compiler::Qubits &qubits, int linenumber) const
Contains the guts of the compatibility layer, parsing using Analyzer and converting the result to an ...
ParseResult parse_string(const std::string &data, const std::string &filename)
Parse the given string.
QasmSemanticChecker(const char *qasm_str_input)
int checkResetAveraging(const compiler::Operation &op, int linenumber) const
bool allQubitsBits() const
Definition: qasm_ast.hpp:286
void checkQubits(compiler::Operation &op, int &result, int linenumber)
int checkMeasureAll(const compiler::Operation &op, int linenumber) const
const std::vector< size_t > & getIndices() const
Definition: qasm_ast.hpp:40
ParseResult parse_file(const std::string &filename)
Parse the given file.
int checkSingleQubit(const compiler::Operation &op, int linenumber) const