Program Listing for File circuit_optimizer.hpp

Return to documentation for file (/home/docs/checkouts/readthedocs.org/user_builds/qulacs-rtd/checkouts/latest/src/cppsim/circuit_optimizer.hpp)

#pragma once

#include <unordered_set>

#include "csim/MPIutil.hpp"
#include "exception.hpp"
#include "type.hpp"

class QuantumCircuit;
class QuantumGateBase;
class QuantumGateMatrix;
class QubitTable;

class DllExport QuantumCircuitOptimizer {
private:
    QuantumCircuit* circuit;
    UINT local_qc;
    UINT global_qc;
    UINT mpisize;
    UINT mpirank;
    bool log_enabled;
    UINT get_rightmost_commute_index(UINT gate_index);
    UINT get_leftmost_commute_index(UINT gate_index);
    UINT get_merged_gate_size(UINT gate_index1, UINT gate_index2);
    bool is_neighboring(UINT gate_index1, UINT gate_index2);

    // for swap insertion
    void set_qubit_count(void);
    bool can_merge_with_swap_insertion(
        UINT gate_idx1, UINT gate_idx2, UINT swap_level);
    bool needs_communication(const UINT gate_index, const QubitTable& qt);
    UINT move_gates_without_communication(const UINT gate_idx,
        const QubitTable& qt,
        const std::multimap<const QuantumGateBase*, const QuantumGateBase*>&
            dep_map,
        std::unordered_set<const QuantumGateBase*>& processed_gates);
    std::unordered_set<UINT> find_next_local_qubits(const UINT start_gate_idx);
    UINT move_matching_qubits_to_local_upper(UINT lowest_idx, QubitTable& qt,
        std::function<bool(UINT)> fn, UINT gate_insertion_pos);
    UINT rearrange_qubits(const UINT gate_idx,
        const std::unordered_set<UINT>& next_local_qubits, QubitTable& qt);
    void revert_qubit_order(QubitTable& qt);
    void insert_swap_gates(const UINT level);

public:
    QuantumCircuitOptimizer(UINT mpi_size = 0) {
#ifdef _USE_MPI
        MPIutil& mpiutil = MPIutil::get_inst();
        if (mpi_size == 0) {
            mpisize = mpiutil.get_size();
        } else {
            mpisize = mpi_size;
        }
        mpirank = mpiutil.get_rank();
#else
        if (mpi_size == 0) {
            mpisize = 1;
        } else {
            mpisize = mpi_size;
        }
        mpirank = 0;
#endif
        if ((mpisize & (mpisize - 1))) {
            throw MPISizeException(
                "Error: "
                "QuantumCircuitOptimizer::QuantumCircuitOptimizer(UINT): "
                "mpi_size must be power of 2");
        }

        log_enabled = false;
        if (const char* tmp = std::getenv("QULACS_OPTIMIZER_LOG")) {
            const UINT tmp_val = strtol(tmp, nullptr, 0);
            log_enabled = (tmp_val > 0);
        }
        // enable logging only on rank 0
        log_enabled = log_enabled && mpirank == 0;
    };

    virtual ~QuantumCircuitOptimizer(){};

    void optimize(
        QuantumCircuit* circuit, UINT max_block_size = 2, UINT swap_level = 0);

    void optimize_light(QuantumCircuit* circuit, UINT swap_level = 0);

    QuantumGateMatrix* merge_all(const QuantumCircuit* circuit);
};