<commit_before>#include "CUDADenseGraphBFSolver.h"
#include "CUDAFormulas.h"
#include "Device.h"
#include <cmath>
#include <float.h>
#include <algorithm>
#include <limits>


using namespace sqaod_cuda;
namespace sq = sqaod;

template<class real>
CUDADenseGraphBFSolver<real>::CUDADenseGraphBFSolver() {
    tileSize_ = 16384; /* FIXME: give a correct size */
}

template<class real>
CUDADenseGraphBFSolver<real>::CUDADenseGraphBFSolver(Device &device) {
    tileSize_ = 16384; /* FIXME: give a correct size */
    assignDevice(device);
}

template<class real>
CUDADenseGraphBFSolver<real>::~CUDADenseGraphBFSolver() {
}

template<class real>
void CUDADenseGraphBFSolver<real>::assignDevice(Device &device) {
    batchSearch_.assignDevice(device);
    devCopy_.assignDevice(device);
}

template<class real>
void CUDADenseGraphBFSolver<real>::getProblemSize(sqaod::SizeType *N) const {
    *N = N_;
}

template<class real>
void CUDADenseGraphBFSolver<real>::setProblem(const Matrix &W, sq::OptimizeMethod om) {
    throwErrorIf(!isSymmetric(W), "W is not symmetric.");
    N_ = W.rows;
    W_ = W;
    om_ = om;
    if (om_ == sq::optMaximize)
        W_ *= real(-1.);
}

template<class real>
void CUDADenseGraphBFSolver<real>::setTileSize(sqaod::SizeType tileSize) {
    tileSize_ = tileSize;
}

template<class real>
const sq::BitsArray &CUDADenseGraphBFSolver<real>::get_x() const {
    return xList_;
}

template<class real>
const sq::VectorType<real> &CUDADenseGraphBFSolver<real>::get_E() const {
    return E_;
}

template<class real>
void CUDADenseGraphBFSolver<real>::initSearch() {
    batchSearch_.setProblem(W_, tileSize_);
    HostObjectAllocator().allocate(&h_packedXmin_, tileSize_);

    Emin_ = std::numeric_limits<real>::max();
    xList_.clear();
    xMax_ = 1ull << N_;
}


template<class real>
void CUDADenseGraphBFSolver<real>::finSearch() {
    batchSearch_.synchronize();
    const DevicePackedBitsArray &dPackedXmin = batchSearch_.get_xMins();
    sqaod::SizeType nXMin = std::min(tileSize_, dPackedXmin.size);
    devCopy_(&h_packedXmin_, dPackedXmin);
    devCopy_.synchronize();
    
    xList_.clear();
    E_.resize(nXMin);
    if (om_ == sq::optMaximize)
        E_ *= real(-1.);
    for (sqaod::IdxType idx = 0; idx < (sqaod::IdxType)nXMin; ++idx) {
        sq::Bits bits;
        unpackBits(&bits, h_packedXmin_[idx], N_);
        xList_.pushBack(bits); // FIXME: apply move
    }
}

template<class real>
void CUDADenseGraphBFSolver<real>::searchRange(sq::PackedBits xBegin, sq::PackedBits xEnd) {
    /* FIXME: Use multiple searchers, multi GPU */
    throwErrorIf(xBegin > xEnd, "xBegin should be larger than xEnd");
    xBegin = std::min(std::max(0ULL, xBegin), xMax_);
    xEnd = std::min(std::max(0ULL, xEnd), xMax_);
    if (xBegin == xEnd)
        return; /* Nothing to do */

    batchSearch_.calculate_E(xBegin, xEnd);
    batchSearch_.synchronize();

    real newEmin = batchSearch_.get_Emin();
    if (newEmin < Emin_) {
        batchSearch_.partition_xMins(false);
        Emin_ = newEmin;
    }
    else if (newEmin == Emin_) {
        batchSearch_.partition_xMins(true);
    }
}


template<class real>
void CUDADenseGraphBFSolver<real>::search() {
    initSearch();
    int iStep = (int)std::min((unsigned long long)tileSize_, xMax_);
    for (sq::PackedBits iTile = 0; iTile < xMax_; iTile += iStep) {
        searchRange(iTile, iTile + iStep);
    }
    finSearch();
}

template class sqaod_cuda::CUDADenseGraphBFSolver<float>;
template class sqaod_cuda::CUDADenseGraphBFSolver<double>;
<commit_msg>Fix: Emin_ is not copied to E_.<commit_after>#include "CUDADenseGraphBFSolver.h"
#include "CUDAFormulas.h"
#include "Device.h"
#include <cmath>
#include <float.h>
#include <algorithm>
#include <limits>


