Commit b603d93e authored by Nguyen, Thien Minh's avatar Nguyen, Thien Minh
Browse files

Added conjugate circuit feature



compute the bra side by propagating the input circuit then perform inner product.

Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent 2503ba5a
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -140,6 +140,15 @@ void ITensorMPSVisitor::initialize(
  }
  // Debug
  // itensor::PrintData(m_mps);
  // Option to provide a circuit to construct the conjugate state for inner
  // product calculation.
  m_conjCircuit.reset();
  if (options.pointerLikeExists<xacc::CompositeInstruction>(
          "conjugate-circuit-inner-product")) {
    m_conjCircuit =
        xacc::as_shared_ptr(options.getPointerLike<xacc::CompositeInstruction>(
            "conjugate-circuit-inner-product"));
  }
}

itensor::Index ITensorMPSVisitor::getSiteIndex(size_t site_id) {
@@ -193,6 +202,35 @@ double ITensorMPSVisitor::compute_expectation_z(
}

void ITensorMPSVisitor::finalize() {
  if (m_conjCircuit) {
    itensor::SpinHalf sites(m_buffer->size(), {"ConserveQNs=", false});
    // Set all spins to be Up
    itensor::InitState state(sites, "Up");
    auto bra_mps = itensor::MPS(state);
    // Cache the ket MPS
    auto ket_mps = m_mps;

    // Set the running MPS to bra and visit the conj. circuit:
    m_mps = bra_mps;
    InstructionIterator it(m_conjCircuit);
    while (it.hasNext()) {
      auto nextInst = it.next();
      if (nextInst->isEnabled() && !nextInst->isComposite()) {
        if (nextInst->name() != "Measure") {
          nextInst->accept(this);
        } else {
          xacc::error("Illegal Measure instructions in conjugate circuit.");
        }
      }
    }

    const std::complex<double> inner_product = itensor::innerC(ket_mps, m_mps);
    // std::cout << "Inner product = " << inner_product << "\n";
    m_buffer->addExtraInfo("amplitude-real", inner_product.real());
    m_buffer->addExtraInfo("amplitude-imag", inner_product.imag());
    return;
  }

  // Assign the exp-val-z (single Composite mode)
  m_buffer->addExtraInfo("exp-val-z", compute_expectation_z(m_measureBits));
}
+1 −0
Original line number Diff line number Diff line
@@ -112,6 +112,7 @@ private:
  // SVD options
  double m_svdCutoff;
  int m_maxDim;
  std::shared_ptr<CompositeInstruction> m_conjCircuit;
};

} // namespace tnqvm
+31 −0
Original line number Diff line number Diff line
@@ -519,6 +519,37 @@ TEST(ITensorMPSVisitorTester, testDeuteronVqeH3) {
  EXPECT_NEAR((*buffer)["opt-val"].as<double>(), -2.04482, 1e-4);
}

TEST(ITensorMPSVisitorTester, testAmplitudeCalcByConjCircuit) {
  auto gateRegistry = xacc::getIRProvider("quantum");
  auto xasmCompiler = xacc::getCompiler("xasm");

  auto conj_circ = gateRegistry->createComposite("temp_circuit");
  conj_circ->addInstruction(gateRegistry->createInstruction("X", {0}));
  conj_circ->addInstruction(gateRegistry->createInstruction("X", {1}));
  conj_circ->addInstruction(gateRegistry->createInstruction("X", {2}));

  auto accelerator = xacc::getAccelerator(
      "tnqvm", {{"conjugate-circuit-inner-product", conj_circ}});

  auto program = xasmCompiler
                     ->compile(R"(__qpu__ void ghz(qbit q, double t) {
      H(q[0]);
      Z(q[0]);
      CX(q[0], q[1]);
      CX(q[1], q[2]);
  })",
                               accelerator)
                     ->getComposites()[0];

  auto buffer = xacc::qalloc(3);
  accelerator->execute(buffer, program);
  buffer->print();
  const double realAmpl = (*buffer)["amplitude-real"].as<double>();
  const double imagAmpl = (*buffer)["amplitude-imag"].as<double>();
  EXPECT_NEAR(realAmpl, -1.0/std::sqrt(2.0), 1e-6);
  EXPECT_NEAR(imagAmpl, 0.0, 1e-6);
}

int main(int argc, char **argv) {
  xacc::Initialize(argc, argv);
  ::testing::InitGoogleTest(&argc, argv);