1mod misc;
5
6use self::misc::{arg_id, arg_to_id, is_unique};
7use crate::openqasm::ast::{
8 ast_to_vec::UOpOrBarrier,
9 AnyList, Argument, Decl, Exp, Exp1, Exp2, Exp3, Exp4, GateDecl, GopList, Identifier,
10 MainProgram, QOp, Statement, UOp,
11 UnaryOp::{Cos, Exp as Exponent, Ln, Sin, Sqrt, Tan},
12};
13use crate::parser::ast::ast_node::{ToRefVec, ToVec};
14use std::{cmp::Eq, collections::HashMap, hash::Hash};
15
16pub struct OpenQASMProgram {
23 pub gates: HashMap<String, Gate>,
26
27 pub qregs: HashMap<String, usize>,
30
31 pub cregs: HashMap<String, usize>,
34
35 pub operations: Vec<(Option<Condition>, Operation)>,
38}
39
40pub struct Gate {
42 pub num_targets: usize,
44
45 pub num_arguments: usize,
47
48 pub operations: Vec<GateOperation>,
50}
51
52pub type Expression = dyn Fn(&Vec<f32>) -> f32;
58
59pub enum GateOperation {
64 U(Box<Expression>, Box<Expression>, Box<Expression>, usize),
65 CX(usize, usize),
66 Custom(String, Vec<Box<Expression>>, Vec<usize>),
67}
68
69#[derive(Clone, PartialEq, Eq, Hash, Debug)]
72pub struct Qubit(pub String, pub usize);
73
74#[derive(Clone, Debug)]
77pub struct Cbit(pub String, pub usize);
78
79#[derive(Debug, Clone)]
84pub struct Condition(pub String, pub u32);
85
86#[derive(Debug)]
88pub enum Operation {
89 U(f32, f32, f32, Qubit),
91
92 CX(Qubit, Qubit),
94
95 Custom(String, Vec<f32>, Vec<Qubit>),
100
101 Measure(Qubit, Cbit),
103
104 ResetQ(Qubit),
106
107 ResetC(Cbit),
109}
110
111#[derive(Debug)]
113pub enum SemanticError {
114 UnsupportedVersion,
116
117 DuplicateRegisterDeclaration,
119
120 WrongNumberOfParameters,
122
123 WrongNumberOfTargets,
125
126 UnknownIdentifier,
128
129 IndexedRegisterInGateDecl,
133
134 SameTargetUsedTwice,
136
137 InvalidTargetDimensions,
141
142 IndexOutOfBounds,
144
145 OpaqueIsNotSupported,
147}
148
149impl OpenQASMProgram {
150 pub fn from_ast(ast_node: &MainProgram) -> Result<Self, SemanticError> {
152 let mut openqasm_program = OpenQASMProgram {
153 gates: HashMap::new(),
154 qregs: HashMap::new(),
155 cregs: HashMap::new(),
156 operations: Vec::new(),
157 };
158
159 if ast_node.0 .0 != "2.0" {
161 return Err(SemanticError::UnsupportedVersion);
162 }
163
164 for statement in ast_node.1.to_ref_vec() {
165 match statement {
166 Statement::Decl(decl) => openqasm_program.create_reg(decl)?,
167 Statement::GateDecl(gatedecl, goplist) => {
168 openqasm_program.create_gate(gatedecl, Some(goplist))?
169 }
170 Statement::GateDeclEmpty(gatedecl) => {
171 openqasm_program.create_gate(gatedecl, None)?
172 }
173 Statement::Opaque => return Err(SemanticError::OpaqueIsNotSupported),
174 Statement::QOp(qop) => {
175 openqasm_program.create_qop(qop, None)?;
176 }
177 Statement::If(id, int, qop) => {
178 if !openqasm_program.cregs.contains_key(&id.0) {
179 return Err(SemanticError::UnknownIdentifier);
180 }
181 let condition = Some(Condition(id.0.clone(), int.0));
182 openqasm_program.create_qop(qop, condition)?;
183 }
184 Statement::Barrier(_) => {}
185 };
186 }
187
188 Ok(openqasm_program)
189 }
190
191 fn create_reg(&mut self, decl: &Decl) -> Result<(), SemanticError> {
194 let res = match decl {
195 Decl::QReg(id, size) => self.qregs.insert(id.0.clone(), size.0 as usize),
196 Decl::CReg(id, size) => self.cregs.insert(id.0.clone(), size.0 as usize),
197 };
198 if res.is_some() {
199 return Err(SemanticError::DuplicateRegisterDeclaration);
200 }
201 Ok(())
202 }
203
204 fn create_gate(
207 &mut self,
208 gatedecl: &GateDecl,
209 goplist: Option<&GopList>,
210 ) -> Result<(), SemanticError> {
211 let (name, params, targets) = match gatedecl {
213 GateDecl::NoArgList(name, targets) => (name, vec![], targets.to_ref_vec()),
214 GateDecl::EmptyArgList(name, targets) => (name, vec![], targets.to_ref_vec()),
215 GateDecl::WithArgList(name, params, targets) => {
216 (name, params.to_ref_vec(), targets.to_ref_vec())
217 }
218 };
219
220 let mut gate_ops = Vec::new();
222 let goplist = goplist.map_or(vec![], |gl| gl.to_vec());
223 for gop in goplist {
224 match gop {
225 UOpOrBarrier::UOp(UOp::U(exps, target)) => {
226 let exps = exps.to_ref_vec();
227 if exps.len() != 3 {
228 return Err(SemanticError::WrongNumberOfParameters);
229 }
230 let exp1 = create_exp(exps[0], ¶ms)?;
231 let exp2 = create_exp(exps[1], ¶ms)?;
232 let exp3 = create_exp(exps[2], ¶ms)?;
233
234 let target = create_gate_targets(&vec![arg_to_id(&target)?], &targets)?;
235
236 gate_ops.push(GateOperation::U(exp1, exp2, exp3, target[0]));
237 }
238 UOpOrBarrier::UOp(UOp::CX(target1, target2)) => {
239 let op_targets = create_gate_targets(
240 &vec![arg_to_id(&target1)?, arg_to_id(&target2)?],
241 &targets,
242 )?;
243
244 gate_ops.push(GateOperation::CX(op_targets[0], op_targets[1]));
245 }
246 UOpOrBarrier::UOp(UOp::NoArgList(op_name, op_targets)) => {
247 gate_ops.push(create_custom_gate_op(
248 ¶ms,
249 &op_name,
250 vec![],
251 &op_targets,
252 &targets,
253 &self.gates,
254 )?);
255 }
256 UOpOrBarrier::UOp(UOp::EmptyArgList(op_name, op_targets)) => {
257 gate_ops.push(create_custom_gate_op(
258 ¶ms,
259 &op_name,
260 vec![],
261 &op_targets,
262 &targets,
263 &self.gates,
264 )?);
265 }
266 UOpOrBarrier::UOp(UOp::WithArgList(op_name, op_args, op_targets)) => {
267 gate_ops.push(create_custom_gate_op(
268 ¶ms,
269 &op_name,
270 op_args.to_ref_vec(),
271 &op_targets,
272 &targets,
273 &self.gates,
274 )?);
275 }
276 UOpOrBarrier::Barrier(_) => {} }
278 }
279
280 self.gates.insert(
281 name.0.clone(),
282 Gate {
283 num_targets: targets.len(),
284 num_arguments: params.len(),
285 operations: gate_ops,
286 },
287 );
288 Ok(())
289 }
290
291 fn create_qop(&mut self, qop: &QOp, condition: Option<Condition>) -> Result<(), SemanticError> {
294 match qop {
295 QOp::UOp(uop) => self.create_uop(uop, condition)?,
296 QOp::Measure(qubit, cbit) => {
297 let qbits = create_uop_targets(&vec![qubit.clone()], &self.qregs)?;
298 let cbits = create_uop_targets(&vec![cbit.clone()], &self.cregs)?;
299 if qbits.len() != cbits.len() {
300 return Err(SemanticError::InvalidTargetDimensions);
301 }
302 for (qubit, cbit) in qbits.iter().zip(cbits.iter()) {
303 let cbit = Cbit(cbit[0].0.clone(), cbit[0].1);
304 self.operations.push((
305 condition.clone(),
306 Operation::Measure(qubit[0].clone(), cbit),
307 ));
308 }
309 }
310 QOp::Reset(bit) => {
311 let qubits = create_uop_targets(&vec![bit.clone()], &self.qregs);
312 if let Ok(qubits) = qubits {
313 for qubits in qubits {
314 self.operations
315 .push((condition.clone(), Operation::ResetQ(qubits[0].clone())));
316 }
317 } else {
318 let cbits = create_uop_targets(&vec![bit.clone()], &self.cregs)?;
319 for cbits in cbits {
320 let cbit = Cbit(cbits[0].0.clone(), cbits[0].1);
321 self.operations
322 .push((condition.clone(), Operation::ResetC(cbit)));
323 }
324 }
325 }
326 }
327 Ok(())
328 }
329
330 fn create_uop(&mut self, uop: &UOp, condition: Option<Condition>) -> Result<(), SemanticError> {
332 match uop {
333 UOp::U(exps, target) => {
334 let exps: Result<Vec<_>, _> =
335 exps.to_ref_vec().iter().map(|e| exp_to_float(e)).collect();
336 let exps = exps?;
337 if exps.len() != 3 {
338 return Err(SemanticError::WrongNumberOfParameters);
339 }
340 let targets = create_uop_targets(&vec![target.clone()], &self.qregs)?;
341
342 for targets in targets.iter() {
343 self.operations.push((
344 condition.clone(),
345 Operation::U(exps[0], exps[1], exps[2], targets[0].clone()),
346 ));
347 }
348 }
349 UOp::CX(target1, target2) => {
350 let targets =
351 create_uop_targets(&vec![target1.clone(), target2.clone()], &self.qregs)?;
352
353 for targets in targets.iter() {
354 self.operations.push((
355 condition.clone(),
356 Operation::CX(targets[0].clone(), targets[1].clone()),
357 ));
358 }
359 }
360 UOp::NoArgList(name, targets) => {
361 let targets = create_uop_targets(&targets.to_vec(), &self.qregs)?;
362 for targets in targets {
363 self.operations.push((
364 condition.clone(),
365 create_cusom_uop(name, vec![], targets, &self.gates)?,
366 ));
367 }
368 }
369 UOp::EmptyArgList(name, targets) => {
370 let targets = create_uop_targets(&targets.to_vec(), &self.qregs)?;
371 for targets in targets {
372 self.operations.push((
373 condition.clone(),
374 create_cusom_uop(name, vec![], targets, &self.gates)?,
375 ));
376 }
377 }
378 UOp::WithArgList(name, params, targets) => {
379 let targets = create_uop_targets(&targets.to_vec(), &self.qregs)?;
380 for targets in targets {
381 self.operations.push((
382 condition.clone(),
383 create_cusom_uop(name, params.to_ref_vec(), targets, &self.gates)?,
384 ));
385 }
386 }
387 }
388
389 Ok(())
390 }
391}
392
393fn create_custom_gate_op(
395 params: &Vec<&Identifier>, op_name: &Identifier, op_params: Vec<&Exp>, op_targets: &AnyList, target_names: &Vec<&Identifier>, gates: &HashMap<String, Gate>, ) -> Result<GateOperation, SemanticError> {
402 let op_name = &op_name.0;
403 let op_targets = match op_targets {
404 AnyList::IdList(op_targets) => op_targets.to_ref_vec(),
405 AnyList::MixedList(_) => Err(SemanticError::IndexedRegisterInGateDecl)?,
406 };
407
408 if let Some(gate) = gates.get(op_name) {
409 if gate.num_targets != op_targets.len() {
410 return Err(SemanticError::WrongNumberOfTargets);
411 }
412
413 if gate.num_arguments != op_params.len() {
414 return Err(SemanticError::WrongNumberOfParameters);
415 }
416 } else {
417 return Err(SemanticError::UnknownIdentifier);
418 }
419
420 let op_params: Result<Vec<_>, _> = op_params.iter().map(|a| create_exp(a, ¶ms)).collect();
421 let op_params = op_params?;
422 let op_targets = create_gate_targets(&op_targets, target_names)?;
423
424 Ok(GateOperation::Custom(
425 op_name.clone(),
426 op_params,
427 op_targets,
428 ))
429}
430
431fn create_exp1(exp: &Exp1, exps: &Vec<&Identifier>) -> Result<Box<Expression>, SemanticError> {
433 match exp {
434 Exp1::Number(num) => {
435 let f = num.0.parse::<f32>().unwrap();
436 Ok(Box::new(move |_| f))
437 }
438 Exp1::Integer(int) => {
439 let i = int.0 as f32;
440 Ok(Box::new(move |_| i))
441 }
442 Exp1::Identifier(id) => {
443 let search = exps.iter().position(|&arg| arg.0 == id.0);
444 if let Some(i) = search {
445 Ok(Box::new(move |args| args[i]))
446 } else {
447 Err(SemanticError::UnknownIdentifier)
448 }
449 }
450 Exp1::Pi => Ok(Box::new(|_| std::f32::consts::PI)),
451 Exp1::Paren(exp) => create_exp(exp, exps),
452 Exp1::UnaryOp(uop, exp) => {
453 let exp = create_exp(exp, exps)?;
454 match uop {
455 Sin => Ok(Box::new(move |args| f32::sin(exp(args)))),
456 Cos => Ok(Box::new(move |args| f32::cos(exp(args)))),
457 Tan => Ok(Box::new(move |args| f32::tan(exp(args)))),
458 Exponent => Ok(Box::new(move |args| f32::exp(exp(args)))),
459 Ln => Ok(Box::new(move |args| f32::ln(exp(args)))),
460 Sqrt => Ok(Box::new(move |args| f32::sqrt(exp(args)))),
461 }
462 }
463 Exp1::Neg(exp) => {
464 let exp = create_exp(exp, exps)?;
465 Ok(Box::new(move |args| -exp(args)))
466 }
467 }
468}
469
470fn create_exp2(exp: &Exp2, exps: &Vec<&Identifier>) -> Result<Box<Expression>, SemanticError> {
472 match exp {
473 Exp2::Pow(lhs, rhs) => {
474 let lhs = create_exp1(lhs, exps)?;
475 let rhs = create_exp2(rhs, exps)?;
476 Ok(Box::new(move |args| lhs(args).powf(rhs(args))))
477 }
478 Exp2::Exp1(exp1) => create_exp1(exp1, exps),
479 }
480}
481
482fn create_exp3(exp: &Exp3, exps: &Vec<&Identifier>) -> Result<Box<Expression>, SemanticError> {
484 match exp {
485 Exp3::Mul(lhs, rhs) => {
486 let lhs = create_exp2(lhs, exps)?;
487 let rhs = create_exp3(rhs, exps)?;
488 Ok(Box::new(move |args| lhs(args) * rhs(args)))
489 }
490 Exp3::Div(lhs, rhs) => {
491 let lhs = create_exp2(lhs, exps)?;
492 let rhs = create_exp3(rhs, exps)?;
493 Ok(Box::new(move |args| lhs(args) / rhs(args)))
494 }
495 Exp3::Exp2(exp2) => create_exp2(exp2, exps),
496 }
497}
498
499fn create_exp4(exp: &Exp4, exps: &Vec<&Identifier>) -> Result<Box<Expression>, SemanticError> {
501 match exp {
502 Exp4::Add(lhs, rhs) => {
503 let lhs = create_exp3(lhs, exps)?;
504 let rhs = create_exp4(rhs, exps)?;
505 Ok(Box::new(move |args| lhs(args) + rhs(args)))
506 }
507 Exp4::Sub(lhs, rhs) => {
508 let lhs = create_exp3(lhs, exps)?;
509 let rhs = create_exp4(rhs, exps)?;
510 Ok(Box::new(move |args| lhs(args) - rhs(args)))
511 }
512 Exp4::Exp3(exp3) => create_exp3(exp3, exps),
513 }
514}
515
516fn create_exp(exp: &Exp, exps: &Vec<&Identifier>) -> Result<Box<Expression>, SemanticError> {
521 create_exp4(exp.0.as_ref(), exps)
522}
523
524fn create_gate_targets(
527 targets: &Vec<&Identifier>,
528 gate_targets: &Vec<&Identifier>,
529) -> Result<Vec<usize>, SemanticError> {
530 let res: Result<Vec<_>, _> = targets
531 .iter()
532 .map(|target| {
533 gate_targets
534 .iter()
535 .position(|t| t.0 == target.0)
536 .ok_or(SemanticError::UnknownIdentifier)
537 })
538 .collect();
539 let res = res?;
540 if is_unique(&res) {
541 Ok(res)
542 } else {
543 Err(SemanticError::SameTargetUsedTwice)
544 }
545}
546
547fn exp_to_float(exp: &Exp) -> Result<f32, SemanticError> {
551 let exp_fn = create_exp(exp, &vec![])?;
552 Ok(exp_fn(&vec![]))
553}
554
555fn create_uop_targets(
558 targets: &Vec<Argument>,
559 regs: &HashMap<String, usize>,
560) -> Result<Vec<Vec<Qubit>>, SemanticError> {
561 let mut arg_len = None;
563 for target in targets.iter() {
564 let target_len = regs
565 .get(arg_id(target))
566 .ok_or(SemanticError::UnknownIdentifier)?;
567
568 match target {
569 Argument::Id(_) => {
570 if let Some(arg_len) = arg_len {
571 if arg_len != target_len {
572 return Err(SemanticError::InvalidTargetDimensions);
573 }
574 } else {
575 arg_len = Some(target_len);
576 }
577 }
578 Argument::Indexed(_, index) => {
579 if index.0 as usize >= *target_len {
580 return Err(SemanticError::IndexOutOfBounds);
581 }
582 }
583 }
584 }
585 let arg_len = *arg_len.unwrap_or(&1);
586
587 let mut res = vec![];
588 for i in 0..arg_len {
589 let mut row = Vec::new();
590
591 for target in targets.iter() {
592 let qubit = match target {
593 Argument::Id(id) => Qubit(id.0.clone(), i),
594 Argument::Indexed(id, index) => Qubit(id.0.clone(), index.0 as usize),
595 };
596
597 row.push(qubit);
598 }
599
600 if !is_unique(&row) {
601 return Err(SemanticError::SameTargetUsedTwice);
602 }
603
604 res.push(row);
605 }
606
607 Ok(res)
608}
609
610fn create_cusom_uop(
612 name: &Identifier, params: Vec<&Exp>, targets: Vec<Qubit>, gates: &HashMap<String, Gate>, ) -> Result<Operation, SemanticError> {
617 let params: Result<Vec<_>, _> = params.to_vec().iter().map(|e| exp_to_float(e)).collect();
618 let params = params?;
619
620 let gate = gates.get(&name.0).ok_or(SemanticError::UnknownIdentifier)?;
621 if params.len() != gate.num_arguments {
622 return Err(SemanticError::WrongNumberOfParameters);
623 }
624 if targets.len() != gate.num_targets {
625 return Err(SemanticError::WrongNumberOfTargets);
626 }
627
628 Ok(Operation::Custom(name.0.clone(), params, targets))
629}