using namespace sqaod_cuda;
namespace sq = sqaod;

template<class real>
CUDADenseGraphBFSolver<real>::CUDADenseGraphBFSolver() {
    tileSize_ = 16384; /* FIXME: give a correct size */
}

template<class real>
CUDADenseGraphBFSolver<real>::CUDADenseGraphBFSolver(Device &device) {
    tileSize_ = 16384; /* FIXME: give a correct size */
    assignDevice(device);
}

template<class real>
CUDADenseGraphBFSolver<real>::~CUDADenseGraphBFSolver() {
}

template<class real>
void CUDADenseGraphBFSolver<real>::assignDevice(Device &device) {
    batchSearch_.assignDevice(device);
    devCopy_.assignDevice(device);
}

template<class real>
void CUDADenseGraphBFSolver<real>::getProblemSize(sqaod::SizeType *N) const {
    *N = N_;
}

template<class real>
void CUDADenseGraphBFSolver<real>::setProblem(const Matrix &W, sq::OptimizeMethod om) {
    throwErrorIf(!isSymmetric(W), "W is not symmetric.");
    N_ = W.rows;
    W_ = W;
    om_ = om;
    if (om_ == sq::optMaximize)
        W_ *= real(-1.);
}

template<class real>
void CUDADenseGraphBFSolver<real>::setTileSize(sqaod::SizeType tileSize) {
    tileSize_ = tileSize;
}

template<class real>
const sq::BitsArray &CUDADenseGraphBFSolver<real>::get_x() const {
    return xList_;
}

template<class real>
const sq::VectorType<real> &CUDADenseGraphBFSolver<real>::get_E() const {
    return E_;
}

template<class real>
void CUDADenseGraphBFSolver<real>::initSearch() {
    batchSearch_.setProblem(W_, tileSize_);
    HostObjectAllocator().allocate(&h_packedXmin_, tileSize_);

    Emin_ = std::numeric_limits<real>::max();
    xList_.clear();
    xMax_ = 1ull << N_;
}


template<class real>
void CUDADenseGraphBFSolver<real>::finSearch() {
    batchSearch_.synchronize();
    const DevicePackedBitsArray &dPackedXmin = batchSearch_.get_xMins();
    sqaod::SizeType nXMin = std::min(tileSize_, dPackedXmin.size);
    devCopy_(&h_packedXmin_, dPackedXmin);
    devCopy_.synchronize();
    
    xList_.clear();
    E_.resize(nXMin);
    E_ = Emin_;
    if (om_ == sq::optMaximize)
        E_ *= real(-1.);
    for (sqaod::IdxType idx = 0; idx < (sqaod::IdxType)nXMin; ++idx) {
        sq::Bits bits;
        unpackBits(&bits, h_packedXmin_[idx], N_);
        xList_.pushBack(bits); // FIXME: apply move
    }
}

template<class real>
void CUDADenseGraphBFSolver<real>::searchRange(sq::PackedBits xBegin, sq::PackedBits xEnd) {
    /* FIXME: Use multiple searchers, multi GPU */
    throwErrorIf(xBegin > xEnd, "xBegin should be larger than xEnd");
    xBegin = std::min(std::max(0ULL, xBegin), xMax_);
    xEnd = std::min(std::max(0ULL, xEnd), xMax_);
    if (xBegin == xEnd)
        return; /* Nothing to do */

    batchSearch_.calculate_E(xBegin, xEnd);
    batchSearch_.synchronize();

    real newEmin = batchSearch_.get_Emin();
    if (newEmin < Emin_) {
        batchSearch_.partition_xMins(false);
        Emin_ = newEmin;
    }
    else if (newEmin == Emin_) {
        batchSearch_.partition_xMins(true);
    }
}


template<class real>
void CUDADenseGraphBFSolver<real>::search() {
    initSearch();
    int iStep = (int)std::min((unsigned long long)tileSize_, xMax_);
    for (sq::PackedBits iTile = 0; iTile < xMax_; iTile += iStep) {
        searchRange(iTile, iTile + iStep);
    }
    finSearch();
}

template class sqaod_cuda::CUDADenseGraphBFSolver<float>;
template class sqaod_cuda::CUDADenseGraphBFSolver<double>;

{'fraction_non_alphanumeric': 0.13756316676024705, 'fraction_numerical': 0.004772599663110612, 'mean_word_length': 4.468150422102839, 'pattern_counts': {'":': 0, '<': 81, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3211747', 'n_tokens_mistral': 2589, 'n_tokens_neox': 2546, 'n_words': 492}