Hi all,
I am currently implementing a restraint in C++ with the goal of providing similar functionality as the fuzzyRestraint in pmi/restraints/proteomics with better efficiency.
I have come up with the following design (see code excerpts bellow):
A pure virtual base FuzzyRestraint class that implements the interface. Several child classes that inherit from that and perform the fuzzy logic calculation (ie OR, AND, NOT).
For example, given two restraints r1,r2, I could instantiate a FuzzyOr r3=r1|r2;
My issue is the following: whenever I chain more that two operands (for example r=r1|r2|r3|r4), I get a segfault in the do_get_inputs. I believe this is due to the class containing pointers, but I didn't specify a copy constructor, assignment operator, and destructor to handle these operations without corrupting my memory/loosing information.
I know if I was writing standard c++ that's what i'd have to do, but I admit that I am a bit lost when it comes to IMP due to the entanglement with python and automatic memory management.
So my question is: 1/ Do you agree that my issue comes from that shallow copy ? 2/ Is there a functionality in IMP to handle such a case ?
Thanks, sam hanot
class IMPPMIEXPORT FuzzyRestraint; class IMPPMIEXPORT FuzzyOr; class IMPPMIEXPORT FuzzyRestraint : public Restraint { public: FuzzyRestraint(Model *m, std::string name) : Restraint(m, name) {} virtual double unprotected_evaluate(DerivativeAccumulator *) const = 0; virtual ModelObjectsTemp do_get_inputs() const = 0; FuzzyOr *operator|(FuzzyRestraint *r); IMP_OBJECT_METHODS(FuzzyRestraint); };
class IMPPMIEXPORT FuzzyOr : public FuzzyRestraint { FuzzyRestraint *r1_; FuzzyRestraint *r2_;
public: FuzzyOr(Model *m, FuzzyRestraint *r1, FuzzyRestraint *r2) : FuzzyRestraint(m, "FuzzyOr %1%"), r1_(r1), r2_(r2) { std::cerr << "Creating FuzzyOr from " << r1_->get_name() << " (" << r1_ << ") " << r2_->get_name() << " (" << r2_ << ") " << ": " << get_name() << '\n'; } virtual double unprotected_evaluate(DerivativeAccumulator *) const IMP_OVERRIDE { Model *m(get_model()); double const a(r1_->unprotected_evaluate(nullptr)); double const b(r2_->unprotected_evaluate(nullptr)); return exp(-a) + exp(-b) - exp(-a - b); } virtual ModelObjectsTemp do_get_inputs() const IMP_OVERRIDE { ModelObjectsTemp ret(r1_->get_inputs()); ModelObjectsTemp const tmp(r2_->get_inputs()); ret.insert(ret.end(), tmp.begin(), tmp.end()); return ret; } IMP_OBJECT_METHODS(FuzzyOr); };
FuzzyOr *FuzzyRestraint::operator|(FuzzyRestraint *r) { IMP_NEW(IMP::pmi::FuzzyOr, ret, (get_model(), this, r)); return ret.release(); }