1717
1818#include " HybridNeutralAtomMapper.hpp"
1919#include " NeutralAtomArchitecture.hpp"
20- #include " NeutralAtomUtils .hpp"
20+ #include " hybridmap/Mapping .hpp"
2121#include " hybridmap/NeutralAtomDefinitions.hpp"
22+ #include " hybridmap/NeutralAtomScheduler.hpp"
2223#include " ir/Definitions.hpp"
2324#include " ir/QuantumComputation.hpp"
2425
25- #include < cstddef >
26+ #include < cstdint >
2627#include < fstream>
2728#include < sstream>
2829#include < stdexcept>
@@ -44,103 +45,187 @@ class HybridSynthesisMapper : public NeutralAtomMapper {
4445 using qcs = std::vector<qc::QuantumComputation>;
4546
4647 qc::QuantumComputation synthesizedQc;
48+ qc::QuantumComputation bufferedQc;
49+ uint32_t bufferSize;
50+ Mapping originalMapping;
4751 bool initialized = false ;
4852
4953 /* *
5054 * @brief Evaluate a single proposed synthesis step.
5155 * @details Effort considers swaps/shuttling and execution time estimated by
5256 * the mapper.
5357 * @param qc Proposed synthesis subcircuit.
58+ * @param completeRemap If `true`, evaluate by completely remapping the whole
59+ * circuit; if `false`, preserve the current mapping state.
5460 * @return Scalar cost/effort score for mapping qc.
5561 */
56- qc::fp evaluateSynthesisStep (qc::QuantumComputation& qc) const ;
62+ qc::fp evaluateSynthesisStep (qc::QuantumComputation& qc,
63+ bool completeRemap = false ) const ;
5764
5865public:
5966 // Constructors
6067 HybridSynthesisMapper () = delete ;
6168 /* *
62- * @brief Construct with device and optional mapper parameters.
63- * @param arch Neutral atom architecture.
64- * @param params Optional mapper configuration parameters.
69+ * @brief Create a HybridSynthesisMapper configured for a neutral-atom device.
70+ *
71+ * @param arch Neutral-atom device architecture used for mapping and
72+ * scheduling.
73+ * @param params Optional mapper configuration parameters; defaults to
74+ * MapperParameters().
75+ * @param bufferSize Number of operations to hold in the internal buffer
76+ * before flushing to the synthesized circuit (0 disables buffering).
6577 */
6678 explicit HybridSynthesisMapper (
6779 const NeutralAtomArchitecture& arch,
68- const MapperParameters& params = MapperParameters())
69- : NeutralAtomMapper(arch, params) {}
80+ const MapperParameters& params = MapperParameters(),
81+ const uint32_t bufferSize = 0)
82+ : NeutralAtomMapper(arch, params), bufferSize(bufferSize) {}
7083
7184 // Functions
7285
7386 /* *
74- * @brief Initialize synthesized and mapped circuits and mapping structures.
75- * @param nQubits Number of logical qubits to synthesize.
87+ * @brief Initialize internal circuits and mapping state for a given number of
88+ * logical qubits.
89+ *
90+ * Sets up the synthesized and buffered quantum computations, the mapped
91+ * circuit storage, the logical-to-physical mapping, and records the original
92+ * mapping; marks the mapper as initialized.
93+ *
94+ * @param nQubits Number of logical qubits to prepare.
95+ * @throws std::runtime_error if `nQubits` exceeds the architecture's
96+ * available positions.
7697 */
7798 void initMapping (const size_t nQubits) {
7899 if (nQubits > arch->getNpositions ()) {
79100 throw std::runtime_error (" Not enough qubits in architecture." );
80101 }
81102 mappedQc = qc::QuantumComputation (arch->getNpositions ());
82103 synthesizedQc = qc::QuantumComputation (nQubits);
104+ bufferedQc = qc::QuantumComputation (nQubits);
83105 mapping = Mapping (nQubits);
84106 initialized = true ;
107+ originalMapping = mapping;
85108 }
86109
87110 /* *
88- * @brief Complete a (re-)mapping of the synthesized circuit to hardware.
89- * @param initMapping Initial mapping heuristic (defaults to Identity).
111+ * @brief Remap the synthesized circuit onto the stored original hardware
112+ * mapping.
113+ *
114+ * If `includeBuffer` is true, the remap uses the combined
115+ * synthesized-plus-buffered circuit returned by getSynthesizedQc(); otherwise
116+ * it remaps only the internal synthesizedQc (excluding buffered operations).
117+ * The result is mapped into originalMapping.
118+ *
119+ * @param includeBuffer When true, include buffered operations in the remap.
90120 */
91- void completeRemap (const InitialMapping initMapping = Identity) {
92- auto qcCopy = synthesizedQc;
93- map (qcCopy, initMapping);
121+ void completeRemap (const bool includeBuffer = true ) {
122+ if (includeBuffer) {
123+ auto copyQC = getSynthesizedQc ();
124+ map (copyQC, originalMapping);
125+ } else {
126+ auto temp = synthesizedQc;
127+ map (temp, originalMapping);
128+ }
129+ }
130+
131+ /* *
132+ * @brief Appends buffered operations into the synthesized circuit, maps them,
133+ * and schedules the mapped circuit.
134+ *
135+ * Appends all operations currently held in the internal buffer to the
136+ * synthesized circuit, applies mapping for those appended operations, clears
137+ * the buffer, and then performs the scheduling pass using the base mapper.
138+ *
139+ * @param verboseArg Enable verbose scheduling output when true.
140+ * @param createAnimationCsv Emit scheduling animation CSV when true.
141+ * @param shuttlingSpeedFactor Factor to scale shuttling durations during
142+ * scheduling (1.0 = nominal speed).
143+ * @return SchedulerResults Results produced by the scheduling pass (timing
144+ * and placement outcomes).
145+ */
146+ [[nodiscard]] SchedulerResults
147+ schedule (const bool verboseArg = false , const bool createAnimationCsv = false ,
148+ const qc::fp shuttlingSpeedFactor = 1.0 ) {
149+ for (const auto & op : bufferedQc) {
150+ synthesizedQc.emplace_back (op->clone ());
151+ }
152+ mapAppend (bufferedQc, this ->mapping );
153+ bufferedQc.clear ();
154+ return NeutralAtomMapper::schedule (verboseArg, createAnimationCsv,
155+ shuttlingSpeedFactor);
94156 }
95157
96158 /* *
97- * @brief Get the currently synthesized (unmapped) circuit.
98- * @return Synthesized QuantumComputation.
159+ * @brief Return a combined view of the synthesized and buffered (unmapped)
160+ * circuit.
161+ *
162+ * The returned QuantumComputation contains all operations from the mapper's
163+ * synthesized circuit followed by any buffered operations, using the mapper's
164+ * current qubit count.
165+ *
166+ * @return qc::QuantumComputation A new QuantumComputation with synthesized
167+ * operations then buffered operations.
99168 */
100169 [[nodiscard]] qc::QuantumComputation getSynthesizedQc () const {
101- return synthesizedQc;
170+ qc::QuantumComputation qc (synthesizedQc.getNqubits ());
171+ qc.reserve (synthesizedQc.size () + bufferedQc.size ());
172+ for (const auto & op : synthesizedQc) {
173+ qc.emplace_back (op->clone ());
174+ }
175+ for (const auto & op : bufferedQc) {
176+ qc.emplace_back (op->clone ());
177+ }
178+ return qc;
102179 }
103180
104181 /* *
105- * @brief Export synthesized circuit as OpenQASM string.
106- * @return QASM representation of the synthesized circuit.
182+ * @brief Produce the OpenQASM representation of the synthesized circuit.
183+ *
184+ * Returns an OpenQASM string for the current synthesized circuit view,
185+ * including any buffered operations not yet scheduled.
186+ *
187+ * @return std::string OpenQASM text describing the synthesized (and buffered)
188+ * circuit.
107189 */
108190 [[nodiscard]] [[maybe_unused]] std::string getSynthesizedQcQASM () const {
109191 std::stringstream ss;
110- synthesizedQc.dumpOpenQASM (ss, false );
192+ const auto copyQC = getSynthesizedQc ();
193+ copyQC.dumpOpenQASM (ss, false );
111194 return ss.str ();
112195 }
113196
114197 /* *
115- * @brief Save synthesized circuit as OpenQASM to a file.
116- * @param filename Output filename.
198+ * @brief Write the current synthesized circuit (including buffered
199+ * operations) to a file in OpenQASM format.
200+ *
201+ * @param filename Path to the output file where the OpenQASM representation
202+ * will be written.
117203 */
118204 [[maybe_unused]] void saveSynthesizedQc (const std::string& filename) const {
119205 std::ofstream ofs (filename);
120- synthesizedQc.dumpOpenQASM (ofs, false );
206+ const auto copyQC = getSynthesizedQc ();
207+ copyQC.dumpOpenQASM (ofs, false );
121208 ofs.close ();
122209 }
123210
124211 /* *
125212 * @brief Evaluate candidate synthesis steps and optionally map the best.
126213 * @param synthesisSteps Vector of candidate subcircuits.
214+ * @param completeRemap If true, completely remap before evaluation.
127215 * @param alsoMap If true, append and map the best candidate.
128216 * @return List of fidelity scores for mapped steps (order matches input).
129217 */
130218 std::vector<qc::fp> evaluateSynthesisSteps (qcs& synthesisSteps,
219+ bool completeRemap = false ,
131220 bool alsoMap = false );
132221
133- /* *
134- * @brief Append gates without mapping (no SWAPs/shuttling inserted).
135- * @param qc Subcircuit to append as-is.
136- */
137- void appendWithoutMapping (const qc::QuantumComputation& qc);
138-
139222 /* *
140223 * @brief Append and map a subcircuit to hardware (may insert moves/SWAPs).
141224 * @param qc Subcircuit to append and map.
225+ * @param completeRemap If true, completely remap before appending.
142226 */
143- void appendWithMapping (qc::QuantumComputation& qc);
227+ void appendWithMapping (qc::QuantumComputation& qc,
228+ bool completeRemap = false );
144229
145230 /* *
146231 * @brief Get the current device adjacency (connectivity) matrix.
0 commit comments