簡體   English   中英

將 boost odeint 與 std::map 和自定義向量空間代數一起使用時,沒有可行的重載“=”

[英]No viable overloaded '=' when using boost odeint with std::map and a custom vector space algebra

我正在嘗試使用 std::maps 並利用 boost 的 odeint 來解決 ODE 系統。 默認情況下不支持 std::map,因此我按照boost 文檔中的相關步驟來定義自定義向量空間代數。

在編譯時,我收到以下錯誤:

In file included from /usr/local/include/boost/numeric/odeint.hpp:32:
In file included from /usr/local/include/boost/numeric/odeint/stepper/runge_kutta_dopri5.hpp:25:
In file included from /usr/local/include/boost/numeric/odeint/stepper/base/explicit_error_stepper_fsal_base.hpp:31:
/usr/local/include/boost/numeric/odeint/util/copy.hpp:43:12: error: no viable overloaded '='
        to = from;

...

note: candidate function not viable: 'this' argument has type 'const DeterministicStateType', but method is not marked const
DeterministicStateType& operator=(const DeterministicStateType& a)

我不是 C++ 專家,但這似乎意味着 = 方法需要是 const,這對我來說沒有意義。

MWE:

#include <iostream>
#include <map>
#include <boost/numeric/odeint.hpp>
#include <boost/operators.hpp>

namespace pl = std::placeholders;

class DeterministicStateType :
    boost::additive1< DeterministicStateType ,
    boost::additive2< DeterministicStateType , double ,
    boost::multiplicative2< DeterministicStateType , double > > >
{
public:
    DeterministicStateType(std::map<std::string, double> map) : mMap(map)
    {}

    DeterministicStateType() {}

    DeterministicStateType(const DeterministicStateType &p)
    {
        DeterministicStateType(p.mMap);
    }

    std::map<std::string, double> mMap;

    DeterministicStateType& operator+=(const DeterministicStateType &p)
    {
        for (std::map<std::string, double>::const_iterator it = p.mMap.begin(); it != p.mMap.end(); it++)
        {
            mMap[it->first] = mMap[it->first] + it->second;
        }

        return *this;
    }

    DeterministicStateType& operator+=(double a)
    {
        for (std::map<std::string, double>::const_iterator it = mMap.begin(); it != mMap.end(); it++)
        {
            mMap[it->first] += a;
        }

        return *this;
    }

    DeterministicStateType& operator*=(const double a)
    {
        for (std::map<std::string, double>::const_iterator it = mMap.begin(); it != mMap.end(); it++)
        {
            mMap[it->first] *= it->second;
        }

        return *this;
    }

    DeterministicStateType& operator=(const DeterministicStateType& a)
    {
        mMap.clear();
        std::map<std::string, double> map2 = a.mMap;
        for (std::map<std::string, double>::iterator it = map2.begin() ; it != map2.end(); it++)
        {
            mMap[it->first] = it->second;
        }

        return *this;
    }        
};

DeterministicStateType operator/( const DeterministicStateType &p1 , const DeterministicStateType &p2 )
{
    std::map<std::string, double> map;
    std::map<std::string, double> p2map = p2.mMap;
    for (std::map<std::string, double>::const_iterator it = p1.mMap.begin() ; it != p1.mMap.end() ; it++)
    {
        map[it->first] = it->second / p2map[it->first];
    }
    return DeterministicStateType(map);
}

DeterministicStateType abs( const DeterministicStateType &p )
{
    std::map<std::string, double> map;
    for (std::map<std::string, double>::const_iterator it = p.mMap.begin() ; it != p.mMap.end() ; it++)
    {
        map[it->first] = std::abs(it->second);
    }
    return DeterministicStateType(map);
}

namespace boost { namespace numeric { namespace odeint {
    template<>
    struct vector_space_norm_inf< DeterministicStateType >
    {
        typedef double result_type;
        double operator()( const DeterministicStateType &p ) const
        {
            using std::abs;
            double max = 0;
            for (std::map<std::string, double>::const_iterator it = p.mMap.begin(); it != p.mMap.end(); it++)
            {
                if (abs(it->second) > max)
                {
                    max = abs(it->second);
                }
            }
            return max;
        }
    };
}}}

namespace boost { namespace numeric { namespace odeint {

    template< >
    struct is_resizeable<DeterministicStateType>
    {
        typedef boost::true_type type;
        const static bool value = type::value;
    };

    template< >
    struct same_size_impl<DeterministicStateType, DeterministicStateType>
    {
        static bool same_size(const DeterministicStateType &v1, const DeterministicStateType &v2)
        {
            return v1.mMap.size() == v2.mMap.size();
        }
    };

    template< >
    struct resize_impl<DeterministicStateType, DeterministicStateType>
    {
        static void resize(DeterministicStateType &v1, const DeterministicStateType &v2)
        {
            for (std::map<std::string, double>::const_iterator it = v2.mMap.begin() ; it != v2.mMap.end() ; it++)
            {
                if (v1.mMap.count(it->first) == 0)
                {
                    v1.mMap[it->first] = 0;
                }
            }
        }
    };
}}}

