Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
lasradorohan authored Jan 22, 2025
2 parents e1533e1 + e50fd94 commit c4dfcfb
Show file tree
Hide file tree
Showing 11 changed files with 76 additions and 142 deletions.
25 changes: 17 additions & 8 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@

<h3>Internal changes ⚙️</h3>

* The `get_c_interface` method has been added to the OQD device, which enables retrieval of the C++
implementation of the device from Python. This allows `qjit` to accept an instance of the device
and connect to its runtime.
[(#1420)](https://github.com/PennyLaneAI/catalyst/pull/1420)

* `from_plxpr` now uses the `qml.capture.PlxprInterpreter` class for reduced code duplication.
[(#1398)](https://github.com/PennyLaneAI/catalyst/pull/1398)

Expand All @@ -30,13 +25,27 @@
* Replace `ValueRange` with `ResultRange` and `Value` with `OpResult` to better align with the semantics of `**QubitResult()` functions like `getNonCtrlQubitResults()`. This change ensures clearer intent and usage. Improve the `matchAndRewrite` function by using `replaceAllUsesWith` instead of for loop.
[(#1426)](https://github.com/PennyLaneAI/catalyst/pull/1426)

* Several changes for experimental support of trapped-ion OQD devices have been made, including:

- The `get_c_interface` method has been added to the OQD device, which enables retrieval of the C++
implementation of the device from Python. This allows `qjit` to accept an instance of the device
and connect to its runtime.
[(#1420)](https://github.com/PennyLaneAI/catalyst/pull/1420)

- Improved ion dialect to reduce redundant code generated. Added a string attribute `label` to Level.
Also changed the levels of a transition from `LevelAttr` to `string`
[(#1471)](https://github.com/PennyLaneAI/catalyst/pull/1471)

- The region of a `ParallelProtocolOp` is now always terminated with a `ion::YieldOp` with explicitly yielded SSA values. This ensures the op is well-formed, and improves readability.
[(#1475)](https://github.com/PennyLaneAI/catalyst/pull/1475)

<h3>Documentation 📝</h3>

<h3>Contributors ✍️</h3>

This release contains contributions from (in alphabetical order):

Christina Lee
Mehrdad Malekmohammadi
Sengthai Heng
Sengthai Heng,
Christina Lee,
Mehrdad Malekmohammadi,
Paul Haochen Wang.
2 changes: 1 addition & 1 deletion frontend/catalyst/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@
Version number (major.minor.patch[-label])
"""

__version__ = "0.11.0-dev12"
__version__ = "0.11.0-dev13"
12 changes: 7 additions & 5 deletions mlir/include/Ion/IR/IonOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def LevelAttr : Ion_Attr<"Level", "level"> {
let summary = "A class to represent an atomic level.";

let parameters = (ins
"mlir::StringAttr":$label,
"mlir::IntegerAttr":$principal,
"mlir::FloatAttr":$spin,
"mlir::FloatAttr":$orbital,
Expand All @@ -63,6 +64,7 @@ def LevelAttr : Ion_Attr<"Level", "level"> {

let builders = [
AttrBuilderWithInferredContext<(ins
"mlir::StringAttr":$label,
"mlir::IntegerAttr":$principal,
"mlir::FloatAttr":$spin,
"mlir::FloatAttr":$orbital,
Expand All @@ -71,7 +73,7 @@ def LevelAttr : Ion_Attr<"Level", "level"> {
"mlir::FloatAttr":$spin_orbital_nuclear,
"mlir::FloatAttr":$spin_orbital_nuclear_magnetization,
"mlir::FloatAttr":$energy), [{
return $_get(principal.getContext(), principal, spin, orbital, nuclear, spin_orbital, spin_orbital_nuclear, spin_orbital_nuclear_magnetization, energy);
return $_get(principal.getContext(), label, principal, spin, orbital, nuclear, spin_orbital, spin_orbital_nuclear, spin_orbital_nuclear_magnetization, energy);
}]>
];

Expand All @@ -82,14 +84,14 @@ def TransitionAttr : Ion_Attr<"Transition", "transition"> {
let summary = "A class to represent a atomic transition between two levels.";

let parameters = (ins
"LevelAttr":$level_0,
"LevelAttr":$level_1,
"mlir::StringAttr":$level_0,
"mlir::StringAttr":$level_1,
"mlir::FloatAttr":$einstein_a
);

let builders = [
AttrBuilderWithInferredContext<(ins "LevelAttr":$level_0,
"LevelAttr":$level_1,
AttrBuilderWithInferredContext<(ins "mlir::StringAttr":$level_0,
"mlir::StringAttr":$level_1,
"mlir::FloatAttr":$einstein_a), [{
return $_get(einstein_a.getContext(), level_0, level_1, einstein_a);
}]>
Expand Down
20 changes: 7 additions & 13 deletions mlir/include/Ion/Transforms/oqd_database_managers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include <algorithm>
#include <cassert>
#include <set>

#include <toml++/toml.hpp>

Expand Down Expand Up @@ -133,6 +134,7 @@ class OQDDatabaseManager {
toml::node_view<toml::node> ionsToml = sourceTomlQubit["ions"];

auto parseSingleLevel = [](auto level) {
std::string label = level["label"].as_string()->get();
int64_t principal = level["principal"].as_integer()->get();

std::vector<std::string> properties{"spin",
Expand All @@ -149,29 +151,22 @@ class OQDDatabaseManager {
return level[name].as_floating_point()->get();
});

return Level(principal, propertiesData[0], propertiesData[1], propertiesData[2],
return Level(label, principal, propertiesData[0], propertiesData[1], propertiesData[2],
propertiesData[3], propertiesData[4], propertiesData[5],
propertiesData[6]);
};

auto parseSingleTransition = [](const auto &transition_entry,
const std::vector<Level> &allLevels) {
// FIXME: `allLevels` is hardcoded as {downstate, upstate, estate}
// Not super important, as the ion species is extremely unlikely to change, so
// hardcoding is fine

auto parseSingleTransition = [](const auto &transition_entry) {
double einstein_a = transition_entry["einstein_a"].as_floating_point()->get();
std::string level1 = transition_entry["level1"].as_string()->get();
std::string level2 = transition_entry["level2"].as_string()->get();

std::map<std::string, int64_t> levelEncodings{
{"downstate", 0}, {"upstate", 1}, {"estate", 2}};
std::set<std::string> levelEncodings{"downstate", "upstate", "estate"};
assert((levelEncodings.count(level1) & levelEncodings.count(level2)) &&
"Only \"downstate\", \"upstate\" and \"estate\" are allowed in the atom's "
"transition levels.");

return Transition(allLevels[levelEncodings[level1]], allLevels[levelEncodings[level2]],
einstein_a);
return Transition(level1, level2, einstein_a);
};

for (auto &ion_it : *(ionsToml.as_table())) {
Expand All @@ -192,8 +187,7 @@ class OQDDatabaseManager {
std::vector<Transition> transitions;
auto *transitionsTable = data->at_path("transitions").as_table();
for (auto &transition : *transitionsTable) {
transitions.push_back(
parseSingleTransition(*(transition.second.as_table()), levels));
transitions.push_back(parseSingleTransition(*(transition.second.as_table())));
}

Ion ion(name, mass, charge, position, levels, transitions);
Expand Down
12 changes: 7 additions & 5 deletions mlir/include/Ion/Transforms/oqd_database_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,15 @@ struct PhononMode {
struct Level {
// This class represents an atomic level.
// It contains the innate properties of the qubit.
std::string label;
int64_t principal;
double spin, orbital, nuclear, spin_orbital, spin_orbital_nuclear,
spin_orbital_nuclear_magnetization, energy;

Level(int64_t _principal, double _spin, double _orbital, double _nuclear, double _spin_orbital,
double _spin_orbital_nuclear, double _spin_orbital_nuclear_magnetization, double _energy)
: principal(_principal), spin(_spin), orbital(_orbital), nuclear(_nuclear),
Level(std::string _label, int64_t _principal, double _spin, double _orbital, double _nuclear,
double _spin_orbital, double _spin_orbital_nuclear,
double _spin_orbital_nuclear_magnetization, double _energy)
: label(_label), principal(_principal), spin(_spin), orbital(_orbital), nuclear(_nuclear),
spin_orbital(_spin_orbital), spin_orbital_nuclear(_spin_orbital_nuclear),
spin_orbital_nuclear_magnetization(_spin_orbital_nuclear_magnetization), energy(_energy)
{
Expand All @@ -79,10 +81,10 @@ struct Level {
struct Transition {
// This class represents a transition between two atomic levels.
// It contains the innate properties of the qubit.
Level level_0, level_1;
std::string level_0, level_1;
double einstein_a;

Transition(Level _level_0, Level _level_1, double _einstein_a)
Transition(std::string _level_0, std::string _level_1, double _einstein_a)
: level_0(_level_0), level_1(_level_1), einstein_a(_einstein_a)
{
}
Expand Down
9 changes: 7 additions & 2 deletions mlir/lib/Ion/IR/IonOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,23 @@ void ParallelProtocolOp::build(OpBuilder &builder, OperationState &result, Value
BodyBuilderFn bodyBuilder)
{
OpBuilder::InsertionGuard guard(builder);
Location loc = result.location;

result.addOperands(inQubits);
for (Value v : inQubits)
result.addTypes(v.getType());

Region *bodyRegion = result.addRegion();
Block *bodyBlock = builder.createBlock(bodyRegion);
for (Value v : inQubits)
for (Value v : inQubits) {
bodyBlock->addArgument(v.getType(), v.getLoc());
}

builder.setInsertionPointToStart(bodyBlock);
bodyBuilder(builder, result.location, bodyBlock->getArguments());
bodyBuilder(builder, loc, bodyBlock->getArguments());

builder.setInsertionPointToEnd(bodyBlock);
builder.create<ion::YieldOp>(loc, bodyBlock->getArguments());
}

//===----------------------------------------------------------------------===//
Expand Down
3 changes: 0 additions & 3 deletions mlir/lib/Ion/Transforms/QuantumToIonPatterns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,6 @@ mlir::LogicalResult oneQubitGateToPulse(CustomOp op, mlir::PatternRewriter &rewr
auto qubit = qubits.front();
builder.create<ion::PulseOp>(loc, time, qubit, beam0toEAttr, phase1Attr);
builder.create<ion::PulseOp>(loc, time, qubit, beam1toEAttr, phase2Attr);
builder.create<ion::YieldOp>(loc);
});
rewriter.replaceOp(op, ppOp);
return success();
Expand Down Expand Up @@ -408,8 +407,6 @@ mlir::LogicalResult MSGateToPulse(CustomOp op, mlir::PatternRewriter &rewriter,
rewriter.getI64VectorAttr(beam.polarization),
rewriter.getI64VectorAttr(flipSign(beam.wavevector)));
builder.create<ion::PulseOp>(loc, time, qubit1, beam6Attr, phase0Attr);

builder.create<ion::YieldOp>(loc);
});
rewriter.replaceOp(op, ppOp);
return success();
Expand Down
10 changes: 5 additions & 5 deletions mlir/lib/Ion/Transforms/quantum_to_ion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,18 @@ struct QuantumToIonPass : impl::QuantumToIonPassBase<QuantumToIonPass> {
LevelAttr getLevelAttr(MLIRContext *ctx, IRRewriter &builder, Level level)
{
return LevelAttr::get(
ctx, builder.getI64IntegerAttr(level.principal), builder.getF64FloatAttr(level.spin),
builder.getF64FloatAttr(level.orbital), builder.getF64FloatAttr(level.nuclear),
builder.getF64FloatAttr(level.spin_orbital),
ctx, builder.getStringAttr(level.label), builder.getI64IntegerAttr(level.principal),
builder.getF64FloatAttr(level.spin), builder.getF64FloatAttr(level.orbital),
builder.getF64FloatAttr(level.nuclear), builder.getF64FloatAttr(level.spin_orbital),
builder.getF64FloatAttr(level.spin_orbital_nuclear),
builder.getF64FloatAttr(level.spin_orbital_nuclear_magnetization),
builder.getF64FloatAttr(level.energy));
}

TransitionAttr getTransitionAttr(MLIRContext *ctx, IRRewriter &builder, Transition transition)
{
return TransitionAttr::get(ctx, getLevelAttr(ctx, builder, transition.level_0),
getLevelAttr(ctx, builder, transition.level_1),
return TransitionAttr::get(ctx, builder.getStringAttr(transition.level_0),
builder.getStringAttr(transition.level_1),
builder.getF64FloatAttr(transition.einstein_a));
}

Expand Down
46 changes: 6 additions & 40 deletions mlir/test/Ion/Dialect.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ func.func @example_ion() -> !ion.ion {
position=dense<[0, 1]>: tensor<2xi64>,
levels=[
#ion.level<
label="downstate",
principal=1,
spin=1.1,
orbital=2.2,
Expand All @@ -167,6 +168,7 @@ func.func @example_ion() -> !ion.ion {
energy=8.8
>,
#ion.level<
label="upstate",
principal=1,
spin=1.1,
orbital=2.2,
Expand All @@ -179,49 +181,13 @@ func.func @example_ion() -> !ion.ion {
],
transitions=[
#ion.transition<
level_0 = #ion.level<
principal=1,
spin=1.1,
orbital=2.2,
nuclear=3.3,
spin_orbital=4.4,
spin_orbital_nuclear=5.5,
spin_orbital_nuclear_magnetization=6.6,
energy=8.8
>,
level_1 = #ion.level<
principal=1,
spin=1.1,
orbital=2.2,
nuclear=3.3,
spin_orbital=4.4,
spin_orbital_nuclear=5.5,
spin_orbital_nuclear_magnetization=6.6,
energy=8.8
>,
level_0 = "downstate",
level_1 = "upstate",
einstein_a=10.10
>,
#ion.transition<
level_0 = #ion.level<
principal=1,
spin=1.1,
orbital=2.2,
nuclear=3.3,
spin_orbital=4.4,
spin_orbital_nuclear=5.5,
spin_orbital_nuclear_magnetization=6.6,
energy=8.8
>,
level_1 = #ion.level<
principal=1,
spin=1.1,
orbital=2.2,
nuclear=3.3,
spin_orbital=4.4,
spin_orbital_nuclear=5.5,
spin_orbital_nuclear_magnetization=6.6,
energy=8.8
>,
level_0 = "upstate",
level_1 = "downstate",
einstein_a=10.10
>
]
Expand Down
Loading

0 comments on commit c4dfcfb

Please sign in to comment.