Commit ed06b06f authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

Merge branch 'mccaskey/mlir_value_semantics' into mccaskey/runtime_pimpl

parents 60d017d3 85894c95
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2,3 +2,4 @@
#define QCOR_LIB_SUFFIX "${CMAKE_SHARED_LIBRARY_SUFFIX}"
#define QCOR_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}"
#define XACC_ROOT "${XACC_ROOT}"
#define LLVM_ROOT "${LLVM_INSTALL_PREFIX}"
+47 −0
Original line number Diff line number Diff line
#include <qcor_hadamard_test>

int main() {
  // Create the Deuteron Hamiltonian
  auto H = 5.907 - 2.1433 * X(0) * X(1) - 2.1433 * Y(0) * Y(1) + .21829 * Z(0) -
           6.125 * Z(1);

  for (auto x : linspace(-constants::pi, constants::pi, 10)) {
    auto terms = H.getNonIdentitySubTerms();
    double sum = H.getIdentitySubTerm()->coefficient().real();
    for (auto term : terms) {
      auto pop = std::dynamic_pointer_cast<PauliOperator>(term);

      assert(pop && pop->nTerms() == 1);

      auto [zv, xv] = pop->toBinaryVectors(2);

      auto sp = qpu_lambda(
          [](qreg q) {
            X(q.head());
            Ry(q.tail(), x);
            X::ctrl(q.tail(), q.head());
          },
          x);

      auto l = qpu_lambda(
          [](qreg q) {
            for (auto [i, x_val] : enumerate(xv)) {
              auto z_val = zv[i];
              if (x_val == z_val && x_val == 1) {
                Y(q[i]);
              } else if (x_val == 1) {
                X(q[i]);
              } else if (z_val == 1) {
                Z(q[i]);
              }
            }
          },
          xv, zv);

      auto val = qcor::hadamard_test(sp, l, 2);
      sum += pop->coefficient().real() * val;
    }

    print("E(", x, ") = ", sum);
  }
}
 No newline at end of file
+8 −0
Original line number Diff line number Diff line
@@ -34,6 +34,14 @@ double hadamard_test(StatePrep state_prep, Unitary unitary,
  auto q = qalloc(n_state_qubits + 1);
  __quantum_hadamard_test(q, state_prep, unitary);
  // Compute <psi|U|psi>
  // First make sure we have counts, 
  // if not, grab exp-val-z key in buffer
  auto counts = q.counts();
  if (counts.empty()) {
    return q.results()->getExpectationValueZ();
  }
 
  // We have counts, so use that
  double count1 = (double)q.counts().find("1")->second;
  double count2 = (double)q.counts().find("0")->second;
  return std::fabs((count1 - count2) / (count1 + count2));
+1 −2
Original line number Diff line number Diff line
@@ -15,4 +15,3 @@

#define GET_OP_CLASSES
#include "Quantum/QuantumOps.h.inc"
 No newline at end of file
+55 −0
Original line number Diff line number Diff line
@@ -15,6 +15,10 @@ def StringType : OpaqueType<"quantum", "StringType", "opaque string type">;
def QallocOp : QuantumOp<"qalloc", []> {
    let arguments = (ins AnyI64Attr:$size, StrAttr:$name);
    let results = (outs ArrayType:$qubits);

    let printer = [{  auto op = *this;
  p << "q.qalloc(" << op.size() << ") { name = " << op.name() << " }";
  p << " : " << op.qubits().getType(); }];
}

// Create an array holding Qubit pointers for aliasing purposes,
@@ -27,6 +31,9 @@ def QaliasArrayAllocOp : QuantumOp<"createQubitArray", []> {
def ExtractQubitOp : QuantumOp<"qextract", []> {
    let arguments = (ins ArrayType:$qreg, AnyInteger:$idx);
    let results = (outs QubitType:$qbit);
    let printer = [{  auto op = *this;
  p << "q.extract(" << op.getOperands() << ")";
  p << " : " << op.qbit().getType(); }];
}

def GeneralArrayExtractOp : QuantumOp<"array_extract", []> {
@@ -55,11 +62,17 @@ def ArrayConcatOp : QuantumOp<"qarray_concat", []> {
def StartCtrlURegion : QuantumOp<"start_ctrl_u_region", []> {
  let arguments = (ins);
  let results = (outs);
  let printer = [{  
  p << "q.ctrl_region {";
  }];
}

def EndCtrlURegion : QuantumOp<"end_ctrl_u_region", []> {
  let arguments = (ins QubitType:$ctrl_qubit);
  let results = (outs);
  let printer = [{  auto op = *this;
  p << "} (ctrl_bit = " << op.ctrl_qubit() << ")";
  }];
}

def StartAdjointURegion : QuantumOp<"start_adj_u_region", []> {
@@ -85,36 +98,78 @@ def EndPowURegion : QuantumOp<"end_pow_u_region", []> {
def InstOp : QuantumOp<"inst", [AttrSizedOperandSegments]> {
    let arguments = (ins StrAttr:$name, Variadic<QubitType>:$qubits, Variadic<F64>:$params);
    let results = (outs Optional<ResultType>:$bit);

    let printer = [{  auto op = *this;
  p << "q." << op.name() << "(" << op.getOperands() << ") : " << op.getResultTypes(); }];
}

def ValueSemanticsInstOp : QuantumOp<"value_inst", [AttrSizedOperandSegments]> {
    let arguments = (ins StrAttr:$name, Variadic<QubitType>:$qubits, Variadic<F64>:$params);
    let results = (outs Variadic<AnyTypeOf<[ResultType, QubitType]>>:$result);

    let printer = [{  auto op = *this;
  p << "qvs." << op.name() << "(" << op.getOperands() << ") : " << op.result().getType(); }]; 
}

def DeallocOp : QuantumOp<"dealloc", []> {
    let arguments = (ins ArrayType:$qubits);
    let results = (outs);
    let printer = [{  auto op = *this;
  p << "q.dealloc(" << op.qubits() << ")"; }];
}

def QRTInitOp : QuantumOp<"init", []> {
    let arguments = (ins AnyI32:$argc, ArgvType:$argv);
    let results = (outs);
    let printer = [{  auto op = *this;
  p << "q.init(" << op.getOperands() << ")"; }];
}

def QRTFinalizeOp : QuantumOp<"finalize", []> {
    let arguments = (ins);
    let results = (outs);
    let printer = [{  p << "q.finalize()"; }];
}

def SetQregOp : QuantumOp<"set_qreg", []> {
    let arguments = (ins QregType:$qreg);
    let results = (outs);
    let printer = [{  auto op = *this;
  p << "q.set_qreg(" << op.qreg() << ")"; }];
}

def PrintOp : QuantumOp<"print", []> {
    let arguments = (ins Variadic<AnyType>:$print_args);
    let results = (outs);
let printer = [{  auto op = *this;
  p << "q.print(" << op.getOperands() << ")"; }];
}

def CreateStringLiteralOp : QuantumOp<"createString", []> {
    let arguments = (ins StrAttr:$text, StrAttr:$varname);
    let results = (outs StringType:$result);
    let printer = [{  auto op = *this;
  p << "q.create_string(\"" << op.text() << "\")"; }];
}

// Cast QIR Result to bool (i1 type)
def ResultCastOp : QuantumOp<"resultCast", []> {
    let arguments = (ins ResultType:$measure_result);
    let results = (outs I1:$bit_result);
    let printer = [{  auto op = *this;
  p << "q.resultCast" << "(" << op.measure_result() << ") : " << op.bit_result().getType(); }];
}

// Sign-Unsign cast:
// Rationale: std dialect only accepts signless type (i.e. int but not uint)
// we need to have this cast op in the dialect to finally lower to LLVM cast 
// which can handle int -> uint casting at the final lowering phase.
// Note: std.index_cast cannot handle int -> unit casting (one of the type must be an index type).
def IntegerCastOp : QuantumOp<"integerCast", []> {
    let arguments = (ins AnyInteger:$input);
    let results = (outs AnyInteger:$output);
    let printer = [{  auto op = *this;
  p << "q.integerCast" << "(" << op.input() << ") : " << op.output().getType(); }];
}

#endif // Quantum_OPS
 No newline at end of file
Loading