void derivative(const DeterministicStateType p, DeterministicStateType &dpdt, const double t) {}

using namespace boost::numeric::odeint;
int main(int argc, char *argv[])
{
    std::map<std::string, double> x0; x0["A"]=1.0; x0["B"]=1.0;
    typedef runge_kutta_dopri5<DeterministicStateType, double, DeterministicStateType, double, vector_space_algebra> stepper_type;
    integrate_adaptive( make_dense_output(1e-6, 1e-6, stepper_type()) ,
        derivative, DeterministicStateType(x0), 0.0, 300.0, 0.00001);
}

您復制賦值運算符將 rhs 作為非常量

 
 
  
  DeterministicStateType &operator=(DeterministicStateType &a) {
 
 

當調用代碼中的源為 const 時,這既不是必需的,也不會編譯。 只需通過添加 const 來修復它:

 
 
 
  
  DeterministicStateType &operator=(DeterministicStateType const& a) {
 
 

更好的是,簡化所有這些函數(我認為乘法完全錯誤,它甚至沒有使用它的參數):

State &operator=(State const&a) = default;

更好的是,假設您在編譯器上啟用了 C++11:

 State &operator=(State const&a) = default;

等等為什么我的錯誤信息還在這里?

那是因為現在你仍然傳遞一個臨時的integrate_adaptive 臨時變量只綁定到const& ,從不綁定到& ²。 因此,只需在調用之前創建您的DeterministicStateType ,並通過引用傳遞它,而不是臨時的DeterministicStateType(x0)

 int main() { DeterministicStateType x0 { { {"A", 1.0}, {"B", 1.0} } }; typedef runge_kutta_dopri5<DeterministicStateType, double, DeterministicStateType, double, vector_space_algebra> stepper_type; integrate_adaptive(make_dense_output(1e-6, 1e-6, stepper_type()), derivative, x0, 0.0, 300.0, 0.00001); }

簡化代碼

在這個簡化版本中,我使用了命名空間,將mMap私有並使用了 C++11 特性來使所有內容都不太容易出錯:

現場直播

#include <boost/numeric/odeint.hpp> #include <boost/operators.hpp> #include <iostream> #include <map> namespace Deterministic { class State : boost::additive1<State, boost::additive2<State, double, boost::multiplicative2<State, double> > > { public: using Map = std::map<std::string, double>; State(Map const& map) : mMap(map) {} State() = default; State(const State &p) = default; State &operator=(State const&a) = default; State &operator+=(const State &p) { for (auto& p : p.mMap) mMap[p.first] += p.second; return *this; } State &operator+=(double a) { for (auto& p : mMap) p.second += a; return *this; } State &operator*=(double f) { for (auto& p : mMap) mMap[p.first] *= f; return *this; } friend State abs(const State &p) { using std::abs; auto map = p.mMap; for(auto& e : map) e.second = abs(e.second); return map; } friend State operator/(const State &p1, const State &p2) { auto map = p1.mMap; for(auto& e : map) e.second /= p2.mMap.at(e.first); return map; } friend double vector_space_norm_inf_impl(State const& p) { double max = 0; using std::abs; for (auto& el : p.mMap) max = std::max(abs(el.second), max); return max; } size_t size() const { return mMap.size(); } void resize(State const& other) { for (auto& el : other.mMap) mMap[el.first] += 0; // inserts if non-existent } private: Map mMap; }; } using DeterministicStateType = Deterministic::State; namespace boost { namespace numeric { namespace odeint { template <> struct vector_space_norm_inf<DeterministicStateType> { typedef double result_type; double operator()(const DeterministicStateType &p) const { return vector_space_norm_inf_impl(p); } }; template <> struct is_resizeable<DeterministicStateType> { typedef boost::true_type type; const static bool value = type::value; }; template <> struct same_size_impl<DeterministicStateType, DeterministicStateType> { static bool same_size(const DeterministicStateType &v1, const DeterministicStateType &v2) { return v1.size() == v2.size(); } }; template <> struct resize_impl<DeterministicStateType, DeterministicStateType> { static void resize(DeterministicStateType &v1, const DeterministicStateType &v2) { v1.resize(v2); } }; } } } void derivative(const DeterministicStateType, DeterministicStateType &, const double) {} using namespace boost::numeric::odeint; int main() { DeterministicStateType x0 { { {"A", 1.0}, {"B", 1.0} } }; typedef runge_kutta_dopri5<DeterministicStateType, double, DeterministicStateType, double, vector_space_algebra> stepper_type; integrate_adaptive(make_dense_output(1e-6, 1e-6, stepper_type()), derivative, x0, 0.0, 300.0, 0.00001); }

² 損壞的編譯器除外

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM