diff --git a/src/algo/arg_iterator.cpp b/src/algo/arg_iterator.cpp index 4d6f990..b8f938e 100644 --- a/src/algo/arg_iterator.cpp +++ b/src/algo/arg_iterator.cpp @@ -2,45 +2,54 @@ #include "algo/arg_iterator.h" #include "data/htn_instance.h" -ArgIterator ArgIterator::getFullInstantiation(const USignature& sig, HtnInstance& _htn) { - std::vector> constantsPerArg; +ArgIterator ArgIterator::getFullInstantiation(const USignature &sig, HtnInstance &_htn) +{ + std::vector> constantsPerArg; - // "Empty" signature? - if (sig._args.empty()) { + // "Empty" signature? + if (sig._args.empty()) + { return ArgIterator(sig._name_id, std::move(constantsPerArg)); } // enumerate all arg combinations for variable args // Get all constants of the respective type(s) - std::vector sorts = _htn.getSorts(sig._name_id); + std::basic_string sorts = _htn.getSorts(sig._name_id); assert(sorts.size() == sig._args.size() || Log::e("Sorts table of predicate %s has an invalid size\n", TOSTR(sig))); - for (size_t pos = 0; pos < sorts.size(); pos++) { + for (size_t pos = 0; pos < sorts.size(); pos++) + { int arg = sig._args[pos]; - - if (arg > 0 && _htn.isVariable(arg)) { + + if (arg > 0 && _htn.isVariable(arg)) + { // free argument and no placeholder int sort = sorts[pos]; // Scan through all eligible arguments, filtering out q constants - std::vector eligibleConstants; - for (int arg : _htn.getConstantsOfSort(sort)) { - if (_htn.isQConstant(arg)) continue; + std::basic_string eligibleConstants; + for (int arg : _htn.getConstantsOfSort(sort)) + { + if (_htn.isQConstant(arg)) + continue; eligibleConstants.push_back(arg); } // Empty instantiation if there is not a single eligible constant at some pos - //log("OF_SORT %s : %i constants\n", _htn._name_back_table[sort].c_str(), eligibleConstants.size()); - if (eligibleConstants.empty()) { + // log("OF_SORT %s : %i constants\n", _htn._name_back_table[sort].c_str(), eligibleConstants.size()); + if (eligibleConstants.empty()) + { constantsPerArg.clear(); return ArgIterator(sig._name_id, std::move(constantsPerArg)); } constantsPerArg.push_back(eligibleConstants); - } else { + } + else + { // constant - constantsPerArg.push_back(std::vector(1, arg)); + constantsPerArg.push_back(std::basic_string(1, arg)); } } diff --git a/src/algo/arg_iterator.h b/src/algo/arg_iterator.h index 161ef51..2f48701 100644 --- a/src/algo/arg_iterator.h +++ b/src/algo/arg_iterator.h @@ -10,41 +10,49 @@ class HtnInstance; -class ArgIterator { +class ArgIterator +{ private: + std::vector> _eligible_args; - std::vector> _eligible_args; - - struct It { + struct It + { int _sig_id; - const std::vector>& _eligible_args; + const std::vector> &_eligible_args; std::vector _counter; size_t _counter_number; USignature _usig; - It(int sigId, const std::vector>& eligibleArgs) - : _sig_id(sigId), _eligible_args(eligibleArgs), _counter(eligibleArgs.size(), 0), - _counter_number(0), _usig(_sig_id, std::vector(_counter.size())) { - - for (size_t i = 0; i < _usig._args.size(); i++) { + It(int sigId, const std::vector> &eligibleArgs) + : _sig_id(sigId), _eligible_args(eligibleArgs), _counter(eligibleArgs.size(), 0), + _counter_number(0), _usig(_sig_id, std::basic_string(_counter.size(), 0)) + { + for (size_t i = 0; i < _usig._args.size(); i++) + { assert(i < _eligible_args.size()); assert(!_eligible_args[i].empty()); _usig._args[i] = _eligible_args[i].front(); } } - const USignature& operator*() { + const USignature &operator*() + { return _usig; } - const USignature& operator++() { - for (size_t i = 0; i < _counter.size(); i++) { - if (_counter[i]+1 == _eligible_args[i].size()) { + const USignature &operator++() + { + for (size_t i = 0; i < _counter.size(); i++) + { + if (_counter[i] + 1 == _eligible_args[i].size()) + { // reached max value of some position _counter[i] = 0; _usig._args[i] = _eligible_args[i].front(); - } else { + } + else + { // increment and done _counter[i]++; _usig._args[i] = _eligible_args[i].at(_counter[i]); @@ -55,36 +63,40 @@ class ArgIterator { return _usig; } - bool operator==(const It& other) const { + bool operator==(const It &other) const + { return _counter_number == other._counter_number; } - bool operator!=(const It& other) const { + bool operator!=(const It &other) const + { return !(*this == other); } } _begin, _end; public: + ArgIterator(int sigId, std::vector> &&eligibleArgs) : _eligible_args(std::move(eligibleArgs)), + _begin(sigId, _eligible_args), + _end(sigId, _eligible_args) + { - ArgIterator(int sigId, std::vector>&& eligibleArgs) : - _eligible_args(std::move(eligibleArgs)), - _begin(sigId, _eligible_args), - _end(sigId, _eligible_args) { - size_t numChoices = _eligible_args.empty() ? 0 : 1; - for (const auto& args : _eligible_args) numChoices *= args.size(); + for (const auto &args : _eligible_args) + numChoices *= args.size(); _end._counter_number = numChoices; } - It begin() const { + It begin() const + { return _begin; } - It end() const { + It end() const + { return _end; } - static ArgIterator getFullInstantiation(const USignature& sig, HtnInstance& _htn); + static ArgIterator getFullInstantiation(const USignature &sig, HtnInstance &_htn); }; #endif \ No newline at end of file diff --git a/src/algo/fact_analysis.cpp b/src/algo/fact_analysis.cpp index 9770f89..0b06969 100644 --- a/src/algo/fact_analysis.cpp +++ b/src/algo/fact_analysis.cpp @@ -1,231 +1,288 @@ #include "fact_analysis.h" -const SigSet& FactAnalysis::getPossibleFactChanges(const USignature& sig, FactInstantiationMode mode, OperationType opType) { - - if (opType == UNKNOWN) opType = _htn.isAction(sig) ? ACTION : REDUCTION; - - if (opType == ACTION) return _htn.getOpTable().getAction(sig).getEffects(); - if (_fact_changes_cache.count(sig)) return _fact_changes_cache[sig]; +const SigSet &FactAnalysis::getPossibleFactChanges(const USignature &sig, FactInstantiationMode mode, OperationType opType) +{ + + if (opType == UNKNOWN) + opType = _htn.isAction(sig) ? ACTION : REDUCTION; + + if (opType == ACTION) + return _htn.getOpTable().getAction(sig).getEffects(); + if (_fact_changes_cache.count(sig)) + return _fact_changes_cache[sig]; int nameId = sig._name_id; - + // Substitution mapping - std::vector placeholderArgs; + std::basic_string placeholderArgs; USignature normSig = _htn.getNormalizedLifted(sig, placeholderArgs); Substitution sFromPlaceholder(placeholderArgs, sig._args); - auto& factChanges = mode == FULL ? _fact_changes : _lifted_fact_changes; - if (!factChanges.count(nameId)) { + auto &factChanges = mode == FULL ? _fact_changes : _lifted_fact_changes; + if (!factChanges.count(nameId)) + { // Compute fact changes for origSig - + NodeHashSet facts; - if (_htn.isActionRepetition(nameId)) { + if (_htn.isActionRepetition(nameId)) + { // Special case: Action repetition Action a = _htn.getActionFromRepetition(nameId); a = a.substitute(Substitution(a.getArguments(), placeholderArgs)); - for (const Signature& eff : a.getEffects()) { + for (const Signature &eff : a.getEffects()) + { facts.insert(eff); } - } else { + } + else + { // Normal traversal to find possible fact changes - _traversal.traverse(normSig.substitute(Substitution(normSig._args, placeholderArgs)), - NetworkTraversal::TRAVERSE_PREORDER, - [&](const USignature& nodeSig, int depth) { // NOLINT - if (_htn.isAction(nodeSig)) { - - Action a; - if (_htn.isActionRepetition(nameId)) { - // Special case: Action repetition - a = _htn.toAction(_htn.getActionNameFromRepetition(nameId), nodeSig._args); - } else { - a = _htn.toAction(nodeSig._name_id, nodeSig._args); - } - for (const Signature& eff : a.getEffects()) facts.insert(eff); - - } else if (_htn.isReductionPrimitivizable(nodeSig._name_id)) { - - const Action& op = _htn.getReductionPrimitivization(nodeSig._name_id); - Action action = op.substitute(Substitution(op.getArguments(), nodeSig._args)); - for (const Signature& eff : action.getEffects()) facts.insert(eff); - } - }); + _traversal.traverse(normSig.substitute(Substitution(normSig._args, placeholderArgs)), + NetworkTraversal::TRAVERSE_PREORDER, + [&](const USignature &nodeSig, int depth) { // NOLINT + if (_htn.isAction(nodeSig)) + { + + Action a; + if (_htn.isActionRepetition(nameId)) + { + // Special case: Action repetition + a = _htn.toAction(_htn.getActionNameFromRepetition(nameId), nodeSig._args); + } + else + { + a = _htn.toAction(nodeSig._name_id, nodeSig._args); + } + for (const Signature &eff : a.getEffects()) + facts.insert(eff); + } + else if (_htn.isReductionPrimitivizable(nodeSig._name_id)) + { + + const Action &op = _htn.getReductionPrimitivization(nodeSig._name_id); + Action action = op.substitute(Substitution(op.getArguments(), nodeSig._args)); + for (const Signature &eff : action.getEffects()) + facts.insert(eff); + } + }); } // Convert result to vector - SigSet& liftedResult = _lifted_fact_changes[nameId]; - SigSet& result = _fact_changes[nameId]; - for (const Signature& sig : facts) { + SigSet &liftedResult = _lifted_fact_changes[nameId]; + SigSet &result = _fact_changes[nameId]; + for (const Signature &sig : facts) + { liftedResult.insert(sig); - if (sig._usig._args.empty()) result.insert(sig); - else for (const USignature& sigGround : ArgIterator::getFullInstantiation(sig._usig, _htn)) { - result.emplace(sigGround, sig._negated); - } + if (sig._usig._args.empty()) + result.insert(sig); + else + for (const USignature &sigGround : ArgIterator::getFullInstantiation(sig._usig, _htn)) + { + result.emplace(sigGround, sig._negated); + } } } // Get fact changes, substitute arguments _fact_changes_cache[sig] = factChanges.at(nameId); - for (Signature& s : _fact_changes_cache[sig]) { + for (Signature &s : _fact_changes_cache[sig]) + { s.apply(sFromPlaceholder); } return _fact_changes_cache[sig]; } -void FactAnalysis::eraseCachedPossibleFactChanges(const USignature& sig) { +void FactAnalysis::eraseCachedPossibleFactChanges(const USignature &sig) +{ _fact_changes_cache.erase(sig); } +std::vector> FactAnalysis::getReducedArgumentDomains(const HtnOp &op) +{ -std::vector> FactAnalysis::getReducedArgumentDomains(const HtnOp& op) { - - const std::vector& args = op.getArguments(); - const std::vector& sorts = _htn.getSorts(op.getNameId()); + const std::basic_string &args = op.getArguments(); + const std::basic_string &sorts = _htn.getSorts(op.getNameId()); std::vector> domainPerVariable(args.size()); std::vector occursInPreconditions(args.size(), false); // Check each precondition regarding its valid decodings w.r.t. current state - //const SigSet* preSets[2] = {&op.getPreconditions(), &op.getExtraPreconditions()}; - const SigSet* preSets[1] = {&op.getPreconditions()}; - for (const auto& preSet : preSets) for (const auto& preSig : *preSet) { - - // Find mapping from precond args to op args - std::vector opArgIndices(preSig._usig._args.size(), -1); - for (size_t preIdx = 0; preIdx < preSig._usig._args.size(); preIdx++) { - const int& arg = preSig._usig._args[preIdx]; - for (size_t i = 0; i < args.size(); i++) { - if (args[i] == arg) { - opArgIndices[preIdx] = i; - occursInPreconditions[i] = true; - break; + // const SigSet* preSets[2] = {&op.getPreconditions(), &op.getExtraPreconditions()}; + const SigSet *preSets[1] = {&op.getPreconditions()}; + for (const auto &preSet : preSets) + for (const auto &preSig : *preSet) + { + + // Find mapping from precond args to op args + std::vector opArgIndices(preSig._usig._args.size(), -1); + for (size_t preIdx = 0; preIdx < preSig._usig._args.size(); preIdx++) + { + const int &arg = preSig._usig._args[preIdx]; + for (size_t i = 0; i < args.size(); i++) + { + if (args[i] == arg) + { + opArgIndices[preIdx] = i; + occursInPreconditions[i] = true; + break; + } } } - } - if (!_htn.hasQConstants(preSig._usig) && _htn.isFullyGround(preSig._usig)) { - // Check base condition; if unsatisfied, discard op - if (!isReachable(preSig)) return std::vector>(); - // Add constants to respective argument domains - for (size_t i = 0; i < preSig._usig._args.size(); i++) { - domainPerVariable[opArgIndices[i]].insert(preSig._usig._args[i]); + if (!_htn.hasQConstants(preSig._usig) && _htn.isFullyGround(preSig._usig)) + { + // Check base condition; if unsatisfied, discard op + if (!isReachable(preSig)) + return std::vector>(); + // Add constants to respective argument domains + for (size_t i = 0; i < preSig._usig._args.size(); i++) + { + domainPerVariable[opArgIndices[i]].insert(preSig._usig._args[i]); + } + continue; } - continue; - } - // Compute sorts of the condition's args w.r.t. op signature - std::vector preSorts(preSig._usig._args.size()); - for (size_t i = 0; i < preSorts.size(); i++) { - preSorts[i] = sorts[opArgIndices[i]]; - } + // Compute sorts of the condition's args w.r.t. op signature + std::basic_string preSorts(preSig._usig._args.size(), 0); + for (size_t i = 0; i < preSorts.size(); i++) + { + preSorts[i] = sorts[opArgIndices[i]]; + } - // Check possible decodings of precondition - bool any = false; - bool anyValid = false; - for (const auto& decUSig : _htn.decodeObjects(preSig._usig, _htn.getEligibleArgs(preSig._usig, preSorts))) { - any = true; - assert(_htn.isFullyGround(decUSig)); - - // Valid? - if (!isReachable(decUSig, preSig._negated)) continue; - - // Valid precondition decoding found: Increase domain of concerned variables - anyValid = true; - for (size_t i = 0; i < opArgIndices.size(); i++) { - int opArgIdx = opArgIndices[i]; - if (opArgIdx >= 0) { - domainPerVariable[opArgIdx].insert(decUSig._args[i]); + // Check possible decodings of precondition + bool any = false; + bool anyValid = false; + for (const auto &decUSig : _htn.decodeObjects(preSig._usig, _htn.getEligibleArgs(preSig._usig, preSorts))) + { + any = true; + assert(_htn.isFullyGround(decUSig)); + + // Valid? + if (!isReachable(decUSig, preSig._negated)) + continue; + + // Valid precondition decoding found: Increase domain of concerned variables + anyValid = true; + for (size_t i = 0; i < opArgIndices.size(); i++) + { + int opArgIdx = opArgIndices[i]; + if (opArgIdx >= 0) + { + domainPerVariable[opArgIdx].insert(decUSig._args[i]); + } } } + if (any && !anyValid) + return std::vector>(); } - if (any && !anyValid) return std::vector>(); - } - for (size_t i = 0; i < args.size(); i++) { - if (!occursInPreconditions[i]) domainPerVariable[i] = _htn.getConstantsOfSort(sorts[i]); + for (size_t i = 0; i < args.size(); i++) + { + if (!occursInPreconditions[i]) + domainPerVariable[i] = _htn.getConstantsOfSort(sorts[i]); } return domainPerVariable; } -FactFrame FactAnalysis::getFactFrame(const USignature& sig, USigSet& currentOps) { +FactFrame FactAnalysis::getFactFrame(const USignature &sig, USigSet ¤tOps) +{ static USigSet EMPTY_USIG_SET; - //Log::d("GET_FACT_FRAME %s\n", TOSTR(sig)); + // Log::d("GET_FACT_FRAME %s\n", TOSTR(sig)); int nameId = sig._name_id; - if (!_fact_frames.count(nameId)) { + if (!_fact_frames.count(nameId)) + { FactFrame result; - std::vector newArgs(sig._args.size()); - for (size_t i = 0; i < sig._args.size(); i++) { + std::basic_string newArgs(sig._args.size(), 0); + for (size_t i = 0; i < sig._args.size(); i++) + { newArgs[i] = _htn.nameId("c" + std::to_string(i)); } USignature op(sig._name_id, std::move(newArgs)); result.sig = op; - if (_htn.isAction(op)) { + if (_htn.isAction(op)) + { // Action - const Action& a = _htn.toAction(op._name_id, op._args); + const Action &a = _htn.toAction(op._name_id, op._args); result.preconditions = a.getPreconditions(); result.effects = a.getEffects(); - - } else if (currentOps.count(op)) { + } + else if (currentOps.count(op)) + { // Handle recursive call of same reduction: Conservatively add preconditions and effects // without recursing on subtasks - const Reduction& r = _htn.toReduction(op._name_id, op._args); + const Reduction &r = _htn.toReduction(op._name_id, op._args); result.preconditions = r.getPreconditions(); result.effects = getPossibleFactChanges(r.getSignature(), LIFTED); - //Log::d("RECURSIVE_FACT_FRAME %s\n", TOSTR(result.effects)); - - } else { + // Log::d("RECURSIVE_FACT_FRAME %s\n", TOSTR(result.effects)); + } + else + { currentOps.insert(op); - - const Reduction& r = _htn.toReduction(op._name_id, op._args); + + const Reduction &r = _htn.toReduction(op._name_id, op._args); result.preconditions.insert(r.getPreconditions().begin(), r.getPreconditions().end()); - + // For each subtask position ("offset") - for (size_t offset = 0; offset < r.getSubtasks().size(); offset++) { - + for (size_t offset = 0; offset < r.getSubtasks().size(); offset++) + { + FactFrame frameOfOffset; std::vector children; _traversal.getPossibleChildren(r.getSubtasks(), offset, children); bool firstChild = true; // Assemble fact frame of this offset by iterating over all possible children at the offset - for (const auto& child : children) { + for (const auto &child : children) + { // Assemble unified argument names - std::vector newChildArgs(child._args); - for (size_t i = 0; i < child._args.size(); i++) { - if (_htn.isVariable(child._args[i])) newChildArgs[i] = _htn.nameId("??_"); + std::basic_string newChildArgs(child._args); + for (size_t i = 0; i < child._args.size(); i++) + { + if (_htn.isVariable(child._args[i])) + newChildArgs[i] = _htn.nameId("??_"); } // Recursively get child frame of the child FactFrame childFrame = getFactFrame(USignature(child._name_id, std::move(newChildArgs)), currentOps); - - if (firstChild) { + + if (firstChild) + { // Add all preconditions of child that are not yet part of the parent's effects - for (const auto& pre : childFrame.preconditions) { + for (const auto &pre : childFrame.preconditions) + { bool isNew = true; - for (const auto& eff : result.effects) { - if (_htn.isUnifiable(eff, pre) || _htn.isUnifiable(pre, eff)) { + for (const auto &eff : result.effects) + { + if (_htn.isUnifiable(eff, pre) || _htn.isUnifiable(pre, eff)) + { isNew = false; - //Log::d("FACT_FRAME Precondition %s absorbed by effect %s of %s\n", TOSTR(pre), TOSTR(eff), TOSTR(child)); + // Log::d("FACT_FRAME Precondition %s absorbed by effect %s of %s\n", TOSTR(pre), TOSTR(eff), TOSTR(child)); break; - } + } } - if (isNew) frameOfOffset.preconditions.insert(pre); + if (isNew) + frameOfOffset.preconditions.insert(pre); } firstChild = false; - } else { + } + else + { // Intersect preconditions SigSet newPrec; - for (auto& pre : childFrame.preconditions) { - if (frameOfOffset.preconditions.count(pre)) newPrec.insert(pre); + for (auto &pre : childFrame.preconditions) + { + if (frameOfOffset.preconditions.count(pre)) + newPrec.insert(pre); } frameOfOffset.preconditions = std::move(newPrec); } @@ -238,16 +295,14 @@ FactFrame FactAnalysis::getFactFrame(const USignature& sig, USigSet& currentOps) result.preconditions.insert(frameOfOffset.preconditions.begin(), frameOfOffset.preconditions.end()); result.effects.insert(frameOfOffset.effects.begin(), frameOfOffset.effects.end()); } - } currentOps.erase(sig); _fact_frames[nameId] = std::move(result); - //Log::d("FACT_FRAME %s\n", TOSTR(_fact_frames[nameId])); + // Log::d("FACT_FRAME %s\n", TOSTR(_fact_frames[nameId])); } - const FactFrame& f = _fact_frames[nameId]; + const FactFrame &f = _fact_frames[nameId]; return f.substitute(Substitution(f.sig._args, sig._args)); } - diff --git a/src/algo/instantiator.cpp b/src/algo/instantiator.cpp index ed51955..f7fe2c0 100644 --- a/src/algo/instantiator.cpp +++ b/src/algo/instantiator.cpp @@ -10,48 +10,62 @@ USigSet Instantiator::EMPTY_USIG_SET; -std::vector Instantiator::getApplicableInstantiations(const Reduction& r, int mode) { +std::vector Instantiator::getApplicableInstantiations(const Reduction &r, int mode) +{ int oldMode = _inst_mode; - if (mode >= 0) _inst_mode = mode; + if (mode >= 0) + _inst_mode = mode; auto result = instantiate(r); _inst_mode = oldMode; return result; } -std::vector Instantiator::getApplicableInstantiations(const Action& a, int mode) { +std::vector Instantiator::getApplicableInstantiations(const Action &a, int mode) +{ int oldMode = _inst_mode; - if (mode >= 0) _inst_mode = mode; + if (mode >= 0) + _inst_mode = mode; auto result = instantiate(a); _inst_mode = oldMode; return result; } -const HtnOp* __op; -struct CompArgs { - bool operator()(const int& a, const int& b) const { +const HtnOp *__op; +struct CompArgs +{ + bool operator()(const int &a, const int &b) const + { return rating(a) > rating(b); } - int rating(int arg) const { + int rating(int arg) const + { int r = 0; - for (const Signature& pre : __op->getPreconditions()) { - for (int preArg : pre._usig._args) { - if (preArg == arg) r++; - } + for (const Signature &pre : __op->getPreconditions()) + { + for (int preArg : pre._usig._args) + { + if (preArg == arg) + r++; + } } - for (const Signature& eff : __op->getEffects()) { - for (int effArg : eff._usig._args) { - if (effArg == arg) r++; - } + for (const Signature &eff : __op->getEffects()) + { + for (int effArg : eff._usig._args) + { + if (effArg == arg) + r++; + } } return r; } }; -std::vector Instantiator::instantiate(const HtnOp& op) { +std::vector Instantiator::instantiate(const HtnOp &op) +{ __op = &op; /* @@ -72,22 +86,25 @@ std::vector Instantiator::instantiate(const HtnOp& op) { int arg = op.getArguments()[i]; if (_htn.isVariable(arg) && _htn.getConstantsOfSort(sorts[i]).size() == 1) { // Argument is trivial: insert only possible constant - argIndicesByPriority.push_back(i); + argIndicesByPriority.push_back(i); } }*/ // a) Try to naively ground _one single_ instantiation // -- if this fails, there is no valid instantiation at all std::vector inst = instantiateLimited(op, argIndicesByPriority, 1, /*returnUnfinished=*/true); - if (inst.empty()) return inst; + if (inst.empty()) + return inst; // b) Try if the number of valid instantiations is below the user-defined threshold // -- in that case, return that full instantiation - if (_q_const_instantiation_limit > 0) { + if (_q_const_instantiation_limit > 0) + { std::vector inst = instantiateLimited(op, argIndicesByPriority, _q_const_instantiation_limit, /*returnUnfinished=*/false); - if (!inst.empty()) return inst; + if (!inst.empty()) + return inst; } - + return instantiateLimited(op, argIndicesByPriority, 0, false); /* @@ -104,7 +121,7 @@ std::vector Instantiator::instantiate(const HtnOp& op) { argsToInstantiate.insert(arg); } else if (_inst_mode == INSTANTIATE_PRECONDITIONS) { - + bool found = false; for (const auto& pre : op.getPreconditions()) { for (const int& preArg : pre._usig._args) { @@ -145,33 +162,35 @@ std::vector Instantiator::instantiate(const HtnOp& op) { */ } -std::vector Instantiator::instantiateLimited(const HtnOp& op, const std::vector& argIndicesByPriority, - size_t limit, bool returnUnfinished) { +std::vector Instantiator::instantiateLimited(const HtnOp &op, const std::vector &argIndicesByPriority, + size_t limit, bool returnUnfinished) +{ std::vector instantiation; size_t doneInstSize = argIndicesByPriority.size(); - //Log::d("DIS=%i\n", doneInstSize); - - if (doneInstSize == 0) { - if (_analysis.hasValidPreconditions(op.getPreconditions()) - && _analysis.hasValidPreconditions(op.getExtraPreconditions()) - && _htn.hasSomeInstantiation(op.getSignature())) + // Log::d("DIS=%i\n", doneInstSize); + + if (doneInstSize == 0) + { + if (_analysis.hasValidPreconditions(op.getPreconditions()) && _analysis.hasValidPreconditions(op.getExtraPreconditions()) && _htn.hasSomeInstantiation(op.getSignature())) instantiation.emplace_back(op.getSignature()); - //log("INST %s : %i instantiations X\n", TOSTR(op.getSignature()), instantiation.size()); + // log("INST %s : %i instantiations X\n", TOSTR(op.getSignature()), instantiation.size()); return instantiation; } std::vector> assignmentsStack; assignmentsStack.push_back(std::vector()); // begin with empty assignment - while (!assignmentsStack.empty()) { + while (!assignmentsStack.empty()) + { const std::vector assignment = assignmentsStack.back(); assignmentsStack.pop_back(); - //for (int a : assignment) log("%i ", a); log("\n"); + // for (int a : assignment) log("%i ", a); log("\n"); // Loop over possible choices for the next argument position int argPos = argIndicesByPriority[assignment.size()]; int sort = _htn.getSorts(op.getNameId()).at(argPos); - for (int c : _htn.getConstantsOfSort(sort)) { + for (int c : _htn.getConstantsOfSort(sort)) + { // Create new assignment std::vector newAssignment(assignment); @@ -179,7 +198,8 @@ std::vector Instantiator::instantiateLimited(const HtnOp& op, const // Create corresponding op Substitution s; - for (size_t i = 0; i < newAssignment.size(); i++) { + for (size_t i = 0; i < newAssignment.size(); i++) + { assert(i < argIndicesByPriority.size()); int arg = op.getArguments()[argIndicesByPriority[i]]; s[arg] = newAssignment[i]; @@ -187,32 +207,38 @@ std::vector Instantiator::instantiateLimited(const HtnOp& op, const HtnOp newOp = op.substitute(s); // Test validity - if (!_analysis.hasValidPreconditions(newOp.getPreconditions()) - || !_analysis.hasValidPreconditions(newOp.getExtraPreconditions())) continue; + if (!_analysis.hasValidPreconditions(newOp.getPreconditions()) || !_analysis.hasValidPreconditions(newOp.getExtraPreconditions())) + continue; // All ok -- add to stack - if (newAssignment.size() == doneInstSize) { + if (newAssignment.size() == doneInstSize) + { - // If there are remaining variables: + // If there are remaining variables: // is there some valid constant for each of them? - if (!_htn.hasSomeInstantiation(newOp.getSignature())) continue; + if (!_htn.hasSomeInstantiation(newOp.getSignature())) + continue; // This instantiation is finished: // Assemble instantiated signature instantiation.emplace_back(newOp.getSignature()); - if (limit > 0) { - if (returnUnfinished && instantiation.size() == limit) { + if (limit > 0) + { + if (returnUnfinished && instantiation.size() == limit) + { // Limit exceeded -- return unfinished instantiation return instantiation; } - if (!returnUnfinished && instantiation.size() > limit) { + if (!returnUnfinished && instantiation.size() > limit) + { // Limit exceeded -- return failure return std::vector(); } } - - } else { + } + else + { // Unfinished instantiation assignmentsStack.push_back(newAssignment); } @@ -221,25 +247,28 @@ std::vector Instantiator::instantiateLimited(const HtnOp& op, const __op = NULL; - //log("INST %s : %i instantiations\n", TOSTR(op.getSignature()), instantiation.size()); + // log("INST %s : %i instantiations\n", TOSTR(op.getSignature()), instantiation.size()); return instantiation; } -const FlatHashMap& Instantiator::getPreconditionRatings(const USignature& opSig) { +const FlatHashMap &Instantiator::getPreconditionRatings(const USignature &opSig) +{ int nameId = opSig._name_id; - + // Substitution mapping - std::vector placeholderArgs; + std::basic_string placeholderArgs; USignature normSig = _htn.getNormalizedLifted(opSig, placeholderArgs); Substitution sFromPlaceholder(placeholderArgs, opSig._args); - if (!_precond_ratings.count(nameId)) { + if (!_precond_ratings.count(nameId)) + { // Compute NodeHashMap> ratings; NodeHashMap> numRatings; - - NetworkTraversal(_htn).traverse(normSig, NetworkTraversal::TRAVERSE_PREORDER, [&](const USignature& nodeSig, int depth) { + + NetworkTraversal(_htn).traverse(normSig, NetworkTraversal::TRAVERSE_PREORDER, [&](const USignature &nodeSig, int depth) + { HtnOp op = (_htn.isAction(nodeSig) ? (HtnOp)_htn.toAction(nodeSig._name_id, nodeSig._args) : @@ -265,17 +294,19 @@ const FlatHashMap& Instantiator::getPreconditionRatings(const USigna ratings[opArg][depth] += (numPrecondArgs > 0) ? (float)occs / numPrecondArgs : 0; numRatings[opArg][depth]++; - } - }); + } }); _precond_ratings[nameId]; - for (const auto& entry : ratings) { - const int& arg = entry.first; + for (const auto &entry : ratings) + { + const int &arg = entry.first; _precond_ratings[nameId][arg] = 0; - for (size_t depth = 0; depth < entry.second.size(); depth++) { - const float& r = entry.second[depth]; - const int& numR = numRatings[arg][depth]; - if (numR > 0) _precond_ratings[nameId][arg] += 1.0f/(1 << depth) * r/numR; + for (size_t depth = 0; depth < entry.second.size(); depth++) + { + const float &r = entry.second[depth]; + const int &numR = numRatings[arg][depth]; + if (numR > 0) + _precond_ratings[nameId][arg] += 1.0f / (1 << depth) * r / numR; } } } diff --git a/src/algo/minres.h b/src/algo/minres.h index 8321e24..e5ded5a 100644 --- a/src/algo/minres.h +++ b/src/algo/minres.h @@ -6,72 +6,88 @@ #include "algo/network_traversal.h" #include "algo/arg_iterator.h" +#include + // Minimum Recursive Expansion Size -class MinRES { +class MinRES +{ private: - HtnInstance& _htn; + HtnInstance &_htn; FlatHashMap _min_recursive_expansion_sizes; public: - MinRES(HtnInstance& htn) : _htn(htn) { - //computeMinNumPrimitiveChildren(); + MinRES(HtnInstance &htn) : _htn(htn) + { + // computeMinNumPrimitiveChildren(); } - int getMinNumPrimitiveChildren(int sigName) { - + int getMinNumPrimitiveChildren(int sigName) + { + if (_min_recursive_expansion_sizes.count(sigName)) return _min_recursive_expansion_sizes[sigName]; - assert(_htn.isAction(USignature(sigName, std::vector())) || Log::e("Invalid query for MinRES: %s\n", TOSTR(sigName))); + assert(_htn.isAction(USignature(sigName, {})) || Log::e("Invalid query for MinRES: %s\n", TOSTR(sigName))); int blankId = _htn.getBlankActionSig()._name_id; - int& minNumChildren = _min_recursive_expansion_sizes[sigName]; - minNumChildren = sigName == blankId - || _htn.getActionNameFromRepetition(sigName) == blankId - ? 0 : 1; + int &minNumChildren = _min_recursive_expansion_sizes[sigName]; + minNumChildren = sigName == blankId || _htn.getActionNameFromRepetition(sigName) == blankId + ? 0 + : 1; return minNumChildren; } - void computeMinNumPrimitiveChildren() { + void computeMinNumPrimitiveChildren() + { - for (const auto& [nameId, action] : _htn.getActionTemplates()) { - Log::d("%s : MinRES = %i\n", TOSTR(action.getSignature()), - getMinNumPrimitiveChildren(nameId)); + for (const auto &[nameId, action] : _htn.getActionTemplates()) + { + Log::d("%s : MinRES = %i\n", TOSTR(action.getSignature()), + getMinNumPrimitiveChildren(nameId)); } NetworkTraversal nt(_htn); - + bool change = true; size_t numPasses = 0; - while (change) { + while (change) + { change = false; - for (const auto& [nameId, reduction] : _htn.getReductionTemplates()) { + for (const auto &[nameId, reduction] : _htn.getReductionTemplates()) + { - if (_min_recursive_expansion_sizes.count(nameId)) continue; + if (_min_recursive_expansion_sizes.count(nameId)) + continue; bool canComputeMinRes = true; - for (const auto& sig : nt.getPossibleChildren(reduction.getSignature())) { - if (sig._name_id != nameId && !_min_recursive_expansion_sizes.count(sig._name_id)) { + for (const auto &sig : nt.getPossibleChildren(reduction.getSignature())) + { + if (sig._name_id != nameId && !_min_recursive_expansion_sizes.count(sig._name_id)) + { canComputeMinRes = false; break; } } - if (!canComputeMinRes) continue; + if (!canComputeMinRes) + continue; - std::vector args(_htn.getSorts(nameId).size(), -1); + std::basic_string args(_htn.getSorts(nameId).size(), -1); USignature normSig(nameId, args); - int& minNumChildren = _min_recursive_expansion_sizes[nameId]; - const auto& r = _htn.getReductionTemplate(nameId); - for (size_t o = 0; o < r.getSubtasks().size(); o++) { + int &minNumChildren = _min_recursive_expansion_sizes[nameId]; + const auto &r = _htn.getReductionTemplate(nameId); + for (size_t o = 0; o < r.getSubtasks().size(); o++) + { int minNumChildrenAtO = 999999; std::vector children; nt.getPossibleChildren(r.getSubtasks(), o, children); FlatHashSet childrenIds; - for (const auto& child : children) - if (child._name_id != nameId) childrenIds.insert(child._name_id); - for (const auto& child : childrenIds) { + for (const auto &child : children) + if (child._name_id != nameId) + childrenIds.insert(child._name_id); + for (const auto &child : childrenIds) + { minNumChildrenAtO = std::min(minNumChildrenAtO, getMinNumPrimitiveChildren(child)); } @@ -79,9 +95,9 @@ class MinRES { minNumChildren += minNumChildrenAtO; } - Log::d("%s : MinRES = %i\n", TOSTR(reduction.getSignature()), - getMinNumPrimitiveChildren(nameId)); - + Log::d("%s : MinRES = %i\n", TOSTR(reduction.getSignature()), + getMinNumPrimitiveChildren(nameId)); + change = true; } numPasses++; diff --git a/src/algo/network_traversal.cpp b/src/algo/network_traversal.cpp index 1bc32df..5fed2a9 100644 --- a/src/algo/network_traversal.cpp +++ b/src/algo/network_traversal.cpp @@ -2,8 +2,9 @@ #include "network_traversal.h" #include "data/htn_instance.h" -void NetworkTraversal::traverse(const USignature& opSig, TraverseOrder order, std::function onVisit) { - +void NetworkTraversal::traverse(const USignature &opSig, TraverseOrder order, std::function onVisit) +{ + FlatHashSet seenSignatures; std::vector frontier; std::vector depths; @@ -13,92 +14,115 @@ void NetworkTraversal::traverse(const USignature& opSig, TraverseOrder order, st depths.push_back(1); // Traverse graph of signatures with sub-reduction relationships - while (!frontier.empty()) { - USignature nodeSig = frontier.back(); frontier.pop_back(); - int depth = depths.back(); depths.pop_back(); - //log("%s\n", TOSTR(nodeSig)); - - if (depth < 0) { + while (!frontier.empty()) + { + USignature nodeSig = frontier.back(); + frontier.pop_back(); + int depth = depths.back(); + depths.pop_back(); + // log("%s\n", TOSTR(nodeSig)); + + if (depth < 0) + { // Post-order traversal: visit and pop assert(order == TRAVERSE_POSTORDER); - onVisit(nodeSig, -depth+1); + onVisit(nodeSig, -depth + 1); continue; } // Normalize node signature arguments to compare to seen signatures Substitution s; - for (size_t argPos = 0; argPos < nodeSig._args.size(); argPos++) { + for (size_t argPos = 0; argPos < nodeSig._args.size(); argPos++) + { int arg = nodeSig._args[argPos]; - if (arg > 0 && _htn->isVariable(arg)) { + if (arg > 0 && _htn->isVariable(arg)) + { // Variable - if (!s.count(arg)) s[arg] = _htn->nameId(std::string("??_") + std::to_string(argPos)); + if (!s.count(arg)) + s[arg] = _htn->nameId(std::string("??_") + std::to_string(argPos)); } } USignature normNodeSig = nodeSig.substitute(s); // Already saw this signature? - if (seenSignatures.count(normNodeSig)) continue; - - if (order == TRAVERSE_PREORDER) { + if (seenSignatures.count(normNodeSig)) + continue; + + if (order == TRAVERSE_PREORDER) + { // Visit node (using "original" signature) - onVisit(nodeSig, depth-1); - } else { + onVisit(nodeSig, depth - 1); + } + else + { // Remember node to be visited after all children have been visited frontier.push_back(nodeSig); - depths.push_back(-depth+1); + depths.push_back(-depth + 1); } // Add to seen signatures seenSignatures.insert(normNodeSig); // Expand node, add children to frontier - for (const USignature& child : getPossibleChildren(nodeSig)) { + for (const USignature &child : getPossibleChildren(nodeSig)) + { // Arguments need to be renamed on recursive domains Substitution s; - for (int arg : child._args) { - if (arg > 0) s[arg] = _htn->nameId(_htn->toString(arg) + "_"); + for (int arg : child._args) + { + if (arg > 0) + s[arg] = _htn->nameId(_htn->toString(arg) + "_"); } frontier.push_back(child.substitute(s)); depths.push_back(depth); - //log("-> %s\n", TOSTR(child)); + // log("-> %s\n", TOSTR(child)); } } } -std::vector NetworkTraversal::getPossibleChildren(const USignature& opSig) { +std::vector NetworkTraversal::getPossibleChildren(const USignature &opSig) +{ std::vector result; int nameId = opSig._name_id; - if (!_htn->isReduction(opSig)) return result; + if (!_htn->isReduction(opSig)) + return result; // Reduction Reduction r = _htn->toReduction(nameId, opSig._args); - const std::vector& subtasks = r.getSubtasks(); - for (size_t i = 0; i < subtasks.size(); i++) getPossibleChildren(subtasks, i, result); + const std::vector &subtasks = r.getSubtasks(); + for (size_t i = 0; i < subtasks.size(); i++) + getPossibleChildren(subtasks, i, result); return result; } -void NetworkTraversal::getPossibleChildren(const std::vector& subtasks, int offset, std::vector& result) { +void NetworkTraversal::getPossibleChildren(const std::vector &subtasks, int offset, std::vector &result) +{ // Find all possible (sub-)reductions of this subtask - const USignature& sig = subtasks[offset]; + const USignature &sig = subtasks[offset]; int taskNameId = sig._name_id; - if (_htn->isAction(sig)) { + if (_htn->isAction(sig)) + { // Action result.push_back(sig); - } else { + } + else + { // Reduction std::vector subredIds = _htn->getReductionIdsOfTaskId(taskNameId); - for (int subredId : subredIds) { - const Reduction& subred = _htn->getReductionTemplate(subredId); + for (int subredId : subredIds) + { + const Reduction &subred = _htn->getReductionTemplate(subredId); // Substitute original subred. arguments // with the subtask's arguments - const std::vector& origArgs = subred.getTaskArguments(); + const std::basic_string &origArgs = subred.getTaskArguments(); // When substituting task args of a reduction, there may be multiple possibilities std::vector ss = Substitution::getAll(origArgs, sig._args); - for (const Substitution& s : ss) { + for (const Substitution &s : ss) + { result.push_back(subred.getSignature().substitute(s)); } } diff --git a/src/algo/planner.cpp b/src/algo/planner.cpp index 4e4437c..3b6639c 100644 --- a/src/algo/planner.cpp +++ b/src/algo/planner.cpp @@ -1,5 +1,6 @@ -#include +#include +#include #include "planner.h" #include "util/log.h" @@ -7,10 +8,11 @@ #include "util/timer.h" #include "sat/plan_optimizer.h" -int terminateSatCall(void* state) {return ((Planner*) state)->getTerminateSatCall();} +int terminateSatCall(void *state) { return ((Planner *)state)->getTerminateSatCall(); } + +int Planner::findPlan() +{ -int Planner::findPlan() { - int iteration = 0; Log::i("Iteration %i.\n", iteration); @@ -23,107 +25,128 @@ int Planner::findPlan() { bool solved = false; _enc.setTerminateCallback(this, terminateSatCall); - if (iteration >= firstSatCallIteration) { + if (iteration >= firstSatCallIteration) + { _enc.addAssumptions(_layer_idx); int result = _enc.solve(); - if (result == 0) { + if (result == 0) + { Log::w("Solver was interrupted. Discarding time limit for next solving attempts.\n"); _sat_time_limit = 0; } solved = result == 10; - } - + } + // Next layers - while (!solved && (maxIterations == 0 || iteration < maxIterations)) { + while (!solved && (maxIterations == 0 || iteration < maxIterations)) + { - if (iteration >= firstSatCallIteration) { + if (iteration >= firstSatCallIteration) + { _enc.printFailedVars(*_layers.back()); - if (_params.isNonzero("cs")) { // check solvability + if (_params.isNonzero("cs")) + { // check solvability Log::i("Not solved at layer %i with assumptions\n", _layer_idx); // Attempt to solve formula again, now without assumptions // (is usually simple; if it fails, we know the entire problem is unsolvable) int result = _enc.solve(); - if (result == 20) { + if (result == 20) + { Log::w("Unsolvable at layer %i even without assumptions!\n", _layer_idx); break; - } else { + } + else + { Log::i("Not proven unsolvable - expanding by another layer\n"); } - } else { + } + else + { Log::i("Unsolvable at layer %i -- expanding.\n", _layer_idx); } } - iteration++; + iteration++; Log::i("Iteration %i.\n", iteration); - + createNextLayer(); - if (iteration >= firstSatCallIteration) { + if (iteration >= firstSatCallIteration) + { _enc.addAssumptions(_layer_idx); int result = _enc.solve(); - if (result == 0) { + if (result == 0) + { Log::w("Solver was interrupted. Discarding time limit for next solving attempts.\n"); _sat_time_limit = 0; } solved = result == 10; - } + } } - if (!solved) { - if (iteration >= firstSatCallIteration) _enc.printFailedVars(*_layers.back()); + if (!solved) + { + if (iteration >= firstSatCallIteration) + _enc.printFailedVars(*_layers.back()); Log::w("No success. Exiting.\n"); return 1; } - Log::i("Found a solution at layer %i.\n", _layers.size()-1); + Log::i("Found a solution at layer %i.\n", _layers.size() - 1); _time_at_first_plan = Timer::elapsedSeconds(); improvePlan(iteration); _plan_writer.outputPlan(_plan); - printStatistics(); + printStatistics(); return 0; } -void Planner::improvePlan(int& iteration) { +void Planner::improvePlan(int &iteration) +{ // Compute extra layers after initial solution as desired PlanOptimizer optimizer(_htn, _layers, _enc); int maxIterations = _params.getIntParam("D"); int extraLayers = _params.getIntParam("el"); - int upperBound = _layers.back()->size()-1; - if (extraLayers != 0) { + int upperBound = _layers.back()->size() - 1; + if (extraLayers != 0) + { // Extract initial plan (for anytime purposes) _plan = _enc.extractPlan(); _has_plan = true; upperBound = optimizer.getPlanLength(std::get<0>(_plan)); Log::i("Initial plan at most shallow layer has length %i\n", upperBound); - - if (extraLayers == -1) { + + if (extraLayers == -1) + { // Indefinitely increase bound and solve until program is interrupted or max depth reached size_t el = 1; - do { + do + { // Extra layers without solving - for (size_t x = 0; x < el && (maxIterations == 0 || iteration < maxIterations); x++) { - iteration++; + for (size_t x = 0; x < el && (maxIterations == 0 || iteration < maxIterations); x++) + { + iteration++; Log::i("Iteration %i. (extra)\n", iteration); createNextLayer(); } // Solve again (to get another plan) _enc.addAssumptions(_layer_idx); int result = _enc.solve(); - if (result != 10) break; + if (result != 10) + break; // Extract plan at layer, update bound auto thisLayerPlan = _enc.extractPlan(); int newLength = optimizer.getPlanLength(std::get<0>(thisLayerPlan)); // Update plan only if it is better than any previous plan - if (newLength < upperBound || !_has_plan) { + if (newLength < upperBound || !_has_plan) + { upperBound = newLength; _plan = thisLayerPlan; _has_plan = true; @@ -134,11 +157,13 @@ void Planner::improvePlan(int& iteration) { // Double number of extra layers in next iteration el *= 2; } while (maxIterations == 0 || iteration < maxIterations); - - } else { + } + else + { // Extra layers without solving - for (int x = 0; x < extraLayers; x++) { - iteration++; + for (int x = 0; x < extraLayers; x++) + { + iteration++; Log::i("Iteration %i. (extra)\n", iteration); createNextLayer(); } @@ -149,14 +174,17 @@ void Planner::improvePlan(int& iteration) { } } - if (extraLayers != -1) { - if (_optimization_factor != 0) { + if (extraLayers != -1) + { + if (_optimization_factor != 0) + { // Extract plan at final layer, update bound auto finalLayerPlan = _enc.extractPlan(); int newLength = optimizer.getPlanLength(std::get<0>(finalLayerPlan)); // Update plan only if it is better than any previous plan - if (newLength < upperBound || !_has_plan) { + if (newLength < upperBound || !_has_plan) + { upperBound = newLength; _plan = finalLayerPlan; _has_plan = true; @@ -164,8 +192,9 @@ void Planner::improvePlan(int& iteration) { Log::i("Initial plan at final layer has length %i\n", newLength); // Optimize optimizer.optimizePlan(upperBound, _plan, PlanOptimizer::ConstraintAddition::PERMANENT); - - } else { + } + else + { // Just extract plan _plan = _enc.extractPlan(); _has_plan = true; @@ -173,13 +202,16 @@ void Planner::improvePlan(int& iteration) { } } -void Planner::incrementPosition() { +void Planner::incrementPosition() +{ _num_instantiated_actions += _layers[_layer_idx]->at(_pos).getActions().size(); _num_instantiated_reductions += _layers[_layer_idx]->at(_pos).getReductions().size(); - _pos++; _num_instantiated_positions++; + _pos++; + _num_instantiated_positions++; } -void Planner::createFirstLayer() { +void Planner::createFirstLayer() +{ // Initial layer of size 2 (top level reduction + goal action) int initSize = 2; @@ -187,16 +219,18 @@ void Planner::createFirstLayer() { _layer_idx = 0; _pos = 0; _layers.push_back(new Layer(0, initSize)); - Layer& initLayer = (*_layers[0]); + Layer &initLayer = (*_layers[0]); initLayer[_pos].setPos(_layer_idx, _pos); - + /***** LAYER 0, POSITION 0 ******/ // Instantiate all possible init. reductions - for (USignature& rSig : _instantiator.getApplicableInstantiations(_htn.getInitReduction())) { + for (USignature &rSig : _instantiator.getApplicableInstantiations(_htn.getInitReduction())) + { auto rOpt = createValidReduction(rSig, USignature()); - if (rOpt) { - auto& r = rOpt.value(); + if (rOpt) + { + auto &r = rOpt.value(); USignature sig = r.getSignature(); initLayer[_pos].addReduction(sig); initLayer[_pos].addAxiomaticOp(sig); @@ -205,7 +239,7 @@ void Planner::createFirstLayer() { } addPreconditionConstraints(); initializeNextEffects(); - + incrementPosition(); /***** LAYER 0, POSITION 1 ******/ @@ -218,7 +252,7 @@ void Planner::createFirstLayer() { initLayer[_pos].addAction(goalSig); initLayer[_pos].addAxiomaticOp(goalSig); addPreconditionConstraints(); - + /***** LAYER 0 END ******/ initLayer[0].clearAfterInstantiation(); @@ -230,52 +264,58 @@ void Planner::createFirstLayer() { initLayer.consolidate(); } -void Planner::createNextLayer() { +void Planner::createNextLayer() +{ _layers.push_back(new Layer(_layers.size(), _layers.back()->getNextLayerSize())); - Layer& newLayer = *_layers.back(); + Layer &newLayer = *_layers.back(); Log::i("New layer size: %i\n", newLayer.size()); - Layer& oldLayer = (*_layers[_layer_idx]); + Layer &oldLayer = (*_layers[_layer_idx]); _layer_idx++; _pos = 0; // Instantiate new layer Log::i("Instantiating ...\n"); - for (_old_pos = 0; _old_pos < oldLayer.size(); _old_pos++) { + for (_old_pos = 0; _old_pos < oldLayer.size(); _old_pos++) + { size_t newPos = oldLayer.getSuccessorPos(_old_pos); size_t maxOffset = oldLayer[_old_pos].getMaxExpansionSize(); // Instantiate each new position induced by the old position - for (size_t offset = 0; offset < maxOffset; offset++) { - //Log::d("%i,%i,%i,%i\n", _old_pos, newPos, offset, newLayer.size()); + for (size_t offset = 0; offset < maxOffset; offset++) + { + // Log::d("%i,%i,%i,%i\n", _old_pos, newPos, offset, newLayer.size()); assert(_pos == newPos + offset); Log::v("- Position (%i,%i)\n", _layer_idx, _pos); - assert(newPos+offset < newLayer.size()); + assert(newPos + offset < newLayer.size()); createNextPosition(); - Log::v(" Instantiation done. (r=%i a=%i qf=%i supp=%i)\n", - (*_layers[_layer_idx])[_pos].getReductions().size(), - (*_layers[_layer_idx])[_pos].getActions().size(), - (*_layers[_layer_idx])[_pos].getQFacts().size(), - (*_layers[_layer_idx])[_pos].getPosFactSupports().size() + (*_layers[_layer_idx])[_pos].getNegFactSupports().size() - ); - if (_pos > 0) _layers[_layer_idx]->at(_pos-1).clearAfterInstantiation(); + Log::v(" Instantiation done. (r=%i a=%i qf=%i supp=%i)\n", + (*_layers[_layer_idx])[_pos].getReductions().size(), + (*_layers[_layer_idx])[_pos].getActions().size(), + (*_layers[_layer_idx])[_pos].getQFacts().size(), + (*_layers[_layer_idx])[_pos].getPosFactSupports().size() + (*_layers[_layer_idx])[_pos].getNegFactSupports().size()); + if (_pos > 0) + _layers[_layer_idx]->at(_pos - 1).clearAfterInstantiation(); incrementPosition(); checkTermination(); } } - if (_pos > 0) _layers[_layer_idx]->at(_pos-1).clearAfterInstantiation(); + if (_pos > 0) + _layers[_layer_idx]->at(_pos - 1).clearAfterInstantiation(); Log::i("Collected %i relevant facts at this layer\n", _analysis.getRelevantFacts().size()); // Encode new layer Log::i("Encoding ...\n"); - for (_old_pos = 0; _old_pos < oldLayer.size(); _old_pos++) { + for (_old_pos = 0; _old_pos < oldLayer.size(); _old_pos++) + { size_t newPos = oldLayer.getSuccessorPos(_old_pos); size_t maxOffset = oldLayer[_old_pos].getMaxExpansionSize(); - for (size_t offset = 0; offset < maxOffset; offset++) { + for (size_t offset = 0; offset < maxOffset; offset++) + { _pos = newPos + offset; Log::v("- Position (%i,%i)\n", _layer_idx, _pos); _enc.encode(_layer_idx, _pos); @@ -286,73 +326,86 @@ void Planner::createNextLayer() { newLayer.consolidate(); } -void Planner::createNextPosition() { +void Planner::createNextPosition() +{ // Set up all facts that may hold at this position. - if (_pos == 0) { + if (_pos == 0) + { propagateInitialState(); - } else { - Position& left = (*_layers[_layer_idx])[_pos-1]; + } + else + { + Position &left = (*_layers[_layer_idx])[_pos - 1]; createNextPositionFromLeft(left); } // Generate this new position's content based on the facts and the position above. - if (_layer_idx > 0) { + if (_layer_idx > 0) + { createNextPositionFromAbove(); } // Eliminate operations which are dominated by another operation - if (_params.isNonzero("edo")) + if (_params.isNonzero("edo")) _domination_resolver.eliminateDominatedOperations(_layers[_layer_idx]->at(_pos)); // In preparation for the upcoming position, // add all effects of the actions and reductions occurring HERE - // as (initially false) facts to THIS position. + // as (initially false) facts to THIS position. initializeNextEffects(); } -void Planner::createNextPositionFromAbove() { - Position& newPos = (*_layers[_layer_idx])[_pos]; +void Planner::createNextPositionFromAbove() +{ + Position &newPos = (*_layers[_layer_idx])[_pos]; newPos.setPos(_layer_idx, _pos); - int offset = _pos - (*_layers[_layer_idx-1]).getSuccessorPos(_old_pos); - //eliminateInvalidParentsAtCurrentState(offset); + int offset = _pos - (*_layers[_layer_idx - 1]).getSuccessorPos(_old_pos); + // eliminateInvalidParentsAtCurrentState(offset); propagateActions(offset); propagateReductions(offset); addPreconditionConstraints(); } -void Planner::createNextPositionFromLeft(Position& left) { - Position& newPos = (*_layers[_layer_idx])[_pos]; +void Planner::createNextPositionFromLeft(Position &left) +{ + Position &newPos = (*_layers[_layer_idx])[_pos]; newPos.setPos(_layer_idx, _pos); assert(left.getLayerIndex() == _layer_idx); - assert(left.getPositionIndex() == _pos-1); + assert(left.getPositionIndex() == _pos - 1); // Propagate fact changes from operations from previous position USigSet actionsToRemove; - const USigSet* ops[2] = {&left.getActions(), &left.getReductions()}; + const USigSet *ops[2] = {&left.getActions(), &left.getReductions()}; bool isAction = true; - for (const auto& set : ops) { - for (const auto& aSig : *set) { + for (const auto &set : ops) + { + for (const auto &aSig : *set) + { bool repeatedAction = isAction && _htn.isActionRepetition(aSig._name_id); - for (const Signature& fact : _analysis.getPossibleFactChanges(aSig)) { + for (const Signature &fact : _analysis.getPossibleFactChanges(aSig)) + { if (isAction && !addEffect( - repeatedAction ? aSig.renamed(_htn.getActionNameFromRepetition(aSig._name_id)) : aSig, - fact, - repeatedAction ? EffectMode::DIRECT_NO_QFACT : EffectMode::DIRECT)) { - + repeatedAction ? aSig.renamed(_htn.getActionNameFromRepetition(aSig._name_id)) : aSig, + fact, + repeatedAction ? EffectMode::DIRECT_NO_QFACT : EffectMode::DIRECT)) + { + // Impossible direct effect: forbid action retroactively. Log::w("Retroactively prune action %s due to impossible effect %s\n", TOSTR(aSig), TOSTR(fact)); actionsToRemove.insert(aSig); // Also remove any virtualized actions corresponding to this action USignature repSig = aSig.renamed(_htn.getRepetitionNameOfAction(aSig._name_id)); - if (left.hasAction(repSig)) actionsToRemove.insert(repSig); - + if (left.hasAction(repSig)) + actionsToRemove.insert(repSig); + break; } - if (!isAction && !addEffect(aSig, fact, EffectMode::INDIRECT)) { + if (!isAction && !addEffect(aSig, fact, EffectMode::INDIRECT)) + { // Impossible indirect effect: ignore. } } @@ -361,111 +414,136 @@ void Planner::createNextPositionFromLeft(Position& left) { isAction = false; } - for (const auto& aSig : actionsToRemove) { - _pruning.prune(aSig, _layer_idx, _pos-1); + for (const auto &aSig : actionsToRemove) + { + _pruning.prune(aSig, _layer_idx, _pos - 1); } } -void Planner::addPreconditionConstraints() { - Position& newPos = _layers[_layer_idx]->at(_pos); +void Planner::addPreconditionConstraints() +{ + Position &newPos = _layers[_layer_idx]->at(_pos); - for (const auto& aSig : newPos.getActions()) { - const Action& a = _htn.getOpTable().getAction(aSig); + for (const auto &aSig : newPos.getActions()) + { + const Action &a = _htn.getOpTable().getAction(aSig); // Add preconditions of action bool isRepetition = _htn.isActionRepetition(aSig._name_id); addPreconditionsAndConstraints(aSig, a.getPreconditions(), isRepetition); } - for (const auto& rSig : newPos.getReductions()) { + for (const auto &rSig : newPos.getReductions()) + { // Add preconditions of reduction addPreconditionsAndConstraints(rSig, _htn.getOpTable().getReduction(rSig).getPreconditions(), /*isRepetition=*/false); } } -void Planner::addPreconditionsAndConstraints(const USignature& op, const SigSet& preconditions, bool isRepetition) { - Position& newPos = _layers[_layer_idx]->at(_pos); - +void Planner::addPreconditionsAndConstraints(const USignature &op, const SigSet &preconditions, bool isRepetition) +{ + Position &newPos = _layers[_layer_idx]->at(_pos); + USignature constrOp = isRepetition ? USignature(_htn.getActionNameFromRepetition(op._name_id), op._args) : op; - for (const Signature& fact : preconditions) { + for (const Signature &fact : preconditions) + { auto cOpt = addPrecondition(op, fact, !isRepetition); - if (cOpt) newPos.addSubstitutionConstraint(constrOp, std::move(cOpt.value())); + if (cOpt) + newPos.addSubstitutionConstraint(constrOp, std::move(cOpt.value())); } - if (!isRepetition) addQConstantTypeConstraints(op); + if (!isRepetition) + addQConstantTypeConstraints(op); - if (!newPos.getSubstitutionConstraints().count(op)) return; + if (!newPos.getSubstitutionConstraints().count(op)) + return; // Merge substitution constraints as far as possible - auto& constraints = newPos.getSubstitutionConstraints().at(op); - //Log::d("MERGE? %i constraints\n", constraints.size()); - for (size_t i = 0; i < constraints.size(); i++) { - for (size_t j = i+1; j < constraints.size(); j++) { - auto& iTree = constraints[i]; - auto& jTree = constraints[j]; - if (iTree.canMerge(jTree)) { - //Log::d("MERGE %s %i,%i sizes %i,%i\n", - // iTree.getPolarity() == SubstitutionConstraint::ANY_VALID ? "ANY_VALID" : "NO_INVALID", - // i, j, iTree.getEncodedSize(), jTree.getEncodedSize()); + auto &constraints = newPos.getSubstitutionConstraints().at(op); + // Log::d("MERGE? %i constraints\n", constraints.size()); + for (size_t i = 0; i < constraints.size(); i++) + { + for (size_t j = i + 1; j < constraints.size(); j++) + { + auto &iTree = constraints[i]; + auto &jTree = constraints[j]; + if (iTree.canMerge(jTree)) + { + // Log::d("MERGE %s %i,%i sizes %i,%i\n", + // iTree.getPolarity() == SubstitutionConstraint::ANY_VALID ? "ANY_VALID" : "NO_INVALID", + // i, j, iTree.getEncodedSize(), jTree.getEncodedSize()); iTree.merge(std::move(jTree)); - //Log::d("MERGED: new size %i\n", iTree.getEncodedSize()); - if (j+1 < constraints.size()) + // Log::d("MERGED: new size %i\n", iTree.getEncodedSize()); + if (j + 1 < constraints.size()) constraints[j] = std::move(constraints.back()); - constraints.erase(constraints.begin()+constraints.size()-1); + constraints.erase(constraints.begin() + constraints.size() - 1); j--; } } } } -std::optional Planner::addPrecondition(const USignature& op, const Signature& fact, bool addQFact) { +std::optional Planner::addPrecondition(const USignature &op, const Signature &fact, bool addQFact) +{ - Position& pos = (*_layers[_layer_idx])[_pos]; - const USignature& factAbs = fact.getUnsigned(); + Position &pos = (*_layers[_layer_idx])[_pos]; + const USignature &factAbs = fact.getUnsigned(); - if (!_htn.hasQConstants(factAbs)) { + if (!_htn.hasQConstants(factAbs)) + { assert(_analysis.isReachable(fact) || Log::e("Precondition %s not reachable!\n", TOSTR(fact))); - - if (_analysis.isReachable(factAbs, !fact._negated)) { + + if (_analysis.isReachable(factAbs, !fact._negated)) + { // Negated prec. is reachable: not statically resolvable initializeFact(pos, factAbs); _analysis.addRelevantFact(factAbs); } return std::optional(); } - - std::vector sorts = _htn.getOpSortsForCondition(factAbs, op); - std::vector sortedArgIndices = SubstitutionConstraint::getSortedSubstitutedArgIndices(_htn, factAbs._args, sorts); + + std::basic_string sorts = _htn.getOpSortsForCondition(factAbs, op); + std::basic_string sortedArgIndices = SubstitutionConstraint::getSortedSubstitutedArgIndices(_htn, factAbs._args, sorts); std::vector involvedQConsts(sortedArgIndices.size()); - for (size_t i = 0; i < sortedArgIndices.size(); i++) involvedQConsts[i] = factAbs._args[sortedArgIndices[i]]; + for (size_t i = 0; i < sortedArgIndices.size(); i++) + involvedQConsts[i] = factAbs._args[sortedArgIndices[i]]; SubstitutionConstraint c(involvedQConsts); bool staticallyResolvable = true; USigSet relevants; - + auto eligibleArgs = _htn.getEligibleArgs(factAbs, sorts); auto polarity = SubstitutionConstraint::UNDECIDED; - size_t totalSize = 1; for (auto& args : eligibleArgs) totalSize *= args.size(); + size_t totalSize = 1; + for (auto &args : eligibleArgs) + totalSize *= args.size(); size_t sampleSize = 25; - bool doSample = totalSize > 2*sampleSize; - if (doSample) { + bool doSample = totalSize > 2 * sampleSize; + if (doSample) + { size_t valids = 0; // Check out a random sample of the possible decoded objects - for (const USignature& decFactAbs : _htn.decodeObjects(factAbs, eligibleArgs, sampleSize)) { - if (_analysis.isReachable(decFactAbs, fact._negated)) valids++; + for (const USignature &decFactAbs : _htn.decodeObjects(factAbs, eligibleArgs, sampleSize)) + { + if (_analysis.isReachable(decFactAbs, fact._negated)) + valids++; } - polarity = valids < sampleSize/2 ? SubstitutionConstraint::ANY_VALID : SubstitutionConstraint::NO_INVALID; + polarity = valids < sampleSize / 2 ? SubstitutionConstraint::ANY_VALID : SubstitutionConstraint::NO_INVALID; c.fixPolarity(polarity); } // For each fact decoded from the q-fact: - for (const USignature& decFactAbs : _htn.decodeObjects(factAbs, eligibleArgs)) { + for (const USignature &decFactAbs : _htn.decodeObjects(factAbs, eligibleArgs)) + { // Can the decoded fact occur as is? - if (_analysis.isReachable(decFactAbs, fact._negated)) { + if (_analysis.isReachable(decFactAbs, fact._negated)) + { if (polarity != SubstitutionConstraint::NO_INVALID) c.addValid(SubstitutionConstraint::decodingToPath(factAbs._args, decFactAbs._args, sortedArgIndices)); - } else { + } + else + { // Fact cannot hold here if (polarity != SubstitutionConstraint::ANY_VALID) c.addInvalid(SubstitutionConstraint::decodingToPath(factAbs._args, decFactAbs._args, sortedArgIndices)); @@ -473,8 +551,9 @@ std::optional Planner::addPrecondition(const USignature& } // If the fact is reachable, is it even invariant? - if (_analysis.isInvariant(decFactAbs, fact._negated)) { - // Yes! This precondition is trivially satisfied + if (_analysis.isInvariant(decFactAbs, fact._negated)) + { + // Yes! This precondition is trivially satisfied // with above substitution restrictions continue; } @@ -483,244 +562,299 @@ std::optional Planner::addPrecondition(const USignature& relevants.insert(decFactAbs); } - if (!staticallyResolvable) { - if (addQFact) pos.addQFact(factAbs); - for (const USignature& decFactAbs : relevants) { + if (!staticallyResolvable) + { + if (addQFact) + pos.addQFact(factAbs); + for (const USignature &decFactAbs : relevants) + { // Decoded fact may be new - initialize as necessary initializeFact(pos, decFactAbs); - if (addQFact) pos.addQFactDecoding(factAbs, decFactAbs, fact._negated); + if (addQFact) + pos.addQFactDecoding(factAbs, decFactAbs, fact._negated); _analysis.addRelevantFact(decFactAbs); } } // else : encoding the precondition is not necessary! - if (!doSample) c.fixPolarity(); + if (!doSample) + c.fixPolarity(); return std::optional(std::move(c)); } -bool Planner::addEffect(const USignature& opSig, const Signature& fact, EffectMode mode) { - Position& pos = (*_layers[_layer_idx])[_pos]; +bool Planner::addEffect(const USignature &opSig, const Signature &fact, EffectMode mode) +{ + Position &pos = (*_layers[_layer_idx])[_pos]; assert(_pos > 0); - Position& left = (*_layers[_layer_idx])[_pos-1]; + Position &left = (*_layers[_layer_idx])[_pos - 1]; USignature factAbs = fact.getUnsigned(); bool isQFact = _htn.hasQConstants(factAbs); - if (!isQFact) { + if (!isQFact) + { // Invariant fact? --> no need to encode - if (_analysis.isInvariant(fact)) return true; + if (_analysis.isInvariant(fact)) + return true; - if (mode != INDIRECT) _analysis.addRelevantFact(factAbs); + if (mode != INDIRECT) + _analysis.addRelevantFact(factAbs); // Depending on whether fact supports are encoded for primitive ops only, // add the ground fact to the op's support accordingly - if (_nonprimitive_support || _htn.isAction(opSig)) { + if (_nonprimitive_support || _htn.isAction(opSig)) + { pos.addFactSupport(fact, opSig); - } else { + } + else + { // Remember that there is some (unspecified) support for this fact pos.touchFactSupport(fact); } - + _analysis.addReachableFact(fact); return true; } // Create the full set of valid decodings for this qfact - std::vector sorts = _htn.getOpSortsForCondition(factAbs, opSig); - std::vector sortedArgIndices = SubstitutionConstraint::getSortedSubstitutedArgIndices(_htn, factAbs._args, sorts); + std::basic_string sorts = _htn.getOpSortsForCondition(factAbs, opSig); + std::basic_string sortedArgIndices = SubstitutionConstraint::getSortedSubstitutedArgIndices(_htn, factAbs._args, sorts); const bool isConstrained = left.getSubstitutionConstraints().count(opSig); - + std::vector involvedQConsts(sortedArgIndices.size()); - for (size_t i = 0; i < sortedArgIndices.size(); i++) involvedQConsts[i] = factAbs._args[sortedArgIndices[i]]; - std::vector fittingConstrs, otherConstrs; - if (isConstrained) { - for (auto& c : left.getSubstitutionConstraints().at(opSig)) { - if (c.getInvolvedQConstants() == involvedQConsts) fittingConstrs.push_back(&c); - else if (c.getPolarity() == SubstitutionConstraint::NO_INVALID || c.involvesSupersetOf(involvedQConsts)) + for (size_t i = 0; i < sortedArgIndices.size(); i++) + involvedQConsts[i] = factAbs._args[sortedArgIndices[i]]; + std::vector fittingConstrs, otherConstrs; + if (isConstrained) + { + for (auto &c : left.getSubstitutionConstraints().at(opSig)) + { + if (c.getInvolvedQConstants() == involvedQConsts) + fittingConstrs.push_back(&c); + else if (c.getPolarity() == SubstitutionConstraint::NO_INVALID || c.involvesSupersetOf(involvedQConsts)) otherConstrs.push_back(&c); } } - + bool anyGood = false; bool staticallyResolvable = true; - for (const USignature& decFactAbs : _htn.decodeObjects(factAbs, _htn.getEligibleArgs(factAbs, sorts))) { + for (const USignature &decFactAbs : _htn.decodeObjects(factAbs, _htn.getEligibleArgs(factAbs, sorts))) + { auto path = SubstitutionConstraint::decodingToPath(factAbs._args, decFactAbs._args, sortedArgIndices); // Check if this decoding is known to be invalid due to some precondition - if (isConstrained) { + if (isConstrained) + { bool isValid = true; - for (const auto& c : fittingConstrs) { - if (!c->isValid(path, /*sameReference=*/true)) { + for (const auto &c : fittingConstrs) + { + if (!c->isValid(path, /*sameReference=*/true)) + { isValid = false; break; } } - if (isValid) for (const auto& c : otherConstrs) { - if (!c->isValid(path, /*sameReference=*/false)) { - isValid = false; - break; + if (isValid) + for (const auto &c : otherConstrs) + { + if (!c->isValid(path, /*sameReference=*/false)) + { + isValid = false; + break; + } } - } - if (!isValid) continue; + if (!isValid) + continue; } anyGood = true; - if (_analysis.isInvariant(decFactAbs, fact._negated)) { + if (_analysis.isInvariant(decFactAbs, fact._negated)) + { // Effect holds trivially continue; } // Valid effect decoding _analysis.addReachableFact(decFactAbs, /*negated=*/fact._negated); - if (_nonprimitive_support || _htn.isAction(opSig)) { + if (_nonprimitive_support || _htn.isAction(opSig)) + { pos.addIndirectFactSupport(decFactAbs, fact._negated, opSig, path); - } else { + } + else + { pos.touchFactSupport(decFactAbs, fact._negated); } - if (mode != INDIRECT) { - if (mode == DIRECT) pos.addQFactDecoding(factAbs, decFactAbs, fact._negated); + if (mode != INDIRECT) + { + if (mode == DIRECT) + pos.addQFactDecoding(factAbs, decFactAbs, fact._negated); _analysis.addRelevantFact(decFactAbs); } staticallyResolvable = false; } // Not a single valid decoding of the effect? -> Invalid effect. - if (!anyGood) return false; + if (!anyGood) + return false; + + if (!staticallyResolvable && mode == DIRECT) + pos.addQFact(factAbs); - if (!staticallyResolvable && mode == DIRECT) pos.addQFact(factAbs); - return true; } -void Planner::propagateInitialState() { +void Planner::propagateInitialState() +{ assert(_layer_idx > 0); assert(_pos == 0); - Position& newPos = (*_layers[_layer_idx])[0]; - Position& above = (*_layers[_layer_idx-1])[0]; + Position &newPos = (*_layers[_layer_idx])[0]; + Position &above = (*_layers[_layer_idx - 1])[0]; _analysis.resetReachability(); // Propagate TRUE facts - for (const USignature& fact : above.getTrueFacts()) { + for (const USignature &fact : above.getTrueFacts()) + { newPos.addTrueFact(fact); _analysis.addInitializedFact(fact); } - for (const USignature& fact : above.getFalseFacts()) { + for (const USignature &fact : above.getFalseFacts()) + { newPos.addFalseFact(fact); _analysis.addInitializedFact(fact); } } -void Planner::propagateActions(size_t offset) { - Position& newPos = (*_layers[_layer_idx])[_pos]; - Position& above = (*_layers[_layer_idx-1])[_old_pos]; +void Planner::propagateActions(size_t offset) +{ + Position &newPos = (*_layers[_layer_idx])[_pos]; + Position &above = (*_layers[_layer_idx - 1])[_old_pos]; // Check validity of actions at above position std::vector actionsToPrune; size_t numActionsBefore = above.getActions().size(); - for (const auto& aSig : above.getActions()) { - const Action& a = _htn.getOpTable().getAction(aSig); + for (const auto &aSig : above.getActions()) + { + const Action &a = _htn.getOpTable().getAction(aSig); // Can the action occur here w.r.t. the current state? - bool valid = _analysis.hasValidPreconditions(a.getPreconditions()) - && _analysis.hasValidPreconditions(a.getExtraPreconditions()); + bool valid = _analysis.hasValidPreconditions(a.getPreconditions()) && _analysis.hasValidPreconditions(a.getExtraPreconditions()); // If not: forbid the action, i.e., its parent action - if (!valid) { - Log::i("Retroactively prune action %s@(%i,%i): no children at offset %i\n", TOSTR(aSig), _layer_idx-1, _old_pos, offset); + if (!valid) + { + Log::i("Retroactively prune action %s@(%i,%i): no children at offset %i\n", TOSTR(aSig), _layer_idx - 1, _old_pos, offset); actionsToPrune.push_back(aSig); } } // Prune invalid actions at above position - for (const auto& aSig : actionsToPrune) { - _pruning.prune(aSig, _layer_idx-1, _old_pos); + for (const auto &aSig : actionsToPrune) + { + _pruning.prune(aSig, _layer_idx - 1, _old_pos); } - assert(above.getActions().size() == numActionsBefore - actionsToPrune.size() - || Log::e("%i != %i-%i\n", above.getActions().size(), numActionsBefore, actionsToPrune.size())); + assert(above.getActions().size() == numActionsBefore - actionsToPrune.size() || Log::e("%i != %i-%i\n", above.getActions().size(), numActionsBefore, actionsToPrune.size())); // Propagate remaining (valid) actions from above - for (const auto& aSig : above.getActions()) { - if (offset < 1) { + for (const auto &aSig : above.getActions()) + { + if (offset < 1) + { // proper action propagation assert(_htn.isFullyGround(aSig)); - if (_params.isNonzero("aar") && !_htn.isActionRepetition(aSig._name_id)) { + if (_params.isNonzero("aar") && !_htn.isActionRepetition(aSig._name_id)) + { // Virtualize child of action USignature vChildSig = _htn.getRepetitionOfAction(aSig); newPos.addAction(vChildSig); newPos.addExpansion(aSig, vChildSig); - } else { + } + else + { // Treat as a normal action newPos.addAction(aSig); newPos.addExpansion(aSig, aSig); } - } else { + } + else + { // action expands to "blank" at non-zero offsets - const USignature& blankSig = _htn.getBlankActionSig(); + const USignature &blankSig = _htn.getBlankActionSig(); newPos.addAction(blankSig); newPos.addExpansion(aSig, blankSig); } } } -void Planner::propagateReductions(size_t offset) { - Position& newPos = (*_layers[_layer_idx])[_pos]; - Position& above = (*_layers[_layer_idx-1])[_old_pos]; +void Planner::propagateReductions(size_t offset) +{ + Position &newPos = (*_layers[_layer_idx])[_pos]; + Position &above = (*_layers[_layer_idx - 1])[_old_pos]; NodeHashMap subtaskToParents; NodeHashSet reductionsWithChildren; // Collect all possible subtasks and remember their possible parents - for (const auto& rSig : above.getReductions()) { + for (const auto &rSig : above.getReductions()) + { const Reduction r = _htn.getOpTable().getReduction(rSig); - - if (offset < r.getSubtasks().size()) { + + if (offset < r.getSubtasks().size()) + { // Proper expansion - const USignature& subtask = r.getSubtasks()[offset]; + const USignature &subtask = r.getSubtasks()[offset]; subtaskToParents[subtask].insert(rSig); - } else { + } + else + { // Blank reductionsWithChildren.insert(rSig); - const USignature& blankSig = _htn.getBlankActionSig(); + const USignature &blankSig = _htn.getBlankActionSig(); newPos.addAction(blankSig); newPos.addExpansion(rSig, blankSig); } } // Iterate over all possible subtasks - for (const auto& [subtask, parents] : subtaskToParents) { + for (const auto &[subtask, parents] : subtaskToParents) + { // Calculate all possible actions fitting the subtask. auto allActions = instantiateAllActionsOfTask(subtask); // Any reduction(s) fitting the subtask? - for (const USignature& subRSig : instantiateAllReductionsOfTask(subtask)) { + for (const USignature &subRSig : instantiateAllReductionsOfTask(subtask)) + { - if (_htn.isAction(subRSig)) { + if (_htn.isAction(subRSig)) + { // Actually an action, not a reduction: remember for later allActions.push_back(subRSig); continue; } - const Reduction& subR = _htn.getOpTable().getReduction(subRSig); - + const Reduction &subR = _htn.getOpTable().getReduction(subRSig); + assert(_htn.isReduction(subRSig) && subRSig == subR.getSignature() && _htn.isFullyGround(subRSig)); - + newPos.addReduction(subRSig); newPos.addExpansionSize(subR.getSubtasks().size()); - for (const auto& rSig : parents) { + for (const auto &rSig : parents) + { reductionsWithChildren.insert(rSig); newPos.addExpansion(rSig, subRSig); } } // Any action(s) fitting the subtask? - for (const USignature& aSig : allActions) { + for (const USignature &aSig : allActions) + { assert(_htn.isFullyGround(aSig)); newPos.addAction(aSig); - for (const auto& rSig : parents) { + for (const auto &rSig : parents) + { reductionsWithChildren.insert(rSig); newPos.addExpansion(rSig, aSig); } @@ -728,22 +862,27 @@ void Planner::propagateReductions(size_t offset) { } // Check if any reduction has no valid children at all - for (const auto& rSig : above.getReductions()) { - if (!reductionsWithChildren.count(rSig)) { - Log::i("Retroactively prune reduction %s@(%i,%i): no children at offset %i\n", - TOSTR(rSig), _layer_idx-1, _old_pos, offset); - _pruning.prune(rSig, _layer_idx-1, _old_pos); + for (const auto &rSig : above.getReductions()) + { + if (!reductionsWithChildren.count(rSig)) + { + Log::i("Retroactively prune reduction %s@(%i,%i): no children at offset %i\n", + TOSTR(rSig), _layer_idx - 1, _old_pos, offset); + _pruning.prune(rSig, _layer_idx - 1, _old_pos); } } } -std::vector Planner::instantiateAllActionsOfTask(const USignature& task) { +std::vector Planner::instantiateAllActionsOfTask(const USignature &task) +{ std::vector result; - if (!_htn.isAction(task)) return result; - - for (USignature& sig : _instantiator.getApplicableInstantiations(_htn.toAction(task._name_id, task._args))) { - //Log::d("ADDACTION %s ?\n", TOSTR(action.getSignature())); + if (!_htn.isAction(task)) + return result; + + for (USignature &sig : _instantiator.getApplicableInstantiations(_htn.toAction(task._name_id, task._args))) + { + // Log::d("ADDACTION %s ?\n", TOSTR(action.getSignature())); Action action = _htn.toAction(sig._name_id, sig._args); // Rename any remaining variables in each action as unique q-constants, @@ -753,11 +892,15 @@ std::vector Planner::instantiateAllActionsOfTask(const USignature& t action.removeInconsistentEffects(); // Check validity - if (!_htn.isFullyGround(action.getSignature())) continue; - if (!_htn.hasConsistentlyTypedArgs(sig)) continue; - if (!_analysis.hasValidPreconditions(action.getPreconditions())) continue; - if (!_analysis.hasValidPreconditions(action.getExtraPreconditions())) continue; - + if (!_htn.isFullyGround(action.getSignature())) + continue; + if (!_htn.hasConsistentlyTypedArgs(sig)) + continue; + if (!_analysis.hasValidPreconditions(action.getPreconditions())) + continue; + if (!_analysis.hasValidPreconditions(action.getExtraPreconditions())) + continue; + // Action is valid sig = action.getSignature(); _htn.getOpTable().addAction(action); @@ -766,23 +909,29 @@ std::vector Planner::instantiateAllActionsOfTask(const USignature& t return result; } -std::vector Planner::instantiateAllReductionsOfTask(const USignature& task) { +std::vector Planner::instantiateAllReductionsOfTask(const USignature &task) +{ std::vector result; - if (!_htn.hasReductions(task._name_id)) return result; + if (!_htn.hasReductions(task._name_id)) + return result; // Filter and minimally instantiate methods // applicable in current (super)state - for (int redId : _htn.getReductionIdsOfTaskId(task._name_id)) { + for (int redId : _htn.getReductionIdsOfTaskId(task._name_id)) + { Reduction r = _htn.getReductionTemplate(redId); - if (_htn.isReductionPrimitivizable(redId)) { - const Action& a = _htn.getReductionPrimitivization(redId); + if (_htn.isReductionPrimitivizable(redId)) + { + const Action &a = _htn.getReductionPrimitivization(redId); std::vector subs = Substitution::getAll(r.getTaskArguments(), task._args); - for (const Substitution& s : subs) { + for (const Substitution &s : subs) + { USignature primSig = a.getSignature().substitute(s); - for (const auto& sig : instantiateAllActionsOfTask(primSig)) { + for (const auto &sig : instantiateAllActionsOfTask(primSig)) + { result.push_back(sig); } } @@ -790,62 +939,82 @@ std::vector Planner::instantiateAllReductionsOfTask(const USignature } std::vector subs = Substitution::getAll(r.getTaskArguments(), task._args); - for (const Substitution& s : subs) { - for (const auto& entry : s) assert(entry.second != 0); + for (const Substitution &s : subs) + { + for (const auto &entry : s) + assert(entry.second != 0); Reduction rSub = r.substituteRed(s); USignature origSig = rSub.getSignature(); - if (!_htn.hasConsistentlyTypedArgs(origSig)) continue; - - for (USignature& red : _instantiator.getApplicableInstantiations(rSub)) { + if (!_htn.hasConsistentlyTypedArgs(origSig)) + continue; + + for (USignature &red : _instantiator.getApplicableInstantiations(rSub)) + { auto rOpt = createValidReduction(red, task); - if (rOpt) result.push_back(rOpt.value().getSignature()); + if (rOpt) + result.push_back(rOpt.value().getSignature()); } } } return result; } -std::optional Planner::createValidReduction(const USignature& sig, const USignature& task) { +std::optional Planner::createValidReduction(const USignature &sig, const USignature &task) +{ std::optional rOpt; - // Rename any remaining variables in each action as new, unique q-constants + // Rename any remaining variables in each action as new, unique q-constants Reduction red = _htn.toReduction(sig._name_id, sig._args); auto domains = _analysis.getReducedArgumentDomains(red); red = _htn.replaceVariablesWithQConstants(red, domains, _layer_idx, _pos); // Check validity bool isValid = true; - if (task._name_id >= 0 && red.getTaskSignature() != task) isValid = false; - else if (!_htn.isFullyGround(red.getSignature())) isValid = false; - else if (!_htn.hasConsistentlyTypedArgs(red.getSignature())) isValid = false; - else if (!_analysis.hasValidPreconditions(red.getPreconditions())) isValid = false; - else if (!_analysis.hasValidPreconditions(red.getExtraPreconditions())) isValid = false; - - if (isValid) { + if (task._name_id >= 0 && red.getTaskSignature() != task) + isValid = false; + else if (!_htn.isFullyGround(red.getSignature())) + isValid = false; + else if (!_htn.hasConsistentlyTypedArgs(red.getSignature())) + isValid = false; + else if (!_analysis.hasValidPreconditions(red.getPreconditions())) + isValid = false; + else if (!_analysis.hasValidPreconditions(red.getExtraPreconditions())) + isValid = false; + + if (isValid) + { _htn.getOpTable().addReduction(red); rOpt.emplace(red); } return rOpt; } -void Planner::initializeNextEffects() { - Position& newPos = (*_layers[_layer_idx])[_pos]; - +void Planner::initializeNextEffects() +{ + Position &newPos = (*_layers[_layer_idx])[_pos]; + // For each possible operation effect: - const USigSet* ops[2] = {&newPos.getActions(), &newPos.getReductions()}; + const USigSet *ops[2] = {&newPos.getActions(), &newPos.getReductions()}; bool isAction = true; - for (const auto& set : ops) { - for (const auto& aSig : *set) { - const SigSet& pfc = _analysis.getPossibleFactChanges(aSig, FactAnalysis::FULL, isAction ? FactAnalysis::ACTION : FactAnalysis::REDUCTION); - for (const Signature& eff : pfc) { - - if (!_htn.hasQConstants(eff._usig)) { + for (const auto &set : ops) + { + for (const auto &aSig : *set) + { + const SigSet &pfc = _analysis.getPossibleFactChanges(aSig, FactAnalysis::FULL, isAction ? FactAnalysis::ACTION : FactAnalysis::REDUCTION); + for (const Signature &eff : pfc) + { + + if (!_htn.hasQConstants(eff._usig)) + { // New ground fact: set before the action may happen - initializeFact(newPos, eff._usig); - } else { - std::vector sorts = _htn.getOpSortsForCondition(eff._usig, aSig); - for (const USignature& decEff : _htn.decodeObjects(eff._usig, _htn.getEligibleArgs(eff._usig, sorts))) { + initializeFact(newPos, eff._usig); + } + else + { + std::basic_string sorts = _htn.getOpSortsForCondition(eff._usig, aSig); + for (const USignature &decEff : _htn.decodeObjects(eff._usig, _htn.getEligibleArgs(eff._usig, sorts))) + { // New ground fact: set before the action may happen initializeFact(newPos, decEff); } @@ -856,108 +1025,140 @@ void Planner::initializeNextEffects() { } } -void Planner::initializeFact(Position& newPos, const USignature& fact) { +void Planner::initializeFact(Position &newPos, const USignature &fact) +{ assert(!_htn.hasQConstants(fact)); // Has the fact already been defined? -> Not new! - if (_analysis.isInitialized(fact)) return; + if (_analysis.isInitialized(fact)) + return; _analysis.addInitializedFact(fact); - if (_analysis.isReachable(fact, /*negated=*/true)) newPos.addFalseFact(fact); - else newPos.addTrueFact(fact); + if (_analysis.isReachable(fact, /*negated=*/true)) + newPos.addFalseFact(fact); + else + newPos.addTrueFact(fact); } -void Planner::addQConstantTypeConstraints(const USignature& op) { +void Planner::addQConstantTypeConstraints(const USignature &op) +{ // Add type constraints for q constants std::vector cs = _htn.getQConstantTypeConstraints(op); // Add to this position's data structure - for (const TypeConstraint& c : cs) { + for (const TypeConstraint &c : cs) + { (*_layers[_layer_idx])[_pos].addQConstantTypeConstraint(op, c); } } -void Planner::clearDonePositions(int offset) { +void Planner::clearDonePositions(int offset) +{ - Position* positionToClearLeft = nullptr; - if (_pos == 0 && _layer_idx > 0) { - positionToClearLeft = &_layers.at(_layer_idx-1)->last(); - } else if (_pos > 0) positionToClearLeft = &_layers.at(_layer_idx)->at(_pos-1); - if (positionToClearLeft != nullptr) { + Position *positionToClearLeft = nullptr; + if (_pos == 0 && _layer_idx > 0) + { + positionToClearLeft = &_layers.at(_layer_idx - 1)->last(); + } + else if (_pos > 0) + positionToClearLeft = &_layers.at(_layer_idx)->at(_pos - 1); + if (positionToClearLeft != nullptr) + { Log::v(" Freeing some memory of (%i,%i) ...\n", positionToClearLeft->getLayerIndex(), positionToClearLeft->getPositionIndex()); positionToClearLeft->clearAtPastPosition(); } - if (_layer_idx == 0 || offset > 0) return; - - Position* positionToClearAbove = nullptr; - if (_old_pos == 0) { + if (_layer_idx == 0 || offset > 0) + return; + + Position *positionToClearAbove = nullptr; + if (_old_pos == 0) + { // Clear rightmost position of "above above" layer - if (_layer_idx > 1) positionToClearAbove = &_layers.at(_layer_idx-2)->at(_layers.at(_layer_idx-2)->size()-1); - } else { + if (_layer_idx > 1) + positionToClearAbove = &_layers.at(_layer_idx - 2)->at(_layers.at(_layer_idx - 2)->size() - 1); + } + else + { // Clear previous parent position of "above" layer - positionToClearAbove = &_layers.at(_layer_idx-1)->at(_old_pos-1); + positionToClearAbove = &_layers.at(_layer_idx - 1)->at(_old_pos - 1); } - if (positionToClearAbove != nullptr) { + if (positionToClearAbove != nullptr) + { Log::v(" Freeing most memory of (%i,%i) ...\n", positionToClearAbove->getLayerIndex(), positionToClearAbove->getPositionIndex()); positionToClearAbove->clearAtPastLayer(); } } -void Planner::checkTermination() { +void Planner::checkTermination() +{ bool exitSet = SignalManager::isExitSet(); bool cancelOpt = cancelOptimization(); - if (exitSet) { - if (_has_plan) { + if (exitSet) + { + if (_has_plan) + { Log::i("Termination signal caught - printing last found plan.\n"); _plan_writer.outputPlan(_plan); - } else { + } + else + { Log::i("Termination signal caught.\n"); } - } else if (cancelOpt) { + } + else if (cancelOpt) + { Log::i("Cancelling optimization according to provided limit.\n"); _plan_writer.outputPlan(_plan); - } else if (_time_at_first_plan == 0 - && _init_plan_time_limit > 0 - && Timer::elapsedSeconds() > _init_plan_time_limit) { + } + else if (_time_at_first_plan == 0 && _init_plan_time_limit > 0 && Timer::elapsedSeconds() > _init_plan_time_limit) + { Log::i("Time limit to find an initial plan exceeded.\n"); exitSet = true; } - if (exitSet || cancelOpt) { + if (exitSet || cancelOpt) + { printStatistics(); Log::i("Exiting happily.\n"); exit(0); } } -bool Planner::cancelOptimization() { +bool Planner::cancelOptimization() +{ return _time_at_first_plan > 0 && - _optimization_factor > 0 && - Timer::elapsedSeconds() > (1+_optimization_factor) * _time_at_first_plan; + _optimization_factor > 0 && + Timer::elapsedSeconds() > (1 + _optimization_factor) * _time_at_first_plan; } -int Planner::getTerminateSatCall() { +int Planner::getTerminateSatCall() +{ // Breaking out of first SAT call after some time if (_sat_time_limit > 0 && - _enc.getTimeSinceSatCallStart() > _sat_time_limit) { + _enc.getTimeSinceSatCallStart() > _sat_time_limit) + { return 1; } // Termination due to initial planning time limit (-T) if (_time_at_first_plan == 0 && _init_plan_time_limit > 0 && - Timer::elapsedSeconds() > _init_plan_time_limit) { + Timer::elapsedSeconds() > _init_plan_time_limit) + { return 1; } // Plan length optimization limit hit - if (cancelOptimization()) { + if (cancelOptimization()) + { return 1; } // Termination by interruption signal - if (SignalManager::isExitSet()) return 1; + if (SignalManager::isExitSet()) + return 1; return 0; } -void Planner::printStatistics() { +void Planner::printStatistics() +{ _enc.printStatistics(); Log::i("# instantiated positions: %i\n", _num_instantiated_positions); Log::i("# instantiated actions: %i\n", _num_instantiated_actions); diff --git a/src/algo/planner.h b/src/algo/planner.h index ae9ebfc..d83b048 100644 --- a/src/algo/planner.h +++ b/src/algo/planner.h @@ -1,12 +1,13 @@ #ifndef DOMPASCH_TREE_REXX_PLANNER_H #define DOMPASCH_TREE_REXX_PLANNER_H - + #include "util/names.h" #include "util/params.h" #include "util/hashmap.h" #include "data/layer.h" #include "data/htn_instance.h" +#include "data/substitution_constraint.h" #include "algo/instantiator.h" #include "algo/arg_iterator.h" #include "algo/precondition_inference.h" @@ -17,16 +18,21 @@ #include "algo/plan_writer.h" #include "sat/encoding.h" +#include +#include +#include + typedef std::pair, std::vector> Plan; -class Planner { +class Planner +{ public: - typedef std::function StateEvaluator; + typedef std::function StateEvaluator; private: - Parameters& _params; - HtnInstance& _htn; + Parameters &_params; + HtnInstance &_htn; FactAnalysis _analysis; Instantiator _instantiator; @@ -36,7 +42,7 @@ class Planner { DominationResolver _domination_resolver; PlanWriter _plan_writer; - std::vector _layers; + std::vector _layers; size_t _layer_idx; size_t _pos; @@ -57,60 +63,65 @@ class Planner { size_t _num_instantiated_reductions = 0; public: - Planner(Parameters& params, HtnInstance& htn) : _params(params), _htn(htn), - _analysis(_htn), - _instantiator(params, htn, _analysis), - _enc(_params, _htn, _analysis, _layers, [this](){checkTermination();}), - _minres(_htn), - _pruning(_layers, _enc), - _domination_resolver(_htn), - _plan_writer(_htn, _params), - _init_plan_time_limit(_params.getFloatParam("T")), _nonprimitive_support(_params.isNonzero("nps")), - _optimization_factor(_params.getFloatParam("of")), _has_plan(false) { + Planner(Parameters ¶ms, HtnInstance &htn) : _params(params), _htn(htn), + _analysis(_htn), + _instantiator(params, htn, _analysis), + _enc(_params, _htn, _analysis, _layers, [this]() + { checkTermination(); }), + _minres(_htn), + _pruning(_layers, _enc), + _domination_resolver(_htn), + _plan_writer(_htn, _params), + _init_plan_time_limit(_params.getFloatParam("T")), _nonprimitive_support(_params.isNonzero("nps")), + _optimization_factor(_params.getFloatParam("of")), _has_plan(false) + { // Mine additional preconditions for reductions from their subtasks PreconditionInference::infer(_htn, _analysis, PreconditionInference::MinePrecMode(_params.getIntParam("mp"))); } int findPlan(); - void improvePlan(int& iteration); + void improvePlan(int &iteration); - friend int terminateSatCall(void* state); + friend int terminateSatCall(void *state); void checkTermination(); bool cancelOptimization(); private: - void createFirstLayer(); void createNextLayer(); - + void createNextPosition(); void createNextPositionFromAbove(); - void createNextPositionFromLeft(Position& left); + void createNextPositionFromLeft(Position &left); void incrementPosition(); void addPreconditionConstraints(); - void addPreconditionsAndConstraints(const USignature& op, const SigSet& preconditions, bool isActionRepetition); - std::optional addPrecondition(const USignature& op, const Signature& fact, bool addQFact = true); - - enum EffectMode { INDIRECT, DIRECT, DIRECT_NO_QFACT }; - bool addEffect(const USignature& op, const Signature& fact, EffectMode mode); + void addPreconditionsAndConstraints(const USignature &op, const SigSet &preconditions, bool isActionRepetition); + std::optional addPrecondition(const USignature &op, const Signature &fact, bool addQFact = true); + + enum EffectMode + { + INDIRECT, + DIRECT, + DIRECT_NO_QFACT + }; + bool addEffect(const USignature &op, const Signature &fact, EffectMode mode); - std::optional createValidReduction(const USignature& rSig, const USignature& task); + std::optional createValidReduction(const USignature &rSig, const USignature &task); void propagateInitialState(); void propagateActions(size_t offset); void propagateReductions(size_t offset); - std::vector instantiateAllActionsOfTask(const USignature& task); - std::vector instantiateAllReductionsOfTask(const USignature& task); + std::vector instantiateAllActionsOfTask(const USignature &task); + std::vector instantiateAllReductionsOfTask(const USignature &task); void initializeNextEffects(); - void initializeFact(Position& newPos, const USignature& fact); - void addQConstantTypeConstraints(const USignature& op); + void initializeFact(Position &newPos, const USignature &fact); + void addQConstantTypeConstraints(const USignature &op); int getTerminateSatCall(); void clearDonePositions(int offset); void printStatistics(); - }; #endif \ No newline at end of file diff --git a/src/algo/sample_arg_iterator.h b/src/algo/sample_arg_iterator.h index e960298..8b4b94b 100644 --- a/src/algo/sample_arg_iterator.h +++ b/src/algo/sample_arg_iterator.h @@ -2,6 +2,7 @@ #ifndef DOMPASCH_TREE_REXX_SAMPLE_ARG_ITERATOR_H #define DOMPASCH_TREE_REXX_SAMPLE_ARG_ITERATOR_H +#include #include #include "util/hashmap.h" @@ -11,57 +12,66 @@ class HtnInstance; -class SampleArgIterator { +class SampleArgIterator +{ private: - - std::vector> _eligible_args; + std::vector> _eligible_args; size_t _num_samples; - struct It { + struct It + { int _sig_id; - const std::vector>& _eligible_args; + const std::vector> &_eligible_args; size_t _num_samples; USignature _usig; - It(int sigId, const std::vector>& eligibleArgs, size_t numSamples) - : _sig_id(sigId), _eligible_args(eligibleArgs), _num_samples(numSamples), - _usig(_sig_id, std::vector(eligibleArgs.size())) { - + It(int sigId, const std::vector> &eligibleArgs, size_t numSamples) + : _sig_id(sigId), _eligible_args(eligibleArgs), _num_samples(numSamples), + _usig(_sig_id, std::basic_string(eligibleArgs.size(), 0)) + { + setRandom(); } - const USignature& operator*() { + const USignature &operator*() + { return _usig; } - const USignature& operator++() { + const USignature &operator++() + { setRandom(); _num_samples--; return _usig; } - bool operator==(const It& other) const { + bool operator==(const It &other) const + { return _num_samples == other._num_samples; } - bool operator!=(const It& other) const { + bool operator!=(const It &other) const + { return !(*this == other); } - private: - void setRandom() { + private: + void setRandom() + { size_t totalSize = 1; - for (const auto& args : _eligible_args) totalSize *= args.size(); - //Log::d("total size %i\n", totalSize); - size_t randomIdx = (int) (totalSize * Random::rand()); - //Log::d("random idx %i\n", randomIdx); - + for (const auto &args : _eligible_args) + totalSize *= args.size(); + // Log::d("total size %i\n", totalSize); + size_t randomIdx = (int)(totalSize * Random::rand()); + // Log::d("random idx %i\n", randomIdx); + size_t factor = totalSize; - for (size_t i = 0; i < _eligible_args.size(); i++) { + for (size_t i = 0; i < _eligible_args.size(); i++) + { size_t size = _eligible_args[i].size(); factor /= size; size_t idx = randomIdx / factor; - //Log::d("i=%i size=%i random_idx=%i factor=%i idx=%i\n", i, size, randomIdx, factor, idx); + // Log::d("i=%i size=%i random_idx=%i factor=%i idx=%i\n", i, size, randomIdx, factor, idx); assert(idx < size); _usig._args[i] = _eligible_args[i][idx]; randomIdx -= idx * factor; @@ -72,22 +82,24 @@ class SampleArgIterator { } _begin, _end; public: + SampleArgIterator(int sigId, std::vector> &&eligibleArgs, size_t numSamples) : _eligible_args(std::move(eligibleArgs)), _num_samples(numSamples), + _begin(sigId, _eligible_args, _num_samples), + _end(sigId, _eligible_args, _num_samples) + { - SampleArgIterator(int sigId, std::vector>&& eligibleArgs, size_t numSamples) : - _eligible_args(std::move(eligibleArgs)), _num_samples(numSamples), - _begin(sigId, _eligible_args, _num_samples), - _end(sigId, _eligible_args, _num_samples) { - size_t numChoices = _eligible_args.empty() ? 0 : 1; - for (const auto& args : _eligible_args) numChoices *= args.size(); + for (const auto &args : _eligible_args) + numChoices *= args.size(); _end._num_samples = 0; } - It begin() const { + It begin() const + { return _begin; } - It end() const { + It end() const + { return _end; } }; diff --git a/src/data/action.cpp b/src/data/action.cpp index c66f19d..bfbeccc 100644 --- a/src/data/action.cpp +++ b/src/data/action.cpp @@ -2,16 +2,18 @@ #include "action.h" Action::Action() : HtnOp() {} -Action::Action(const HtnOp& op) : HtnOp(op) {} -Action::Action(const Action& a) : HtnOp(a._id, a._args) { +Action::Action(const HtnOp &op) : HtnOp(op) {} +Action::Action(const Action &a) : HtnOp(a._id, a._args) +{ _preconditions = a._preconditions; _extra_preconditions = a._extra_preconditions; _effects = a._effects; } -Action::Action(int nameId, const std::vector& args) : HtnOp(nameId, args) {} -Action::Action(int nameId, std::vector&& args) : HtnOp(nameId, std::move(args)) {} +Action::Action(int nameId, const std::basic_string &args) : HtnOp(nameId, args) {} +Action::Action(int nameId, std::basic_string &&args) : HtnOp(nameId, std::move(args)) {} -Action& Action::operator=(const Action& op) { +Action &Action::operator=(const Action &op) +{ _id = op._id; _args = op._args; _preconditions = op._preconditions; diff --git a/src/data/action.h b/src/data/action.h index 0cb41f6..6be826d 100644 --- a/src/data/action.h +++ b/src/data/action.h @@ -2,22 +2,24 @@ #ifndef DOMPASCH_TREE_REXX_ACTION_H #define DOMPASCH_TREE_REXX_ACTION_H +#include #include #include "util/hashmap.h" #include "data/htn_op.h" #include "data/signature.h" -class Action : public HtnOp { - +class Action : public HtnOp +{ + public: Action(); - Action(const HtnOp& op); - Action(const Action& a); - Action(int nameId, const std::vector& args); - Action(int nameId, std::vector&& args); + Action(const HtnOp &op); + Action(const Action &a); + Action(int nameId, const std::basic_string &args); + Action(int nameId, std::basic_string &&args); - Action& operator=(const Action& op); + Action &operator=(const Action &op); }; #endif \ No newline at end of file diff --git a/src/data/htn_instance.cpp b/src/data/htn_instance.cpp index 7bacd6f..db0a037 100644 --- a/src/data/htn_instance.cpp +++ b/src/data/htn_instance.cpp @@ -11,9 +11,9 @@ Action HtnInstance::BLANK_ACTION; -HtnInstance::HtnInstance(Parameters& params) : - _params(params), _p(*parse(params.getDomainFilename(), params.getProblemFilename())), - _share_q_constants(_params.isNonzero("sqq")) { +HtnInstance::HtnInstance(Parameters ¶ms) : _params(params), _p(*parse(params.getDomainFilename(), params.getProblemFilename())), + _share_q_constants(_params.isNonzero("sqq")) +{ // Transfer random seed to the hash function for any kind of signature USignatureHasher::seed = _params.getIntParam("s"); @@ -21,84 +21,94 @@ HtnInstance::HtnInstance(Parameters& params) : Log::i("Parser finished.\n"); Names::init(_name_back_table); - + // Create blank action without any preconditions or effects int blankId = nameId("__BLANK___"); - BLANK_ACTION = Action(blankId, std::vector()); + BLANK_ACTION = Action(blankId, {}); _operators[blankId] = BLANK_ACTION; _op_table.addAction(BLANK_ACTION); _blank_action_sig = BLANK_ACTION.getSignature(); _signature_sorts_table[blankId]; - for (const predicate_definition& p : predicate_definitions) + for (const predicate_definition &p : predicate_definitions) extractPredSorts(p); - for (const task& t : primitive_tasks) + for (const task &t : primitive_tasks) extractTaskSorts(t); - for (const task& t : abstract_tasks) + for (const task &t : abstract_tasks) extractTaskSorts(t); - for (const method& m : methods) + for (const method &m : methods) extractMethodSorts(m); - + extractConstants(); Log::i("Structures extracted.\n"); - for (const auto& sort_pair : _p.sorts) { + for (const auto &sort_pair : _p.sorts) + { Log::d(" %s : ", sort_pair.first.c_str()); - for (const std::string& c : sort_pair.second) { + for (const std::string &c : sort_pair.second) + { Log::d("%s ", c.c_str()); } Log::d("\n"); } // Create actions - for (const task& t : primitive_tasks) { + for (const task &t : primitive_tasks) + { createAction(t); } // Create reductions - for (method& method : methods) { + for (method &method : methods) + { createReduction(method); } - if (_params.isNonzero("stats")) { + if (_params.isNonzero("stats")) + { printStatistics(); exit(0); } // Create replacements for simple methods with only one subtask - if (_params.isNonzero("psr")) primitivizeSimpleReductions(); + if (_params.isNonzero("psr")) + primitivizeSimpleReductions(); Log::i("%i operators and %i methods created.\n", _operators.size(), _methods.size()); } -ParsedProblem* HtnInstance::parse(std::string domainFile, std::string problemFile) { +ParsedProblem *HtnInstance::parse(std::string domainFile, std::string problemFile) +{ - const char* firstArg = "pandaPIparser"; - const char* domainStr = domainFile.c_str(); - const char* problemStr = problemFile.c_str(); + const char *firstArg = "pandaPIparser"; + const char *domainStr = domainFile.c_str(); + const char *problemStr = problemFile.c_str(); struct stat sb; - if (stat(domainStr, &sb) != 0 || !S_ISREG(sb.st_mode)) { + if (stat(domainStr, &sb) != 0 || !S_ISREG(sb.st_mode)) + { Log::e("Domain file \"%s\" is not a regular file. Exiting.\n", domainStr); exit(1); } - if (stat(problemStr, &sb) != 0 || !S_ISREG(sb.st_mode)) { + if (stat(problemStr, &sb) != 0 || !S_ISREG(sb.st_mode)) + { Log::e("Problem file \"%s\" is not a regular file. Exiting.\n", problemStr); exit(1); } - char* args[3]; - args[0] = (char*)firstArg; - args[1] = (char*)domainStr; - args[2] = (char*)problemStr; + char *args[3]; + args[0] = (char *)firstArg; + args[1] = (char *)domainStr; + args[2] = (char *)problemStr; - ParsedProblem* p = new ParsedProblem(); + ParsedProblem *p = new ParsedProblem(); optind = 1; run_pandaPIparser(3, args, *p); return p; } -void HtnInstance::printStatistics() { +void HtnInstance::printStatistics() +{ static size_t BIG = 999999UL; size_t maxPredicateArity = 0; @@ -106,21 +116,23 @@ void HtnInstance::printStatistics() { size_t minExpansionSize = BIG; size_t maxExpansionSize = 0; size_t maxLiftedBranchingFactor = 0; - + size_t maxReductionPreconditions = 0; size_t maxReductionArity = 0; size_t maxReductionFreeArgs = 0; - + size_t maxActionPreconditions = 0; size_t maxActionEffects = 0; size_t maxActionArity = 0; - for (auto predId : _predicate_ids) { + for (auto predId : _predicate_ids) + { maxPredicateArity = std::max(maxPredicateArity, _signature_sorts_table[predId].size()); } FlatHashMap numMethodsMatchingTaskNameId; - for (const auto& [nameId, r] : _methods) { + for (const auto &[nameId, r] : _methods) + { if (_name_back_table[r.getNameId()].rfind("__top_method") == 0) continue; minExpansionSize = std::min(minExpansionSize, r.getSubtasks().size()); @@ -128,24 +140,28 @@ void HtnInstance::printStatistics() { maxReductionPreconditions = std::max(maxReductionPreconditions, r.getPreconditions().size()); maxReductionArity = std::max(maxReductionArity, r.getArguments().size()); maxReductionFreeArgs = std::max(maxReductionFreeArgs, getNumFreeArguments(r)); - + int taskNameId = r.getTaskSignature()._name_id; - if (!numMethodsMatchingTaskNameId.count(taskNameId)) + if (!numMethodsMatchingTaskNameId.count(taskNameId)) numMethodsMatchingTaskNameId[taskNameId] = 1; - else numMethodsMatchingTaskNameId[taskNameId]++; + else + numMethodsMatchingTaskNameId[taskNameId]++; } - for (const auto& [nameId, a] : _operators) { + for (const auto &[nameId, a] : _operators) + { maxActionPreconditions = std::max(maxActionPreconditions, a.getPreconditions().size()); maxActionEffects = std::max(maxActionEffects, a.getEffects().size()); maxActionArity = std::max(maxActionArity, a.getArguments().size()); } - for (const auto& [taskNameId, numMethods] : numMethodsMatchingTaskNameId) { + for (const auto &[taskNameId, numMethods] : numMethodsMatchingTaskNameId) + { maxLiftedBranchingFactor = std::max(maxLiftedBranchingFactor, numMethods); } FlatHashSet allConstants; - for (const auto& [sort, constants] : _constants_by_sort) { + for (const auto &[sort, constants] : _constants_by_sort) + { allConstants.insert(constants.begin(), constants.end()); } int initStateSize = getInitState().size(); @@ -153,20 +169,20 @@ void HtnInstance::printStatistics() { Log::e("Domain stats:\n"); - Log::e("STATS numoperators %lu\n", _operators.size()-1); // minus blank action - Log::e("STATS nummethods %lu\n", _methods.size()-1); // minus __top_method - + Log::e("STATS numoperators %lu\n", _operators.size() - 1); // minus blank action + Log::e("STATS nummethods %lu\n", _methods.size() - 1); // minus __top_method + Log::e("STATS maxexpansionsize %lu\n", maxExpansionSize); Log::e("STATS maxliftedbranchingfactor %lu\n", maxLiftedBranchingFactor); Log::e("STATS maxreductionfreeargs %lu\n", maxReductionFreeArgs); - + Log::e("STATS maxactionpreconditions %lu\n", maxActionPreconditions); Log::e("STATS maxreductionpreconditions %lu\n", maxReductionPreconditions); Log::e("STATS maxactioneffects %lu\n", maxActionEffects); - - Log::e("STATS maxpredicatearity %lu\n", maxPredicateArity); + + Log::e("STATS maxpredicatearity %lu\n", maxPredicateArity); Log::e("STATS maxactionarity %lu\n", maxActionArity); - Log::e("STATS maxreductionarity %lu\n", maxReductionArity); + Log::e("STATS maxreductionarity %lu\n", maxReductionArity); Log::e("Problem stats:\n"); @@ -175,14 +191,18 @@ void HtnInstance::printStatistics() { Log::e("STATS numinittasks %lu\n", numInitTasks); } -size_t HtnInstance::getNumFreeArguments(const Reduction& r) { +size_t HtnInstance::getNumFreeArguments(const Reduction &r) +{ size_t freeArgs = 0; - for (size_t i = 0; i < r.getArguments().size(); i++) { + for (size_t i = 0; i < r.getArguments().size(); i++) + { int arg = r.getArguments()[i]; - if (std::find(r.getTaskArguments().begin(), r.getTaskArguments().end(), arg) == r.getTaskArguments().end()) { + if (std::find(r.getTaskArguments().begin(), r.getTaskArguments().end(), arg) == r.getTaskArguments().end()) + { // Argument is not contained in task arguments: Free variable int sort = _signature_sorts_table[r.getSignature()._name_id][i]; - if (_constants_by_sort[sort].size() > 1) { + if (_constants_by_sort[sort].size() > 1) + { // Argument has a non-trivial domain freeArgs++; } @@ -191,17 +211,21 @@ size_t HtnInstance::getNumFreeArguments(const Reduction& r) { return freeArgs; } -void HtnInstance::primitivizeSimpleReductions() { +void HtnInstance::primitivizeSimpleReductions() +{ + + for (const auto &entry : _methods) + { + const Reduction &red = entry.second; + if (red.getSubtasks().size() != 1) + continue; - for (const auto& entry : _methods) { - const Reduction& red = entry.second; - if (red.getSubtasks().size() != 1) continue; - // Single-subtask method USignature childSig = red.getSubtasks().at(0); int childId = childSig._name_id; - if (!_operators.count(childId)) continue; - + if (!_operators.count(childId)) + continue; + // Primitive subtask Substitution s(_operators.at(childId).getArguments(), childSig._args); Action childAct = _operators.at(childId).substitute(s); @@ -209,27 +233,38 @@ void HtnInstance::primitivizeSimpleReductions() { int id = nameId(name); Log::d("SURROGATE %s %i\n", name.c_str(), entry.first); _operators[id] = Action(id, red.getArguments()); - for (const auto& pre : red.getPreconditions()) _operators[id].addPrecondition(pre); - for (const auto& pre : red.getExtraPreconditions()) _operators[id].addExtraPrecondition(pre); - for (const auto& pre : childAct.getPreconditions()) _operators[id].addPrecondition(pre); - for (const auto& pre : childAct.getExtraPreconditions()) _operators[id].addExtraPrecondition(pre); - for (const auto& eff : childAct.getEffects()) _operators[id].addEffect(eff); + for (const auto &pre : red.getPreconditions()) + _operators[id].addPrecondition(pre); + for (const auto &pre : red.getExtraPreconditions()) + _operators[id].addExtraPrecondition(pre); + for (const auto &pre : childAct.getPreconditions()) + _operators[id].addPrecondition(pre); + for (const auto &pre : childAct.getExtraPreconditions()) + _operators[id].addExtraPrecondition(pre); + for (const auto &eff : childAct.getEffects()) + _operators[id].addEffect(eff); _reduction_to_primitivization[entry.first] = id; _signature_sorts_table[id] = _signature_sorts_table[entry.first]; _primitivization_to_parent_and_child[id] = std::pair(entry.first, childId); } } -int HtnInstance::nameId(const std::string& name, bool createQConstant, int layerIdx, int pos) { +int HtnInstance::nameId(const std::string &name, bool createQConstant, int layerIdx, int pos) +{ int id = -1; - if (!_name_table.count(name)) { - if (createQConstant) { + if (!_name_table.count(name)) + { + if (createQConstant) + { id = std::numeric_limits::max() - _q_constants_with_origin.size(); assert(layerIdx >= 0 && pos >= 0); _q_constants_with_origin[id] = IntPair(layerIdx, pos); - } else { + } + else + { id = _name_table_running_id++; - if (name[0] == '?') { + if (name[0] == '?') + { // variable _var_ids.insert(id); } @@ -240,60 +275,77 @@ int HtnInstance::nameId(const std::string& name, bool createQConstant, int layer return id == -1 ? _name_table[name] : id; } -std::string HtnInstance::toString(int id) const { +std::string HtnInstance::toString(int id) const +{ return _name_back_table.at(id); } -std::vector HtnInstance::convertArguments(int predNameId, const std::vector>& vars) { - std::vector args; - for (const auto& var : vars) { +std::basic_string HtnInstance::convertArguments(int predNameId, const std::vector> &vars) +{ + std::basic_string args; + for (const auto &var : vars) + { int id = var.first[0] == '?' ? nameId(var.first + "_" + std::to_string(predNameId)) : nameId(var.first); args.push_back(id); } return args; } -std::vector HtnInstance::convertArguments(int predNameId, const std::vector& vars) { - std::vector args; - for (const auto& var : vars) { +std::basic_string HtnInstance::convertArguments(int predNameId, const std::vector &vars) +{ + std::basic_string args; + for (const auto &var : vars) + { int id = var[0] == '?' ? nameId(var + "_" + std::to_string(predNameId)) : nameId(var); args.push_back(id); } return args; } -USignature HtnInstance::convertSignature(const task& task) { +USignature HtnInstance::convertSignature(const task &task) +{ return USignature(nameId(task.name), convertArguments(nameId(task.name), task.vars)); } -USignature HtnInstance::convertSignature(const method& method) { +USignature HtnInstance::convertSignature(const method &method) +{ return USignature(nameId(method.name), convertArguments(nameId(method.name), method.vars)); } -Signature HtnInstance::convertSignature(int parentNameId, const literal& literal) { +Signature HtnInstance::convertSignature(int parentNameId, const literal &literal) +{ Signature sig = Signature(nameId(literal.predicate), convertArguments(parentNameId, literal.arguments)); - if (!literal.positive) sig.negate(); + if (!literal.positive) + sig.negate(); return sig; } -USigSet HtnInstance::getInitState() { +USigSet HtnInstance::getInitState() +{ USigSet result; - for (const ground_literal& lit : _p.init) if (lit.positive) { - result.emplace(nameId(lit.predicate), convertArguments(nameId(lit.predicate), lit.args)); - } + for (const ground_literal &lit : _p.init) + if (lit.positive) + { + result.emplace(nameId(lit.predicate), convertArguments(nameId(lit.predicate), lit.args)); + } // Insert all necessary equality predicates // For each equality predicate: - for (int eqPredId : _equality_predicates) { + for (int eqPredId : _equality_predicates) + { // For each pair of constants of correct sorts: TODO something more efficient - const std::vector& sorts = getSorts(eqPredId); + const std::basic_string &sorts = getSorts(eqPredId); assert(sorts[0] == sorts[1]); - for (int c1 : _constants_by_sort[sorts[0]]) { - for (int c2 : _constants_by_sort[sorts[1]]) { + for (int c1 : _constants_by_sort[sorts[0]]) + { + for (int c2 : _constants_by_sort[sorts[1]]) + { // Add equality lit to state if the two are equal - if (c1 != c2) continue; - std::vector args; - args.push_back(c1); args.push_back(c2); + if (c1 != c2) + continue; + std::basic_string args; + args.push_back(c1); + args.push_back(c2); Log::d("EQUALITY %s\n", TOSTR(args)); result.emplace(eqPredId, std::move(args)); } @@ -303,24 +355,29 @@ USigSet HtnInstance::getInitState() { return result; } -SigSet HtnInstance::extractGoals() { +SigSet HtnInstance::extractGoals() +{ SigSet result; - for (const ground_literal& lit : _p.goal) { + for (const ground_literal &lit : _p.goal) + { Signature sig(nameId(lit.predicate), convertArguments(nameId(lit.predicate), lit.args)); - if (!lit.positive) sig.negate(); + if (!lit.positive) + sig.negate(); result.insert(sig); } return result; } -Action HtnInstance::getGoalAction() { +Action HtnInstance::getGoalAction() +{ // Create virtual goal action - Action goalAction(nameId(""), std::vector()); + Action goalAction(nameId(""), {}); USignature goalSig = goalAction.getSignature(); - + // Extract primitive goals, add to preconds of goal action - for (Signature& fact : extractGoals()) { + for (Signature &fact : extractGoals()) + { goalAction.addPrecondition(std::move(fact)); } _op_table.addAction(goalAction); @@ -330,11 +387,14 @@ Action HtnInstance::getGoalAction() { return goalAction; } -const Reduction& HtnInstance::getInitReduction() { +const Reduction &HtnInstance::getInitReduction() +{ // Instantiate possible "root" / "top" methods - for (const auto& rPair : _methods) { - const Reduction& r = rPair.second; - if (_name_back_table[r.getNameId()].rfind("__top_method") == 0) { + for (const auto &rPair : _methods) + { + const Reduction &r = rPair.second; + if (_name_back_table[r.getNameId()].rfind("__top_method") == 0) + { // Initial "top" method _init_reduction = r; } @@ -342,24 +402,29 @@ const Reduction& HtnInstance::getInitReduction() { return _init_reduction; } -const USignature& HtnInstance::getBlankActionSig() { +const USignature &HtnInstance::getBlankActionSig() +{ return _blank_action_sig; } -void HtnInstance::extractPredSorts(const predicate_definition& p) { +void HtnInstance::extractPredSorts(const predicate_definition &p) +{ int pId = nameId(p.name); _predicate_ids.insert(pId); - std::vector sorts; - for (const std::string& var : p.argument_sorts) { + std::basic_string sorts; + for (const std::string &var : p.argument_sorts) + { sorts.push_back(nameId(var)); } assert(!_signature_sorts_table.count(pId)); _signature_sorts_table[pId] = std::move(sorts); } -void HtnInstance::extractTaskSorts(const task& t) { - std::vector sorts; - for (const auto& var : t.vars) { +void HtnInstance::extractTaskSorts(const task &t) +{ + std::basic_string sorts; + for (const auto &var : t.vars) + { int sortId = nameId(var.second); sorts.push_back(sortId); } @@ -369,9 +434,11 @@ void HtnInstance::extractTaskSorts(const task& t) { _original_n_taskvars[tId] = t.number_of_original_vars; } -void HtnInstance::extractMethodSorts(const method& m) { - std::vector sorts; - for (const auto& var : m.vars) { +void HtnInstance::extractMethodSorts(const method &m) +{ + std::basic_string sorts; + for (const auto &var : m.vars) + { int sortId = nameId(var.second); sorts.push_back(sortId); } @@ -380,67 +447,77 @@ void HtnInstance::extractMethodSorts(const method& m) { _signature_sorts_table[mId] = std::move(sorts); } -void HtnInstance::extractConstants() { - for (const auto& sortPair : _p.sorts) { +void HtnInstance::extractConstants() +{ + for (const auto &sortPair : _p.sorts) + { int sortId = nameId(sortPair.first); _constants_by_sort[sortId]; - FlatHashSet& constants = _constants_by_sort[sortId]; - for (const std::string& c : sortPair.second) { + FlatHashSet &constants = _constants_by_sort[sortId]; + for (const std::string &c : sortPair.second) + { constants.insert(nameId(c)); - //log("constant %s of sort %s\n", c.c_str(), sortPair.first.c_str()); + // log("constant %s of sort %s\n", c.c_str(), sortPair.first.c_str()); } } } -Reduction& HtnInstance::createReduction(method& method) { +Reduction &HtnInstance::createReduction(method &method) +{ int id = nameId(method.name); - std::vector args = convertArguments(id, method.vars); - + std::basic_string args = convertArguments(id, method.vars); + int taskId = nameId(method.at); _task_id_to_reduction_ids[taskId]; _task_id_to_reduction_ids[taskId].push_back(id); { - std::vector taskArgs = convertArguments(id, method.atargs); + std::basic_string taskArgs = convertArguments(id, method.atargs); assert(_methods.count(id) == 0); _methods[id] = Reduction(id, args, USignature(taskId, std::move(taskArgs))); } - Reduction& r = _methods[id]; + Reduction &r = _methods[id]; std::vector condLiterals; - // Extract (in)equality constraints, put into preconditions to process later - for (const literal& lit : method.constraints) { + // Extract (in)equality constraints, put into preconditions to process later + for (const literal &lit : method.constraints) + { assert(lit.predicate == "__equal" || Log::e("Unknown constraint predicate \"%s\"!\n", lit.predicate.c_str())); condLiterals.push_back(lit); } // Go through expansion of the method - std::map subtaskTagToIndex; - for (const plan_step& st : method.ps) { - + std::map subtaskTagToIndex; + for (const plan_step &st : method.ps) + { + // Normalize task name std::string subtaskName = st.task; Regex::extractCoreNameOfSplittingMethod(subtaskName); Log::d("%s\n", subtaskName.c_str()); - if (subtaskName.rfind(method_precondition_action_name) != std::string::npos) { + if (subtaskName.rfind(method_precondition_action_name) != std::string::npos) + { // This "subtask" is a method precondition which was compiled out - + // Find primitive task belonging to this method precondition task precTask; size_t maxSize = 0; int numFound = 0; - for (const task& t : primitive_tasks) { - + for (const task &t : primitive_tasks) + { + // Normalize task name std::string taskName = t.name; Regex::extractCoreNameOfSplittingMethod(taskName); - //Log::d(" ~~~ %s\n", taskName.c_str()); - if (subtaskName.rfind(taskName) != std::string::npos) { + // Log::d(" ~~~ %s\n", taskName.c_str()); + if (subtaskName.rfind(taskName) != std::string::npos) + { size_t size = t.name.size(); - if (size < maxSize) continue; + if (size < maxSize) + continue; maxSize = size; numFound++; @@ -449,19 +526,24 @@ Reduction& HtnInstance::createReduction(method& method) { } assert(numFound >= 1); Log::d("- Using %i preconds of prim. task %s as preconds of method %s\n", - precTask.prec.size() + precTask.constraints.size(), precTask.name.c_str(), st.task.c_str()); + precTask.prec.size() + precTask.constraints.size(), precTask.name.c_str(), st.task.c_str()); // Add its preconditions to the method's preconditions - for (const literal& lit : precTask.prec) condLiterals.push_back(lit); - for (const literal& lit : precTask.constraints) condLiterals.push_back(lit); + for (const literal &lit : precTask.prec) + condLiterals.push_back(lit); + for (const literal &lit : precTask.constraints) + condLiterals.push_back(lit); // If necessary, (re-)add parameters of the method precondition task - for (const auto& varPair : precTask.vars) { - - if (varPair.first[0] != '?') continue; // not a variable + for (const auto &varPair : precTask.vars) + { + + if (varPair.first[0] != '?') + continue; // not a variable int varId = nameId(varPair.first + "_" + std::to_string(id)); - if (std::find(args.begin(), args.end(), varId) == args.end()) { + if (std::find(args.begin(), args.end(), varId) == args.end()) + { // Arg is not contained, must be added r.addArgument(varId); args = r.getArguments(); @@ -471,8 +553,9 @@ Reduction& HtnInstance::createReduction(method& method) { } // (Do not add the task to the method's subtasks) - - } else { + } + else + { // Actual subtask _methods[id].addSubtask(USignature(nameId(st.task), convertArguments(id, st.args))); subtaskTagToIndex[st.id] = subtaskTagToIndex.size(); @@ -480,21 +563,25 @@ Reduction& HtnInstance::createReduction(method& method) { } // Process constraints of the method - for (auto& pre : extractEqualityConstraints(id, condLiterals, method.vars)) + for (auto &pre : extractEqualityConstraints(id, condLiterals, method.vars)) _methods[id].addPrecondition(std::move(pre)); // Process preconditions of the method - for (const literal& lit : condLiterals) { - if (lit.predicate == dummy_equal_literal) continue; + for (const literal &lit : condLiterals) + { + if (lit.predicate == dummy_equal_literal) + continue; // Normal precondition _methods[id].addPrecondition(convertSignature(id, lit)); } // Order subtasks - if (!method.ordering.empty()) { + if (!method.ordering.empty()) + { std::map> orderingNodelist; - for (const auto& order : method.ordering) { + for (const auto &order : method.ordering) + { size_t indexLeft = subtaskTagToIndex[order.first]; size_t indexRight = subtaskTagToIndex[order.second]; assert(indexLeft < _methods[id].getSubtasks().size()); @@ -505,11 +592,12 @@ Reduction& HtnInstance::createReduction(method& method) { _methods[id].orderSubtasks(orderingNodelist); } - Log::d(" %s : %i preconditions, %i subtasks\n", TOSTR(_methods[id].getSignature()), - _methods[id].getPreconditions().size(), - _methods[id].getSubtasks().size()); + Log::d(" %s : %i preconditions, %i subtasks\n", TOSTR(_methods[id].getSignature()), + _methods[id].getPreconditions().size(), + _methods[id].getSubtasks().size()); Log::d(" PRE "); - for (const Signature& sig : r.getPreconditions()) { + for (const Signature &sig : r.getPreconditions()) + { Log::log_notime(Log::V4_DEBUG, "%s ", TOSTR(sig)); } Log::log_notime(Log::V4_DEBUG, "\n"); @@ -517,55 +605,62 @@ Reduction& HtnInstance::createReduction(method& method) { return _methods[id]; } -Action& HtnInstance::createAction(const task& task) { +Action &HtnInstance::createAction(const task &task) +{ int id = nameId(task.name); - std::vector args = convertArguments(id, task.vars); + std::basic_string args = convertArguments(id, task.vars); assert(_operators.count(id) == 0); _operators[id] = Action(id, std::move(args)); // Process (equality) constraints - for (auto& pre : extractEqualityConstraints(id, task.constraints, task.vars)) + for (auto &pre : extractEqualityConstraints(id, task.constraints, task.vars)) _operators[id].addPrecondition(std::move(pre)); - for (auto& pre : extractEqualityConstraints(id, task.prec, task.vars)) + for (auto &pre : extractEqualityConstraints(id, task.prec, task.vars)) _operators[id].addPrecondition(std::move(pre)); // Process preconditions - for (const auto& p : task.prec) { + for (const auto &p : task.prec) + { _operators[id].addPrecondition(convertSignature(id, p)); } - for (const auto& p : task.eff) { + for (const auto &p : task.eff) + { _operators[id].addEffect(convertSignature(id, p)); } _operators[id].removeInconsistentEffects(); return _operators[id]; } -SigSet HtnInstance::extractEqualityConstraints(int opId, const std::vector& lits, const std::vector>& vars) { +SigSet HtnInstance::extractEqualityConstraints(int opId, const std::vector &lits, const std::vector> &vars) +{ SigSet result; - for (const literal& lit : lits) { + for (const literal &lit : lits) + { - //Log::d("( %s ", lit.predicate.c_str()); - //for (std::string arg : lit.arguments) Log::d("%s ", arg.c_str()); - //Log::d(")\n"); + // Log::d("( %s ", lit.predicate.c_str()); + // for (std::string arg : lit.arguments) Log::d("%s ", arg.c_str()); + // Log::d(")\n"); - if (lit.predicate == dummy_equal_literal) { + if (lit.predicate == dummy_equal_literal) + { // Equality precondition // Find out "type" of this equality predicate std::string arg1Str = lit.arguments[0]; std::string arg2Str = lit.arguments[1]; - //Log::d("%s,%s :: ", arg1Str.c_str(), arg2Str.c_str()); + // Log::d("%s,%s :: ", arg1Str.c_str(), arg2Str.c_str()); int sort1 = -1, sort2 = -1; - for (size_t argPos = 0; argPos < vars.size(); argPos++) { - //Log::d("(%s,%s) ", method.vars[argPos].first.c_str(), method.vars[argPos].second.c_str()); + for (size_t argPos = 0; argPos < vars.size(); argPos++) + { + // Log::d("(%s,%s) ", method.vars[argPos].first.c_str(), method.vars[argPos].second.c_str()); if (arg1Str == vars[argPos].first) sort1 = nameId(vars[argPos].second); if (arg2Str == vars[argPos].first) sort2 = nameId(vars[argPos].second); } - //log("\n"); + // log("\n"); assert(sort1 >= 0 && sort2 >= 0); // Use the "larger" sort as the sort for both argument positions int eqSort = (_constants_by_sort[sort1].size() > _constants_by_sort[sort2].size() ? sort1 : sort2); @@ -573,16 +668,17 @@ SigSet HtnInstance::extractEqualityConstraints(int opId, const std::vector(2, eqSort); + _signature_sorts_table[newPredId] = std::basic_string(2, eqSort); _equality_predicates.insert(newPredId); _predicate_ids.insert(newPredId); } // Add as a precondition - std::vector args(2); - args[0] = nameId(arg1Str + "_" + std::to_string(opId)); + std::basic_string args(2, 0); + args[0] = nameId(arg1Str + "_" + std::to_string(opId)); args[1] = nameId(arg2Str + "_" + std::to_string(opId)); result.emplace(newPredId, std::move(args), !lit.positive); } @@ -591,61 +687,75 @@ SigSet HtnInstance::extractEqualityConstraints(int opId, const std::vectorsecond; - else return (HtnOp&)_methods.at(opSig._name_id); + if (it != _operators.end()) + return (HtnOp &)it->second; + else + return (HtnOp &)_methods.at(opSig._name_id); } -const Action& HtnInstance::getActionTemplate(int nameId) const { +const Action &HtnInstance::getActionTemplate(int nameId) const +{ return _operators.at(nameId); } -const Reduction& HtnInstance::getReductionTemplate(int nameId) const { +const Reduction &HtnInstance::getReductionTemplate(int nameId) const +{ return _methods.at(nameId); } -bool HtnInstance::hasReductions(int taskId) const { +bool HtnInstance::hasReductions(int taskId) const +{ return _task_id_to_reduction_ids.count(taskId); } -const std::vector& HtnInstance::getReductionIdsOfTaskId(int taskId) const { +const std::vector &HtnInstance::getReductionIdsOfTaskId(int taskId) const +{ return _task_id_to_reduction_ids.at(taskId); } -bool HtnInstance::isReductionPrimitivizable(int reductionId) const { +bool HtnInstance::isReductionPrimitivizable(int reductionId) const +{ return _reduction_to_primitivization.count(reductionId); } -const Action& HtnInstance::getReductionPrimitivization(int reductionId) const { +const Action &HtnInstance::getReductionPrimitivization(int reductionId) const +{ return _operators.at(_reduction_to_primitivization.at(reductionId)); } -bool HtnInstance::isActionRepetition(int actionId) const { +bool HtnInstance::isActionRepetition(int actionId) const +{ return _repeated_to_actual_action.count(actionId); } -int HtnInstance::getRepetitionNameOfAction(int actionId) { +int HtnInstance::getRepetitionNameOfAction(int actionId) +{ return nameId("__REPEATED_" + _name_back_table[actionId]); } -USignature HtnInstance::getRepetitionOfAction(const USignature& action) { +USignature HtnInstance::getRepetitionOfAction(const USignature &action) +{ int repOpNameId = getRepetitionNameOfAction(action._name_id); USignature sig(repOpNameId, action._args); - if (!_op_table.hasAction(sig)) { + if (!_op_table.hasAction(sig)) + { // Define the operator - if (!_operators.count(repOpNameId)) { - const Action& op = _operators[action._name_id]; + if (!_operators.count(repOpNameId)) + { + const Action &op = _operators[action._name_id]; Action a(repOpNameId, op.getArguments()); a.setPreconditions(op.getPreconditions()); a.setExtraPreconditions(op.getExtraPreconditions()); a.setEffects(op.getEffects()); _operators[repOpNameId] = std::move(a); _repeated_to_actual_action[repOpNameId] = action._name_id; - const auto& sorts = _signature_sorts_table[action._name_id]; + const auto &sorts = _signature_sorts_table[action._name_id]; _signature_sorts_table[repOpNameId] = sorts; } @@ -657,83 +767,103 @@ USignature HtnInstance::getRepetitionOfAction(const USignature& action) { return sig; } -const Action& HtnInstance::getActionFromRepetition(int vChildId) const { +const Action &HtnInstance::getActionFromRepetition(int vChildId) const +{ return _operators.at(_repeated_to_actual_action.at(vChildId)); } -int HtnInstance::getActionNameFromRepetition(int vChildId) const { +int HtnInstance::getActionNameFromRepetition(int vChildId) const +{ auto it = _repeated_to_actual_action.find(vChildId); return it == _repeated_to_actual_action.end() ? -1 : it->second; } -Action HtnInstance::replaceVariablesWithQConstants(const Action& a, const std::vector>& opArgDomains, int layerIdx, int pos) { - std::vector newArgs = replaceVariablesWithQConstants((const HtnOp&)a, opArgDomains, layerIdx, pos); - if (newArgs.size() == 1 && newArgs[0] == -1) { +Action HtnInstance::replaceVariablesWithQConstants(const Action &a, const std::vector> &opArgDomains, int layerIdx, int pos) +{ + std::basic_string newArgs = replaceVariablesWithQConstants((const HtnOp &)a, opArgDomains, layerIdx, pos); + if (newArgs.size() == 1 && newArgs[0] == -1) + { // No valid substitution. return a; } return toAction(a.getNameId(), newArgs); } -Reduction HtnInstance::replaceVariablesWithQConstants(const Reduction& red, const std::vector>& opArgDomains, int layerIdx, int pos) { - std::vector newArgs = replaceVariablesWithQConstants((const HtnOp&)red, opArgDomains, layerIdx, pos); - if (newArgs.size() == 1 && newArgs[0] == -1) { +Reduction HtnInstance::replaceVariablesWithQConstants(const Reduction &red, const std::vector> &opArgDomains, int layerIdx, int pos) +{ + std::basic_string newArgs = replaceVariablesWithQConstants((const HtnOp &)red, opArgDomains, layerIdx, pos); + if (newArgs.size() == 1 && newArgs[0] == -1) + { // No valid substitution. return red; } return red.substituteRed(Substitution(red.getArguments(), newArgs)); } -std::vector HtnInstance::replaceVariablesWithQConstants(const HtnOp& op, - const std::vector>& domainPerVariable, int layerIdx, int pos) { - - if (op.getArguments().empty()) return std::vector(); - std::vector vecFailure(1, -1); +std::basic_string HtnInstance::replaceVariablesWithQConstants(const HtnOp &op, + const std::vector> &domainPerVariable, int layerIdx, int pos) +{ - std::vector args = op.getArguments(); - std::vector varargIndices; - for (size_t i = 0; i < args.size(); i++) { - const int& arg = args[i]; - if (isVariable(arg)) varargIndices.push_back(i); + if (op.getArguments().empty()) + return {}; + std::basic_string vecFailure(1, -1); + + std::basic_string args = op.getArguments(); + std::basic_string varargIndices; + for (size_t i = 0; i < args.size(); i++) + { + const int &arg = args[i]; + if (isVariable(arg)) + varargIndices.push_back(i); } - if (domainPerVariable.empty()) return vecFailure; + if (domainPerVariable.empty()) + return vecFailure; // Assemble new operator arguments FlatHashMap numIntroducedQConstsPerType; - NodeHashMap> domainsPerQConst; - for (int i : varargIndices) { + NodeHashMap> domainsPerQConst; + for (int i : varargIndices) + { int vararg = args[i]; - auto& domain = domainPerVariable[i]; - if (domain.empty()) { + auto &domain = domainPerVariable[i]; + if (domain.empty()) + { // No valid constants at this position! The op is impossible. Log::d("Empty domain for arg %s of %s\n", TOSTR(vararg), TOSTR(op.getSignature())); return vecFailure; } - if (domain.size() == 1) { + if (domain.size() == 1) + { // Only one valid constant here: Replace directly - int onlyArg = -1; for (int arg : domain) {onlyArg = arg; break;} + int onlyArg = -1; + for (int arg : domain) + { + onlyArg = arg; + break; + } args[i] = onlyArg; - } else { + } + else + { // Several valid constants here: Introduce q-constant // Assemble name int sortCounter = 0; int primarySort = _signature_sorts_table[op.getSignature()._name_id][i]; auto it = numIntroducedQConstsPerType.find(primarySort); - if (it == numIntroducedQConstsPerType.end()) { + if (it == numIntroducedQConstsPerType.end()) + { numIntroducedQConstsPerType[primarySort] = 1; - } else { + } + else + { sortCounter = it->second; it->second++; } - std::vector domainVec(domain.begin(), domain.end()); + std::basic_string domainVec(domain.begin(), domain.end()); std::stringstream domainHash; domainHash << std::hex << USignatureHasher()(USignature(primarySort, domainVec)); - std::string qConstName = "Q_" + std::to_string(layerIdx) + "," - + std::to_string(pos) + "_" + _name_back_table[primarySort] - + ":" + std::to_string(sortCounter) - + "_" + domainHash.str() - + (_share_q_constants ? std::string() : "_#"+std::to_string(_q_constants_with_origin.size())); - + std::string qConstName = "Q_" + std::to_string(layerIdx) + "," + std::to_string(pos) + "_" + _name_back_table[primarySort] + ":" + std::to_string(sortCounter) + "_" + domainHash.str() + (_share_q_constants ? std::string() : "_#" + std::to_string(_q_constants_with_origin.size())); + // Initialize q-constant args[i] = nameId(qConstName, /*createQConstant=*/true, layerIdx, pos); initQConstantSorts(args[i], domain); @@ -752,14 +882,16 @@ std::vector HtnInstance::replaceVariablesWithQConstants(const HtnOp& op, // Remember exact domain of each q constant for this operation USignature newSig(op.getSignature()._name_id, args); - for (auto& [qconst, domain] : domainsPerQConst) { + for (auto &[qconst, domain] : domainsPerQConst) + { _q_const_to_op_domains[qconst][newSig] = std::move(domain); } return args; } -void HtnInstance::initQConstantSorts(int id, const FlatHashSet& domain) { +void HtnInstance::initQConstantSorts(int id, const FlatHashSet &domain) +{ // Create or retrieve the exact sort (= domain of constants) for this q-constant std::string qSortName = "qsort_" + _name_back_table[id]; @@ -771,90 +903,114 @@ void HtnInstance::initQConstantSorts(int id, const FlatHashSet& domain) { // 1. assume that the q-constant is of ALL (super) sorts FlatHashSet qConstSorts; - for (const auto& sortPair : _p.sorts) qConstSorts.insert(nameId(sortPair.first)); + for (const auto &sortPair : _p.sorts) + qConstSorts.insert(nameId(sortPair.first)); // 2. for each constant of the primary sort: // remove all q-constant sorts NOT containing that constant - for (int c : _constants_by_sort[newSortId]) { + for (int c : _constants_by_sort[newSortId]) + { std::vector sortsToRemove; - for (int qsort : qConstSorts) { - if (std::find(_constants_by_sort[qsort].begin(), _constants_by_sort[qsort].end(), c) - == _constants_by_sort[qsort].end()) { + for (int qsort : qConstSorts) + { + if (std::find(_constants_by_sort[qsort].begin(), _constants_by_sort[qsort].end(), c) == _constants_by_sort[qsort].end()) + { sortsToRemove.push_back(qsort); } } - for (int remSort : sortsToRemove) qConstSorts.erase(remSort); + for (int remSort : sortsToRemove) + qConstSorts.erase(remSort); } // RESULT: The intersection of sorts of all eligible constants. // => If the q-constant has some sort, it means that ALL possible substitutions have that sort. _sorts_of_q_constants[id] = qConstSorts; } -const std::vector SIGVEC_EMPTY; +const std::vector SIGVEC_EMPTY; -std::vector> HtnInstance::getEligibleArgs(const USignature& qSig, - const std::vector& restrictiveSorts) { +std::vector> HtnInstance::getEligibleArgs(const USignature &qSig, + const std::basic_string &restrictiveSorts) +{ - std::vector> eligibleArgs; + std::vector> eligibleArgs; - if (!hasQConstants(qSig) && isFullyGround(qSig)) + if (!hasQConstants(qSig) && isFullyGround(qSig)) return eligibleArgs; eligibleArgs.resize(qSig._args.size()); size_t numChoices = 1; - for (size_t argPos = 0; argPos < qSig._args.size(); argPos++) { + for (size_t argPos = 0; argPos < qSig._args.size(); argPos++) + { int arg = qSig._args[argPos]; - if (isVariable(arg) || isQConstant(arg)) { + if (isVariable(arg) || isQConstant(arg)) + { // Q-constant sort or variable - const auto& domain = _constants_by_sort.at(isQConstant(arg) ? _primary_sort_of_q_constants[arg] - : getSorts(qSig._name_id).at(argPos)); - if (restrictiveSorts.empty()) { + const auto &domain = _constants_by_sort.at(isQConstant(arg) ? _primary_sort_of_q_constants[arg] + : getSorts(qSig._name_id).at(argPos)); + if (restrictiveSorts.empty()) + { eligibleArgs[argPos].insert(eligibleArgs[argPos].end(), domain.begin(), domain.end()); - } else { - const auto& restrictiveDomain = _constants_by_sort.at(restrictiveSorts.at(argPos)); - for (int c : domain) { - if (restrictiveDomain.count(c)) eligibleArgs[argPos].push_back(c); + } + else + { + const auto &restrictiveDomain = _constants_by_sort.at(restrictiveSorts.at(argPos)); + for (int c : domain) + { + if (restrictiveDomain.count(c)) + eligibleArgs[argPos].push_back(c); } } - } else { + } + else + { // normal constant eligibleArgs[argPos].push_back(arg); } - //assert(eligibleArgs[argPos].size() > 0); - if (eligibleArgs[argPos].empty()) { - return std::vector>(); + // assert(eligibleArgs[argPos].size() > 0); + if (eligibleArgs[argPos].empty()) + { + return {}; } numChoices *= eligibleArgs[argPos].size(); } return eligibleArgs; } -ArgIterator HtnInstance::decodeObjects(const USignature& qSig, std::vector> eligibleArgs) { +ArgIterator HtnInstance::decodeObjects(const USignature &qSig, std::vector> eligibleArgs) +{ return ArgIterator(qSig._name_id, std::move(eligibleArgs)); } -SampleArgIterator HtnInstance::decodeObjects(const USignature& qSig, std::vector> eligibleArgs, size_t numSamples) { +SampleArgIterator HtnInstance::decodeObjects(const USignature &qSig, std::vector> eligibleArgs, size_t numSamples) +{ return SampleArgIterator(qSig._name_id, std::move(eligibleArgs), numSamples); } -const std::vector& HtnInstance::getSorts(int nameId) const { +const std::basic_string &HtnInstance::getSorts(int nameId) const +{ return _signature_sorts_table.at(nameId); } -const FlatHashSet& HtnInstance::getConstantsOfSort(int sort) const { +const FlatHashSet &HtnInstance::getConstantsOfSort(int sort) const +{ return _constants_by_sort.at(sort); } -const FlatHashSet& HtnInstance::getSortsOfQConstant(int qconst) { +const FlatHashSet &HtnInstance::getSortsOfQConstant(int qconst) +{ return _sorts_of_q_constants[qconst]; } -std::vector HtnInstance::getOpSortsForCondition(const USignature& sig, const USignature& op) { - std::vector sigSorts(sig._args.size()); - const auto& opSorts = _signature_sorts_table[op._name_id]; - for (size_t sigIdx = 0; sigIdx < sigSorts.size(); sigIdx++) { - for (size_t opIdx = 0; opIdx < op._args.size(); opIdx++) { - if (sig._args[sigIdx] == op._args[opIdx]) { +std::basic_string HtnInstance::getOpSortsForCondition(const USignature &sig, const USignature &op) +{ + std::basic_string sigSorts(sig._args.size(), 0); + const auto &opSorts = _signature_sorts_table[op._name_id]; + for (size_t sigIdx = 0; sigIdx < sigSorts.size(); sigIdx++) + { + for (size_t opIdx = 0; opIdx < op._args.size(); opIdx++) + { + if (sig._args[sigIdx] == op._args[opIdx]) + { // Found sigSorts[sigIdx] = opSorts[opIdx]; break; @@ -864,77 +1020,95 @@ std::vector HtnInstance::getOpSortsForCondition(const USignature& sig, cons return sigSorts; } -const FlatHashSet& HtnInstance::getDomainOfQConstant(int qconst) const { +const FlatHashSet &HtnInstance::getDomainOfQConstant(int qconst) const +{ return _constants_by_sort.at(_primary_sort_of_q_constants.at(qconst)); } -const IntPair& HtnInstance::getOriginOfQConstant(int qconst) const { +const IntPair &HtnInstance::getOriginOfQConstant(int qconst) const +{ return _q_constants_with_origin.at(qconst); } -std::vector HtnInstance::popOperationDependentDomainOfQConstant(int qconst, const USignature& op) { +std::basic_string HtnInstance::popOperationDependentDomainOfQConstant(int qconst, const USignature &op) +{ auto it1 = _q_const_to_op_domains.find(qconst); assert(it1 != _q_const_to_op_domains.end()); - auto& opDomains = it1->second; + auto &opDomains = it1->second; auto it2 = opDomains.find(op); assert(it2 != opDomains.end()); - std::vector domain = it2->second; - if (opDomains.size() == 1) { + std::basic_string domain = it2->second; + if (opDomains.size() == 1) + { _q_const_to_op_domains.erase(it1); - } else { + } + else + { opDomains.erase(it2); } return domain; } -const NodeHashMap& HtnInstance::getActionTemplates() const { +const NodeHashMap &HtnInstance::getActionTemplates() const +{ return _operators; } -NodeHashMap& HtnInstance::getReductionTemplates() { +NodeHashMap &HtnInstance::getReductionTemplates() +{ return _methods; } -Action HtnInstance::toAction(int actionName, const std::vector& args) const { - const auto& op = _operators.at(actionName); +Action HtnInstance::toAction(int actionName, const std::basic_string &args) const +{ + const auto &op = _operators.at(actionName); return op.substitute(Substitution(op.getArguments(), args)); } -Reduction HtnInstance::toReduction(int reductionName, const std::vector& args) const { - const auto& op = _methods.at(reductionName); +Reduction HtnInstance::toReduction(int reductionName, const std::basic_string &args) const +{ + const auto &op = _methods.at(reductionName); return op.substituteRed(Substitution(op.getArguments(), args)); } -USignature HtnInstance::cutNonoriginalTaskArguments(const USignature& sig) { +USignature HtnInstance::cutNonoriginalTaskArguments(const USignature &sig) +{ USignature sigCut(sig); sigCut._args.resize(_original_n_taskvars[sig._name_id]); return sigCut; } -const std::pair& HtnInstance::getReductionAndActionFromPrimitivization(int primitivizationName) { +const std::pair &HtnInstance::getReductionAndActionFromPrimitivization(int primitivizationName) +{ return _primitivization_to_parent_and_child[primitivizationName]; } -USignature HtnInstance::getNormalizedLifted(const USignature& opSig, std::vector& placeholderArgs) { +USignature HtnInstance::getNormalizedLifted(const USignature &opSig, std::basic_string &placeholderArgs) +{ int nameId = opSig._name_id; - + // Get original signature of this operator (fully lifted) USignature origSig; - if (_methods.count(nameId)) { + if (_methods.count(nameId)) + { // Reduction origSig = _methods.at(nameId).getSignature(); - } else { + } + else + { // Action origSig = _operators.at(nameId).getSignature(); } // Substitution mapping - for (size_t i = 0; i < opSig._args.size(); i++) { - placeholderArgs.push_back(-i-1); + for (size_t i = 0; i < opSig._args.size(); i++) + { + placeholderArgs.push_back(-i - 1); } - return origSig.substitute(Substitution(origSig._args, placeholderArgs)); + return origSig.substitute(Substitution(origSig._args, placeholderArgs)); } -HtnInstance::~HtnInstance() { +HtnInstance::~HtnInstance() +{ delete &_p; } \ No newline at end of file diff --git a/src/data/htn_instance.h b/src/data/htn_instance.h index 0c3371d..6a4126b 100644 --- a/src/data/htn_instance.h +++ b/src/data/htn_instance.h @@ -3,6 +3,7 @@ #define DOMPASCH_TREE_REXX_HTN_INSTANCE_H #include +#include #include "data/action.h" #include "data/reduction.h" @@ -22,14 +23,15 @@ struct task; struct method; struct literal; -class HtnInstance { +class HtnInstance +{ private: - Parameters& _params; + Parameters &_params; // The raw parsed problem. - ParsedProblem& _p; - + ParsedProblem &_p; + // Maps a string to its name ID within the problem. FlatHashMap _name_table; // Maps a name ID to its string within the problem. @@ -46,10 +48,10 @@ class HtnInstance { // Set of all q-constant IDs. FlatHashMap _q_constants_with_origin; - NodeHashMap, USignatureHasher>> _q_const_to_op_domains; + NodeHashMap, USignatureHasher>> _q_const_to_op_domains; // Maps a {predicate,task,method} name ID to a list of sorts IDs. - NodeHashMap> _signature_sorts_table; + NodeHashMap> _signature_sorts_table; // Maps a sort name ID to a set of constants of that sort. NodeHashMap> _constants_by_sort; @@ -58,11 +60,11 @@ class HtnInstance { FlatHashMap _primary_sort_of_q_constants; // Maps each q-constant to a list of sorts it is constrained with. NodeHashMap> _sorts_of_q_constants; - + // Maps each {action,reduction} name ID to the number of task variables it originally had. FlatHashMap _original_n_taskvars; - // Lookup table for the possible decodings of a fact signature with normalized arguments. + // Lookup table for the possible decodings of a fact signature with normalized arguments. NodeHashMap, USignatureHasher> _fact_sig_decodings; // Maps an action name ID to its action object. @@ -88,111 +90,128 @@ class HtnInstance { Reduction _init_reduction; // Signature of the BLANK virtual action. USignature _blank_action_sig; - + const bool _share_q_constants; public: - // Special action representing a virtual "No-op". static Action BLANK_ACTION; - HtnInstance(Parameters& params); + HtnInstance(Parameters ¶ms); ~HtnInstance(); - ParsedProblem* parse(std::string domainFile, std::string problemFile); + ParsedProblem *parse(std::string domainFile, std::string problemFile); USigSet getInitState(); - const Reduction& getInitReduction(); - const USignature& getBlankActionSig(); + const Reduction &getInitReduction(); + const USignature &getBlankActionSig(); Action getGoalAction(); void printStatistics(); - size_t getNumFreeArguments(const Reduction& r); - - const NodeHashMap& getActionTemplates() const; - NodeHashMap& getReductionTemplates(); - - Action toAction(int actionName, const std::vector& args) const; - Reduction toReduction(int reductionName, const std::vector& args) const; - HtnOp& getOp(const USignature& opSig); - const Action& getActionTemplate(int nameId) const; - const Reduction& getReductionTemplate(int nameId) const; - OpTable& getOpTable() {return _op_table;} + size_t getNumFreeArguments(const Reduction &r); + + const NodeHashMap &getActionTemplates() const; + NodeHashMap &getReductionTemplates(); + + Action toAction(int actionName, const std::basic_string &args) const; + Reduction toReduction(int reductionName, const std::basic_string &args) const; + HtnOp &getOp(const USignature &opSig); + const Action &getActionTemplate(int nameId) const; + const Reduction &getReductionTemplate(int nameId) const; + OpTable &getOpTable() { return _op_table; } bool hasReductions(int taskId) const; - const std::vector& getReductionIdsOfTaskId(int taskId) const; + const std::vector &getReductionIdsOfTaskId(int taskId) const; bool isReductionPrimitivizable(int reductionId) const; - const Action& getReductionPrimitivization(int reductionId) const; + const Action &getReductionPrimitivization(int reductionId) const; bool isActionRepetition(int actionId) const; int getRepetitionNameOfAction(int actionId); - USignature getRepetitionOfAction(const USignature& action); + USignature getRepetitionOfAction(const USignature &action); int getActionNameFromRepetition(int vChildId) const; - const Action& getActionFromRepetition(int vChildId) const; + const Action &getActionFromRepetition(int vChildId) const; + + const std::basic_string &getSorts(int nameId) const; + const FlatHashSet &getConstantsOfSort(int sort) const; + const FlatHashSet &getSortsOfQConstant(int qconst); + const IntPair &getOriginOfQConstant(int qconst) const; + const FlatHashSet &getDomainOfQConstant(int qconst) const; + std::basic_string popOperationDependentDomainOfQConstant(int qconst, const USignature &op); - const std::vector& getSorts(int nameId) const; - const FlatHashSet& getConstantsOfSort(int sort) const; - const FlatHashSet& getSortsOfQConstant(int qconst); - const IntPair& getOriginOfQConstant(int qconst) const; - const FlatHashSet& getDomainOfQConstant(int qconst) const; - std::vector popOperationDependentDomainOfQConstant(int qconst, const USignature& op); + std::basic_string getOpSortsForCondition(const USignature &sig, const USignature &op); - std::vector getOpSortsForCondition(const USignature& sig, const USignature& op); + std::vector> getEligibleArgs(const USignature &qFact, const std::basic_string &restrictiveSorts = {}); + ArgIterator decodeObjects(const USignature &qSig, std::vector> eligibleArgs); + SampleArgIterator decodeObjects(const USignature &qSig, std::vector> eligibleArgs, size_t numSamples); - std::vector> getEligibleArgs(const USignature& qFact, const std::vector& restrictiveSorts = std::vector()); - ArgIterator decodeObjects(const USignature& qSig, std::vector> eligibleArgs); - SampleArgIterator decodeObjects(const USignature& qSig, std::vector> eligibleArgs, size_t numSamples); + Action replaceVariablesWithQConstants(const Action &a, const std::vector> &opArgDomains, int layerIdx, int pos); + Reduction replaceVariablesWithQConstants(const Reduction &red, const std::vector> &opArgDomains, int layerIdx, int pos); - Action replaceVariablesWithQConstants(const Action& a, const std::vector>& opArgDomains, int layerIdx, int pos); - Reduction replaceVariablesWithQConstants(const Reduction& red, const std::vector>& opArgDomains, int layerIdx, int pos); + USignature getNormalizedLifted(const USignature &opSig, std::basic_string &placeholderArgs); - USignature getNormalizedLifted(const USignature& opSig, std::vector& placeholderArgs); - - USignature cutNonoriginalTaskArguments(const USignature& sig); - const std::pair& getReductionAndActionFromPrimitivization(int primitivizationName); + USignature cutNonoriginalTaskArguments(const USignature &sig); + const std::pair &getReductionAndActionFromPrimitivization(int primitivizationName); - int nameId(const std::string& name, bool createQConstant = false, int layerIdx = -1, int pos = -1); + int nameId(const std::string &name, bool createQConstant = false, int layerIdx = -1, int pos = -1); std::string toString(int id) const; - inline bool isVariable(int c) const { - if (c < 0) return true; + inline bool isVariable(int c) const + { + if (c < 0) + return true; assert(_name_back_table.count(c) || Log::d("%i not in name_back_table !\n", c)); return _var_ids.count(c); } - inline bool isQConstant(int c) const { + inline bool isQConstant(int c) const + { return c > _name_table_running_id; } - inline bool hasQConstants(const USignature& sig) const { - for (const int& arg : sig._args) if (isQConstant(arg)) return true; + inline bool hasQConstants(const USignature &sig) const + { + for (const int &arg : sig._args) + if (isQConstant(arg)) + return true; return false; } - bool isUnifiable(const Signature& from, const Signature& to, FlatHashMap* substitution = nullptr) { - if (from._negated != to._negated) return false; + bool isUnifiable(const Signature &from, const Signature &to, FlatHashMap *substitution = nullptr) + { + if (from._negated != to._negated) + return false; return isUnifiable(from._usig, to._usig, substitution); } - bool isUnifiable(const USignature& from, const USignature& to, FlatHashMap* substitution = nullptr) { - if (from._name_id != to._name_id) return false; - if (from._args.size() != to._args.size()) return false; + bool isUnifiable(const USignature &from, const USignature &to, FlatHashMap *substitution = nullptr) + { + if (from._name_id != to._name_id) + return false; + if (from._args.size() != to._args.size()) + return false; - for (size_t i = 0; i < from._args.size(); i++) { + for (size_t i = 0; i < from._args.size(); i++) + { - if (!isVariable(from._args[i])) { + if (!isVariable(from._args[i])) + { // Constant parameter: must be equal - if (from._args[i] != to._args[i]) return false; - - } else if (isVariable(to._args[i])) { + if (from._args[i] != to._args[i]) + return false; + } + else if (isVariable(to._args[i])) + { // Both are variables: fine - if (substitution != nullptr) { + if (substitution != nullptr) + { (*substitution)[from._args[i]] = to._args[i]; } - - } else { + } + else + { // Variable to constant: fine - if (substitution != nullptr) { + if (substitution != nullptr) + { (*substitution)[from._args[i]] = to._args[i]; } } @@ -200,110 +219,142 @@ class HtnInstance { return true; } - std::vector getFreeArgPositions(const std::vector& sigArgs) { + std::vector getFreeArgPositions(const std::vector &sigArgs) + { std::vector argPositions; - for (size_t i = 0; i < sigArgs.size(); i++) { + for (size_t i = 0; i < sigArgs.size(); i++) + { int arg = sigArgs[i]; - if (isVariable(arg)) argPositions.push_back(i); + if (isVariable(arg)) + argPositions.push_back(i); } return argPositions; } - inline bool isFullyGround(const USignature& sig) { - for (int arg : sig._args) if (isVariable(arg)) return false; + inline bool isFullyGround(const USignature &sig) + { + for (int arg : sig._args) + if (isVariable(arg)) + return false; return true; } - inline bool hasSomeInstantiation(const USignature& sig) { - const std::vector& types = getSorts(sig._name_id); - //log("%s , %i\n", TOSTR(sig), types.size()); + inline bool hasSomeInstantiation(const USignature &sig) + { + const std::basic_string &types = getSorts(sig._name_id); + // log("%s , %i\n", TOSTR(sig), types.size()); assert(types.size() == sig._args.size()); - for (size_t argPos = 0; argPos < sig._args.size(); argPos++) { + for (size_t argPos = 0; argPos < sig._args.size(); argPos++) + { int sort = types[argPos]; - if (getConstantsOfSort(sort).empty()) { + if (getConstantsOfSort(sort).empty()) + { return false; } } return true; } - bool hasConsistentlyTypedArgs(const USignature& sig) { - const std::vector& taskSorts = getSorts(sig._name_id); - for (size_t argPos = 0; argPos < sig._args.size(); argPos++) { + bool hasConsistentlyTypedArgs(const USignature &sig) + { + const std::basic_string &taskSorts = getSorts(sig._name_id); + for (size_t argPos = 0; argPos < sig._args.size(); argPos++) + { int sort = taskSorts[argPos]; int arg = sig._args[argPos]; - if (isVariable(arg)) continue; // skip variable + if (isVariable(arg)) + continue; // skip variable bool valid = false; - if (isQConstant(arg)) { + if (isQConstant(arg)) + { // q constant: TODO check if SOME SUBSTITUTEABLE CONSTANT has the correct sort - for (int cnst : getDomainOfQConstant(arg)) { - if (getConstantsOfSort(sort).count(cnst)) { + for (int cnst : getDomainOfQConstant(arg)) + { + if (getConstantsOfSort(sort).count(cnst)) + { valid = true; break; } } - } else { + } + else + { // normal constant: check if it is contained in the correct sort valid = getConstantsOfSort(sort).count(arg); } - if (!valid) { - //log("arg %s not of sort %s => %s invalid\n", TOSTR(arg), TOSTR(sort), TOSTR(sig)); + if (!valid) + { + // log("arg %s not of sort %s => %s invalid\n", TOSTR(arg), TOSTR(sort), TOSTR(sig)); return false; - } + } } return true; } - inline bool isPredicate(int nameId) const { + inline bool isPredicate(int nameId) const + { return _predicate_ids.count(nameId); } - inline bool isAction(const USignature& sig) const { + inline bool isAction(const USignature &sig) const + { return _operators.count(sig._name_id); } - inline bool isReduction(const USignature& sig) const { + inline bool isReduction(const USignature &sig) const + { return _methods.count(sig._name_id); } - inline size_t getNumberOfQConstants() const { + inline size_t getNumberOfQConstants() const + { return _q_constants_with_origin.size(); } - std::vector getQConstantTypeConstraints(const USignature& sig) { + std::vector getQConstantTypeConstraints(const USignature &sig) + { std::vector constraints; - const std::vector& taskSorts = getSorts(sig._name_id); - for (size_t argPos = 0; argPos < sig._args.size(); argPos++) { + const std::basic_string &taskSorts = getSorts(sig._name_id); + for (size_t argPos = 0; argPos < sig._args.size(); argPos++) + { int sigSort = taskSorts[argPos]; int arg = sig._args[argPos]; - + // Not a q-constant here - if (!isQConstant(arg)) { + if (!isQConstant(arg)) + { // Must be of valid type assert(getConstantsOfSort(sigSort).count(arg)); continue; } // Type is fine no matter which substitution is chosen - if (getSortsOfQConstant(arg).count(sigSort)) continue; + if (getSortsOfQConstant(arg).count(sigSort)) + continue; // Type is NOT fine, at least for some substitutions std::vector good; std::vector bad; - const FlatHashSet& validConstants = getConstantsOfSort(sigSort); + const FlatHashSet &validConstants = getConstantsOfSort(sigSort); // For each value the qconstant can assume: - for (int c : getDomainOfQConstant(arg)) { + for (int c : getDomainOfQConstant(arg)) + { // Is that constant of correct type? - if (validConstants.count(c)) good.push_back(c); - else bad.push_back(c); + if (validConstants.count(c)) + good.push_back(c); + else + bad.push_back(c); } - if (good.size() >= bad.size()) { + if (good.size() >= bad.size()) + { // arg must be EITHER of the GOOD ones constraints.emplace_back(arg, true, std::move(good)); - } else { + } + else + { // arg must be NEITHER of the BAD ones constraints.emplace_back(arg, false, std::move(bad)); } @@ -313,28 +364,26 @@ class HtnInstance { } private: - void primitivizeSimpleReductions(); - - std::vector convertArguments(int predNameId, const std::vector>& vars); - std::vector convertArguments(int predNameId, const std::vector& vars); - USignature convertSignature(const task& task); - USignature convertSignature(const method& method); - Signature convertSignature(int parentNameId, const literal& literal); - - void extractPredSorts(const predicate_definition& p); - void extractTaskSorts(const task& t); - void extractMethodSorts(const method& m); + + std::basic_string convertArguments(int predNameId, const std::vector> &vars); + std::basic_string convertArguments(int predNameId, const std::vector &vars); + USignature convertSignature(const task &task); + USignature convertSignature(const method &method); + Signature convertSignature(int parentNameId, const literal &literal); + + void extractPredSorts(const predicate_definition &p); + void extractTaskSorts(const task &t); + void extractMethodSorts(const method &m); void extractConstants(); - SigSet extractEqualityConstraints(int opId, const std::vector& lits, const std::vector>& vars); + SigSet extractEqualityConstraints(int opId, const std::vector &lits, const std::vector> &vars); SigSet extractGoals(); - Reduction& createReduction(method& method); - Action& createAction(const task& task); - - std::vector replaceVariablesWithQConstants(const HtnOp& op, const std::vector>& opArgDomains, int layerIdx, int pos); - void initQConstantSorts(int id, const FlatHashSet& domain); + Reduction &createReduction(method &method); + Action &createAction(const task &task); + std::basic_string replaceVariablesWithQConstants(const HtnOp &op, const std::vector> &opArgDomains, int layerIdx, int pos); + void initQConstantSorts(int id, const FlatHashSet &domain); }; #endif \ No newline at end of file diff --git a/src/data/htn_op.cpp b/src/data/htn_op.cpp index c89037b..9d8b6e7 100644 --- a/src/data/htn_op.cpp +++ b/src/data/htn_op.cpp @@ -2,100 +2,128 @@ #include "htn_op.h" HtnOp::HtnOp() {} -HtnOp::HtnOp(int id, const std::vector& args) : _id(id), _args(args) {} -HtnOp::HtnOp(int id, std::vector&& args) : _id(id), _args(std::move(args)) {} -HtnOp::HtnOp(const HtnOp& op) : _id(op._id), _args(op._args), _preconditions(op._preconditions), - _extra_preconditions(op._extra_preconditions), _effects(op._effects) {} -HtnOp::HtnOp(HtnOp&& op) : _id(op._id), _args(std::move(op._args)), - _preconditions(std::move(op._preconditions)), - _extra_preconditions(std::move(op._extra_preconditions)), - _effects(std::move(op._effects)) {} +HtnOp::HtnOp(int id, const std::basic_string &args) : _id(id), _args(args) {} +HtnOp::HtnOp(int id, std::basic_string &&args) : _id(id), _args(std::move(args)) {} +HtnOp::HtnOp(const HtnOp &op) : _id(op._id), _args(op._args), _preconditions(op._preconditions), + _extra_preconditions(op._extra_preconditions), _effects(op._effects) {} +HtnOp::HtnOp(HtnOp &&op) : _id(op._id), _args(std::move(op._args)), + _preconditions(std::move(op._preconditions)), + _extra_preconditions(std::move(op._extra_preconditions)), + _effects(std::move(op._effects)) {} -void HtnOp::setPreconditions(const SigSet& set) { +void HtnOp::setPreconditions(const SigSet &set) +{ _preconditions = set; } -void HtnOp::setExtraPreconditions(const SigSet& set) { +void HtnOp::setExtraPreconditions(const SigSet &set) +{ _extra_preconditions = set; } -void HtnOp::setEffects(const SigSet& set) { +void HtnOp::setEffects(const SigSet &set) +{ _effects = set; } -void HtnOp::addPrecondition(const Signature& sig) { +void HtnOp::addPrecondition(const Signature &sig) +{ _preconditions.insert(sig); } -void HtnOp::addPrecondition(Signature&& sig) { +void HtnOp::addPrecondition(Signature &&sig) +{ _preconditions.insert(std::move(sig)); } -void HtnOp::addExtraPrecondition(const Signature& sig) { +void HtnOp::addExtraPrecondition(const Signature &sig) +{ _extra_preconditions.insert(sig); } -void HtnOp::addExtraPrecondition(Signature&& sig) { +void HtnOp::addExtraPrecondition(Signature &&sig) +{ _extra_preconditions.insert(std::move(sig)); } -void HtnOp::addEffect(const Signature& sig) { +void HtnOp::addEffect(const Signature &sig) +{ _effects.insert(sig); } -void HtnOp::addEffect(Signature&& sig) { +void HtnOp::addEffect(Signature &&sig) +{ _effects.insert(std::move(sig)); } -void HtnOp::addArgument(int arg) { +void HtnOp::addArgument(int arg) +{ _args.push_back(arg); } -void HtnOp::removeInconsistentEffects() { +void HtnOp::removeInconsistentEffects() +{ // Collect all neg. preconds for which the pos. precond is contained, too SigSet inconsistentEffs; - for (const Signature& sig : _effects) { - if (sig._negated && _effects.count(Signature(sig._usig, false))) { + for (const Signature &sig : _effects) + { + if (sig._negated && _effects.count(Signature(sig._usig, false))) + { inconsistentEffs.insert(sig); } } // Remove each such neg. precond - for (const Signature& sig : inconsistentEffs) { + for (const Signature &sig : inconsistentEffs) + { _effects.erase(sig); } } -HtnOp HtnOp::substitute(const Substitution& s) const { +HtnOp HtnOp::substitute(const Substitution &s) const +{ HtnOp op; op._id = _id; op._args.resize(_args.size()); - for (size_t i = 0; i < _args.size(); i++) { + for (size_t i = 0; i < _args.size(); i++) + { auto it = s.find(_args[i]); - if (it != s.end()) op._args[i] = it->second; - else op._args[i] = _args[i]; + if (it != s.end()) + op._args[i] = it->second; + else + op._args[i] = _args[i]; } - for (const Signature& sig : _preconditions) { + for (const Signature &sig : _preconditions) + { op.addPrecondition(sig.substitute(s)); } - for (const Signature& sig : _extra_preconditions) { + for (const Signature &sig : _extra_preconditions) + { op.addExtraPrecondition(sig.substitute(s)); } - for (const Signature& sig : _effects) { + for (const Signature &sig : _effects) + { op.addEffect(sig.substitute(s)); } return op; } -const SigSet& HtnOp::getPreconditions() const { +const SigSet &HtnOp::getPreconditions() const +{ return _preconditions; } -const SigSet& HtnOp::getExtraPreconditions() const { +const SigSet &HtnOp::getExtraPreconditions() const +{ return _extra_preconditions; } -const SigSet& HtnOp::getEffects() const { +const SigSet &HtnOp::getEffects() const +{ return _effects; } -const std::vector& HtnOp::getArguments() const { +const std::basic_string &HtnOp::getArguments() const +{ return _args; } -USignature HtnOp::getSignature() const { +USignature HtnOp::getSignature() const +{ return USignature(_id, _args); } -int HtnOp::getNameId() const { +int HtnOp::getNameId() const +{ return _id; } -HtnOp& HtnOp::operator=(const HtnOp& op) { +HtnOp &HtnOp::operator=(const HtnOp &op) +{ _id = op._id; _args = op._args; _preconditions = op._preconditions; diff --git a/src/data/htn_op.h b/src/data/htn_op.h index faa53eb..9f7cb62 100644 --- a/src/data/htn_op.h +++ b/src/data/htn_op.h @@ -6,15 +6,15 @@ #include "signature.h" - -class HtnOp { +class HtnOp +{ protected: int _id; - std::vector _args; + std::basic_string _args; SigSet _preconditions; - + // Preconditions which are not part of the problem description. // They are implied by the logic and thus are not necessary to be checked, // but they *can* be checked, helping to prune operations. @@ -24,34 +24,33 @@ class HtnOp { public: HtnOp(); - HtnOp(int id, const std::vector& args); - HtnOp(int id, std::vector&& args); - HtnOp(const HtnOp& op); - HtnOp(HtnOp&& op); - - void setPreconditions(const SigSet& set); - void setExtraPreconditions(const SigSet& set); - void setEffects(const SigSet& set); - void addPrecondition(const Signature& sig); - void addPrecondition(Signature&& sig); - void addExtraPrecondition(const Signature& sig); - void addExtraPrecondition(Signature&& sig); - void addEffect(const Signature& sig); - void addEffect(Signature&& sig); + HtnOp(int id, const std::basic_string &args); + HtnOp(int id, std::basic_string &&args); + HtnOp(const HtnOp &op); + HtnOp(HtnOp &&op); + + void setPreconditions(const SigSet &set); + void setExtraPreconditions(const SigSet &set); + void setEffects(const SigSet &set); + void addPrecondition(const Signature &sig); + void addPrecondition(Signature &&sig); + void addExtraPrecondition(const Signature &sig); + void addExtraPrecondition(Signature &&sig); + void addEffect(const Signature &sig); + void addEffect(Signature &&sig); void addArgument(int arg); void removeInconsistentEffects(); - virtual HtnOp substitute(const Substitution& s) const; + virtual HtnOp substitute(const Substitution &s) const; - const SigSet& getPreconditions() const; - const SigSet& getExtraPreconditions() const; - const SigSet& getEffects() const; - const std::vector& getArguments() const; + const SigSet &getPreconditions() const; + const SigSet &getExtraPreconditions() const; + const SigSet &getEffects() const; + const std::basic_string &getArguments() const; USignature getSignature() const; int getNameId() const; - HtnOp& operator=(const HtnOp& op); + HtnOp &operator=(const HtnOp &op); }; - #endif \ No newline at end of file diff --git a/src/data/reduction.cpp b/src/data/reduction.cpp index 2db0b1b..2f46246 100644 --- a/src/data/reduction.cpp +++ b/src/data/reduction.cpp @@ -2,61 +2,75 @@ #include "reduction.h" Reduction::Reduction() : HtnOp() {} -Reduction::Reduction(HtnOp& op) : HtnOp(op) {} -Reduction::Reduction(const Reduction& r) : HtnOp(r._id, r._args), _task_name_id(r._task_name_id), _task_args(r._task_args), _subtasks(r._subtasks) { - for (auto pre : r.getPreconditions()) addPrecondition(pre); - for (auto pre : r.getExtraPreconditions()) addExtraPrecondition(pre); - for (auto eff : r.getEffects()) addEffect(eff); +Reduction::Reduction(HtnOp &op) : HtnOp(op) {} +Reduction::Reduction(const Reduction &r) : HtnOp(r._id, r._args), _task_name_id(r._task_name_id), _task_args(r._task_args), _subtasks(r._subtasks) +{ + for (auto pre : r.getPreconditions()) + addPrecondition(pre); + for (auto pre : r.getExtraPreconditions()) + addExtraPrecondition(pre); + for (auto eff : r.getEffects()) + addEffect(eff); } -Reduction::Reduction(int nameId, const std::vector& args, const USignature& task) : - HtnOp(nameId, args), _task_name_id(task._name_id), _task_args(task._args) {} -Reduction::Reduction(int nameId, const std::vector& args, USignature&& task) : - HtnOp(nameId, args), _task_name_id(task._name_id), _task_args(std::move(task._args)) {} +Reduction::Reduction(int nameId, const std::basic_string &args, const USignature &task) : HtnOp(nameId, args), _task_name_id(task._name_id), _task_args(task._args) {} +Reduction::Reduction(int nameId, const std::basic_string &args, USignature &&task) : HtnOp(nameId, args), _task_name_id(task._name_id), _task_args(std::move(task._args)) {} -void Reduction::orderSubtasks(const std::map>& orderingNodelist) { +void Reduction::orderSubtasks(const std::map> &orderingNodelist) +{ // Initialize "visited" state for each node std::map visitedStates; - for (auto pair : orderingNodelist) { + for (auto pair : orderingNodelist) + { visitedStates[pair.first] = 0; } // Topological ordering via multiple DFS std::vector sortedNodes; - while (true) { + while (true) + { // Pick an unvisited node int node = -1; - for (auto pair : orderingNodelist) { - if (visitedStates[pair.first] == 0) { + for (auto pair : orderingNodelist) + { + if (visitedStates[pair.first] == 0) + { node = pair.first; break; } } - if (node == -1) break; // no node left: done + if (node == -1) + break; // no node left: done // Traverse ordering graph std::vector nodeStack; nodeStack.push_back(node); - while (!nodeStack.empty()) { + while (!nodeStack.empty()) + { int n = nodeStack.back(); - if (visitedStates[n] == 2) { + if (visitedStates[n] == 2) + { // Closed node: pop nodeStack.pop_back(); - - } else if (visitedStates[n] == 1) { + } + else if (visitedStates[n] == 1) + { // Open node: close, pop nodeStack.pop_back(); visitedStates[n] = 2; sortedNodes.insert(sortedNodes.begin(), n); - - } else { + } + else + { // Unvisited node: open, visit children visitedStates[n] = 1; - if (!orderingNodelist.count(n)) continue; - for (int m : orderingNodelist.at(n)) { + if (!orderingNodelist.count(n)) + continue; + for (int m : orderingNodelist.at(n)) + { if (visitedStates[m] < 2) nodeStack.push_back(m); } @@ -67,54 +81,67 @@ void Reduction::orderSubtasks(const std::map>& orderingNod // Reorder subtasks std::vector newSubtasks; newSubtasks.resize(_subtasks.size()); - for (size_t i = 0; i < _subtasks.size(); i++) { + for (size_t i = 0; i < _subtasks.size(); i++) + { newSubtasks[i] = _subtasks[sortedNodes[i]]; } _subtasks = newSubtasks; } -Reduction Reduction::substituteRed(const Substitution& s) const { +Reduction Reduction::substituteRed(const Substitution &s) const +{ HtnOp op = HtnOp::substitute(s); Reduction r(op); - + r._task_name_id = _task_name_id; - + r._task_args.resize(_task_args.size()); - for (size_t i = 0; i < _task_args.size(); i++) { + for (size_t i = 0; i < _task_args.size(); i++) + { auto it = s.find(_task_args[i]); - if (it != s.end()) r._task_args[i] = it->second; - else r._task_args[i] = _task_args[i]; + if (it != s.end()) + r._task_args[i] = it->second; + else + r._task_args[i] = _task_args[i]; } - + r._subtasks.resize(_subtasks.size()); - for (size_t i = 0; i < _subtasks.size(); i++) { + for (size_t i = 0; i < _subtasks.size(); i++) + { r._subtasks[i] = _subtasks[i].substitute(s); } return r; } -void Reduction::addSubtask(const USignature& subtask) { +void Reduction::addSubtask(const USignature &subtask) +{ _subtasks.push_back(subtask); } -void Reduction::addSubtask(USignature&& subtask) { +void Reduction::addSubtask(USignature &&subtask) +{ _subtasks.push_back(std::move(subtask)); } -void Reduction::setSubtasks(std::vector&& subtasks) { +void Reduction::setSubtasks(std::vector &&subtasks) +{ _subtasks = std::move(subtasks); } -USignature Reduction::getTaskSignature() const { +USignature Reduction::getTaskSignature() const +{ return USignature(_task_name_id, _task_args); } -const std::vector& Reduction::getTaskArguments() const { +const std::basic_string &Reduction::getTaskArguments() const +{ return _task_args; } -const std::vector& Reduction::getSubtasks() const { +const std::vector &Reduction::getSubtasks() const +{ return _subtasks; } -Reduction& Reduction::operator=(const Reduction& other) { +Reduction &Reduction::operator=(const Reduction &other) +{ _id = other._id; _args = other._args; _preconditions = other._preconditions; diff --git a/src/data/reduction.h b/src/data/reduction.h index d784e0d..026c1ae 100644 --- a/src/data/reduction.h +++ b/src/data/reduction.h @@ -2,44 +2,45 @@ #ifndef DOMPASCH_TREE_REXX_REDUCTION_H #define DOMPASCH_TREE_REXX_REDUCTION_H +#include #include #include #include "data/htn_op.h" #include "data/signature.h" -class Reduction : public HtnOp { +class Reduction : public HtnOp +{ private: - // Coding of the methods' AT's name. int _task_name_id = -1; // The method's AT's arguments. - std::vector _task_args; + std::basic_string _task_args; // The ordered list of subtasks. std::vector _subtasks; public: Reduction(); - Reduction(HtnOp& op); - Reduction(const Reduction& r); - Reduction(int nameId, const std::vector& args, const USignature& task); - Reduction(int nameId, const std::vector& args, USignature&& task); + Reduction(HtnOp &op); + Reduction(const Reduction &r); + Reduction(int nameId, const std::basic_string &args, const USignature &task); + Reduction(int nameId, const std::basic_string &args, USignature &&task); - void orderSubtasks(const std::map>& orderingNodelist); + void orderSubtasks(const std::map> &orderingNodelist); - Reduction substituteRed(const Substitution& s) const; + Reduction substituteRed(const Substitution &s) const; - void addSubtask(const USignature& subtask); - void addSubtask(USignature&& subtask); - void setSubtasks(std::vector&& subtasks); + void addSubtask(const USignature &subtask); + void addSubtask(USignature &&subtask); + void setSubtasks(std::vector &&subtasks); USignature getTaskSignature() const; - const std::vector& getTaskArguments() const; - const std::vector& getSubtasks() const; + const std::basic_string &getTaskArguments() const; + const std::vector &getSubtasks() const; - Reduction& operator=(const Reduction& other); + Reduction &operator=(const Reduction &other); }; #endif \ No newline at end of file diff --git a/src/data/signature.cpp b/src/data/signature.cpp index c90a429..4a7987b 100644 --- a/src/data/signature.cpp +++ b/src/data/signature.cpp @@ -2,85 +2,102 @@ #include "data/signature.h" USignature::USignature() = default; -USignature::USignature(int nameId, const std::vector& args) : _name_id(nameId), _args(args) {} -USignature::USignature(int nameId, std::vector&& args) : _name_id(nameId), _args(std::move(args)) {} -USignature::USignature(const USignature& sig) : _name_id(sig._name_id), _args(sig._args) {} -USignature::USignature(USignature&& sig) : _name_id(sig._name_id), _args(std::move(sig._args)) {} +USignature::USignature(int nameId, const std::basic_string &args) : _name_id(nameId), _args(args) {} +USignature::USignature(int nameId, std::basic_string &&args) : _name_id(nameId), _args(std::move(args)) {} +USignature::USignature(const USignature &sig) : _name_id(sig._name_id), _args(sig._args) {} +USignature::USignature(USignature &&sig) : _name_id(sig._name_id), _args(std::move(sig._args)) {} -Signature USignature::toSignature(bool negated) const { +Signature USignature::toSignature(bool negated) const +{ return Signature(*this, negated); } -USignature USignature::substitute(const Substitution& s) const { +USignature USignature::substitute(const Substitution &s) const +{ USignature sig(*this); sig.apply(s); return sig; } -void USignature::apply(const Substitution& s) { - for (size_t i = 0; i < _args.size(); i++) { +void USignature::apply(const Substitution &s) +{ + for (size_t i = 0; i < _args.size(); i++) + { auto it = s.find(_args[i]); - if (it != s.end()) _args[i] = it->second; + if (it != s.end()) + _args[i] = it->second; assert(_args[i] != 0); } } -USignature USignature::renamed(int nameId) const { +USignature USignature::renamed(int nameId) const +{ USignature sig(*this); sig._name_id = nameId; return sig; } -USignature& USignature::operator=(const USignature& sig) { +USignature &USignature::operator=(const USignature &sig) +{ _name_id = sig._name_id; _args = sig._args; return *this; } -USignature& USignature::operator=(USignature&& sig) { +USignature &USignature::operator=(USignature &&sig) +{ _name_id = sig._name_id; _args = std::move(sig._args); return *this; } Signature::Signature() = default; -Signature::Signature(int nameId, const std::vector& args, bool negated) : _usig(nameId, args), _negated(negated) {} -Signature::Signature(int nameId, std::vector&& args, bool negated) : _usig(nameId, std::move(args)), _negated(negated) {} -Signature::Signature(const USignature& usig, bool negated) : _usig(usig), _negated(negated) {} -Signature::Signature(const Signature& sig) : _usig(sig._usig), _negated(sig._negated) {} -Signature::Signature(Signature&& sig) { +Signature::Signature(int nameId, const std::basic_string &args, bool negated) : _usig(nameId, args), _negated(negated) {} +Signature::Signature(int nameId, std::basic_string &&args, bool negated) : _usig(nameId, std::move(args)), _negated(negated) {} +Signature::Signature(const USignature &usig, bool negated) : _usig(usig), _negated(negated) {} +Signature::Signature(const Signature &sig) : _usig(sig._usig), _negated(sig._negated) {} +Signature::Signature(Signature &&sig) +{ _usig = std::move(sig._usig); _negated = sig._negated; } -void Signature::negate() { +void Signature::negate() +{ _negated = !_negated; } -const USignature& Signature::getUnsigned() const { +const USignature &Signature::getUnsigned() const +{ return _usig; } -Signature Signature::Signature::opposite() const { +Signature Signature::Signature::opposite() const +{ Signature out(*this); - if (_negated) out.negate(); + if (_negated) + out.negate(); return out; } -Signature Signature::substitute(const Substitution& s) const { +Signature Signature::substitute(const Substitution &s) const +{ return Signature(_usig.substitute(s), _negated); } -void Signature::apply(const Substitution& s) { +void Signature::apply(const Substitution &s) +{ _usig.apply(s); } -Signature& Signature::operator=(const Signature& sig) { +Signature &Signature::operator=(const Signature &sig) +{ _usig = sig._usig; _negated = sig._negated; return *this; } -Signature& Signature::operator=(Signature&& sig) { +Signature &Signature::operator=(Signature &&sig) +{ _usig = std::move(sig._usig); _negated = sig._negated; return *this; diff --git a/src/data/signature.h b/src/data/signature.h index 72b2d61..d02dd79 100644 --- a/src/data/signature.h +++ b/src/data/signature.h @@ -5,130 +5,154 @@ #include #include #include +#include #include "util/hashmap.h" #include "util/hash.h" #include "substitution.h" -struct TypeConstraint { +struct TypeConstraint +{ int qconstant; bool sign; std::vector constants; - TypeConstraint(int qconstant, bool sign, const std::vector& constants) : - qconstant(qconstant), sign(sign), constants(constants) {} - TypeConstraint(int qconstant, bool sign, std::vector&& constants) : - qconstant(qconstant), sign(sign), constants(constants) {} - TypeConstraint(const TypeConstraint& other) : qconstant(other.qconstant), - sign(other.sign), constants(other.constants) {} - TypeConstraint(TypeConstraint&& other) : qconstant(other.qconstant), - sign(other.sign), constants(std::move(other.constants)) {} + TypeConstraint(int qconstant, bool sign, const std::vector &constants) : qconstant(qconstant), sign(sign), constants(constants) {} + TypeConstraint(int qconstant, bool sign, std::vector &&constants) : qconstant(qconstant), sign(sign), constants(constants) {} + TypeConstraint(const TypeConstraint &other) : qconstant(other.qconstant), + sign(other.sign), constants(other.constants) {} + TypeConstraint(TypeConstraint &&other) : qconstant(other.qconstant), + sign(other.sign), constants(std::move(other.constants)) {} }; struct Signature; -struct USignature { +struct USignature +{ int _name_id = -1; - std::vector _args; + std::basic_string _args; USignature(); - USignature(int nameId, const std::vector& args); - USignature(int nameId, std::vector&& args); - USignature(const USignature& sig); - USignature(USignature&& sig); + USignature(int nameId, const std::basic_string &args); + USignature(int nameId, std::basic_string &&args); + USignature(const USignature &sig); + USignature(USignature &&sig); Signature toSignature(bool negated = false) const; - USignature substitute(const Substitution& s) const; - void apply(const Substitution& s); + USignature substitute(const Substitution &s) const; + void apply(const Substitution &s); USignature renamed(int nameId) const; - USignature& operator=(const USignature& sig); - USignature& operator=(USignature&& sig); + USignature &operator=(const USignature &sig); + USignature &operator=(USignature &&sig); - inline bool operator==(const USignature& b) const { - if (_name_id != b._name_id) return false; - if (_args != b._args) return false; + inline bool operator==(const USignature &b) const + { + if (_name_id != b._name_id) + return false; + if (_args != b._args) + return false; return true; } - inline bool operator!=(const USignature& b) const { + inline bool operator!=(const USignature &b) const + { return !(*this == b); } }; -struct Signature { - +struct Signature +{ + USignature _usig; mutable bool _negated = false; Signature(); - Signature(int nameId, const std::vector& args, bool negated = false); - Signature(int nameId, std::vector&& args, bool negated = false); - Signature(const USignature& usig, bool negated); - Signature(const Signature& sig); - Signature(Signature&& sig); + Signature(int nameId, const std::basic_string &args, bool negated = false); + Signature(int nameId, std::basic_string &&args, bool negated = false); + Signature(const USignature &usig, bool negated); + Signature(const Signature &sig); + Signature(Signature &&sig); void negate(); - const USignature& getUnsigned() const; + const USignature &getUnsigned() const; Signature opposite() const; - Signature substitute(const Substitution& s) const; - void apply(const Substitution& s); - - Signature& operator=(const Signature& sig); - Signature& operator=(Signature&& sig); - - inline bool operator==(const Signature& b) const { - if (_negated != b._negated) return false; - if (_usig != b._usig) return false; + Signature substitute(const Substitution &s) const; + void apply(const Substitution &s); + + Signature &operator=(const Signature &sig); + Signature &operator=(Signature &&sig); + + inline bool operator==(const Signature &b) const + { + if (_negated != b._negated) + return false; + if (_usig != b._usig) + return false; return true; } - inline bool operator!=(const Signature& b) const { + inline bool operator!=(const Signature &b) const + { return !(*this == b); } }; -struct PositionedUSig { - size_t layer; size_t pos; USignature usig; +struct PositionedUSig +{ + size_t layer; + size_t pos; + USignature usig; PositionedUSig() : layer(-1), pos(-1) {} - PositionedUSig(size_t layer, size_t pos, const USignature& usig) : layer(layer), pos(pos), usig(usig) {} - bool operator==(const PositionedUSig& other) const { + PositionedUSig(size_t layer, size_t pos, const USignature &usig) : layer(layer), pos(pos), usig(usig) {} + bool operator==(const PositionedUSig &other) const + { return layer == other.layer && pos == other.pos && usig == other.usig; } }; -struct USignatureHasher { +struct USignatureHasher +{ static int seed; - inline std::size_t operator()(const USignature& s) const { + inline std::size_t operator()(const USignature &s) const + { size_t hash = seed + s._args.size(); - for (const int& arg : s._args) { + for (const int &arg : s._args) + { hash_combine(hash, arg); } hash_combine(hash, s._name_id); return hash; } }; -struct SignatureHasher { +struct SignatureHasher +{ USignatureHasher _usig_hasher; - inline std::size_t operator()(const Signature& s) const { + inline std::size_t operator()(const Signature &s) const + { size_t hash = _usig_hasher(s._usig); hash_combine(hash, s._negated); return hash; } }; -struct PositionedUSigHasher { +struct PositionedUSigHasher +{ USignatureHasher usigHasher; - std::size_t operator()(const PositionedUSig& x) const { + std::size_t operator()(const PositionedUSig &x) const + { size_t hash = x.layer; hash_combine(hash, x.pos); hash_combine(hash, usigHasher(x.usig)); return hash; } }; -struct SigVecHasher { +struct SigVecHasher +{ SignatureHasher _sig_hasher; - inline std::size_t operator()(const std::vector& s) const { + inline std::size_t operator()(const std::vector &s) const + { size_t hash = s.size(); - for (const Signature& sig : s) hash_combine(hash, _sig_hasher(sig)); + for (const Signature &sig : s) + hash_combine(hash, _sig_hasher(sig)); return hash; } }; @@ -136,8 +160,9 @@ struct SigVecHasher { typedef FlatHashSet SigSet; typedef FlatHashSet USigSet; -namespace Sig { - const static USignature NONE_SIG = USignature(-1, std::vector()); +namespace Sig +{ + const static USignature NONE_SIG = USignature(-1, {}); const static SigSet EMPTY_SIG_SET; const static USigSet EMPTY_USIG_SET; } diff --git a/src/data/substitution.cpp b/src/data/substitution.cpp index 1433c92..2ded606 100644 --- a/src/data/substitution.cpp +++ b/src/data/substitution.cpp @@ -4,76 +4,99 @@ #include "substitution.h" Substitution::Entry::Entry(int first, int second) : first(first), second(second) {} -Substitution::Entry::Entry(const Entry& other) : first(other.first), second(other.second) {} +Substitution::Entry::Entry(const Entry &other) : first(other.first), second(other.second) {} Substitution::Substitution() {} -Substitution::Substitution(const Substitution& other) : _entries(other._entries) {} -Substitution::Substitution(Substitution&& old) : _entries(std::move(old._entries)) {} +Substitution::Substitution(const Substitution &other) : _entries(other._entries) {} +Substitution::Substitution(Substitution &&old) : _entries(std::move(old._entries)) {} -Substitution::Substitution(const std::vector& src, const std::vector& dest) { +Substitution::Substitution(const std::basic_string &src, const std::basic_string &dest) +{ assert(src.size() == dest.size()); - for (size_t i = 0; i < src.size(); i++) { - if (src[i] != dest[i]) { + for (size_t i = 0; i < src.size(); i++) + { + if (src[i] != dest[i]) + { assert(!count(src[i]) || (*this)[src[i]] == dest[i]); add(src[i], dest[i]); } } } -void Substitution::clear() { +void Substitution::clear() +{ _entries.clear(); } -bool Substitution::empty() const { +bool Substitution::empty() const +{ return _entries.empty(); } -size_t Substitution::size() const { +size_t Substitution::size() const +{ size_t size = 0; auto it = _entries.begin(); - while (it != _entries.end()) {++it; size++;} + while (it != _entries.end()) + { + ++it; + size++; + } return size; } -Substitution Substitution::concatenate(const Substitution& second) const { +Substitution Substitution::concatenate(const Substitution &second) const +{ Substitution s; - for (const auto& [src, dest] : *this) { - if (second.count(dest)) { + for (const auto &[src, dest] : *this) + { + if (second.count(dest)) + { s[src] = second[dest]; - } else { + } + else + { s[src] = dest; } } - for (const auto& [src, dest] : second) { - if (!s.count(src)) s[src] = dest; + for (const auto &[src, dest] : second) + { + if (!s.count(src)) + s[src] = dest; } return s; } -std::vector Substitution::getAll(const std::vector& src, const std::vector& dest) { +std::vector Substitution::getAll(const std::basic_string &src, const std::basic_string &dest) +{ std::vector ss; ss.emplace_back(); // start with empty substitution assert(src.size() == dest.size()); - for (size_t i = 0; i < src.size(); i++) { + for (size_t i = 0; i < src.size(); i++) + { assert(src[i] != 0 && dest[i] != 0); - if (src[i] != dest[i]) { + if (src[i] != dest[i]) + { // Iterate over existing substitutions int priorSize = ss.size(); - for (int j = 0; j < priorSize; j++) { - Substitution& s = ss[j]; - + for (int j = 0; j < priorSize; j++) + { + Substitution &s = ss[j]; + // Does the substitution already have such a key but with a different value? auto it = s.find(src[i]); - if (it != s.end() && it->second != dest[i]) { + if (it != s.end() && it->second != dest[i]) + { // yes -- branch: keep original substitution, add alternative Substitution s1(s); s1[src[i]] = dest[i]; ss.push_back(s1); // overwritten substitution - - } else { + } + else + { // Just add to substitution s[src[i]] = dest[i]; } @@ -83,9 +106,11 @@ std::vector Substitution::getAll(const std::vector& src, cons return ss; } -std::forward_list::const_iterator Substitution::begin() const { +std::forward_list::const_iterator Substitution::begin() const +{ return _entries.begin(); } -std::forward_list::const_iterator Substitution::end() const { +std::forward_list::const_iterator Substitution::end() const +{ return _entries.end(); } diff --git a/src/data/substitution.h b/src/data/substitution.h index 6ae64ca..248471f 100644 --- a/src/data/substitution.h +++ b/src/data/substitution.h @@ -8,16 +8,19 @@ #include "util/hashmap.h" #include "util/hash.h" -class Substitution { +class Substitution +{ public: - struct Entry { - int first; + struct Entry + { + int first; int second; Entry(int first, int second); - Entry(const Entry& other); - inline bool operator==(const Entry& other) const { + Entry(const Entry &other); + inline bool operator==(const Entry &other) const + { return first == other.first && second == other.second; } }; @@ -27,27 +30,30 @@ class Substitution { public: Substitution(); - Substitution(const Substitution& other); - Substitution(Substitution&& old); - Substitution(const std::vector& src, const std::vector& dest); + Substitution(const Substitution &other); + Substitution(Substitution &&old); + Substitution(const std::basic_string &src, const std::basic_string &dest); void clear(); size_t size() const; bool empty() const; - Substitution concatenate(const Substitution& second) const; + Substitution concatenate(const Substitution &second) const; std::forward_list::const_iterator begin() const; std::forward_list::const_iterator end() const; - //static Substitution get(const std::vector& src, const std::vector& dest); - static std::vector getAll(const std::vector& src, const std::vector& dest); + // static Substitution get(const std::vector& src, const std::vector& dest); + static std::vector getAll(const std::basic_string &src, const std::basic_string &dest); - struct Hasher { - inline std::size_t operator()(const Substitution& s) const { + struct Hasher + { + inline std::size_t operator()(const Substitution &s) const + { size_t hash = 1337; - for (const auto& pair : s) { + for (const auto &pair : s) + { hash_combine(hash, pair.first); hash_combine(hash, pair.second); } @@ -56,33 +62,38 @@ class Substitution { } }; - inline int& operator[](const int& key) { + inline int &operator[](const int &key) + { auto it = _entries.begin(); // Empty list? - if (it == _entries.end()) { + if (it == _entries.end()) + { _entries.emplace_front(key, 0); return _entries.begin()->second; } // Scan entries auto nextIt = _entries.begin(); - while (it != _entries.end()) { - + while (it != _entries.end()) + { + // Key found: return associated value - if (it->first == key) return it->second; - + if (it->first == key) + return it->second; + // Peek next position ++nextIt; // Break if this is the position to insert - if (nextIt == _entries.end() || nextIt->first > key) break; + if (nextIt == _entries.end() || nextIt->first > key) + break; // Proceed to next position ++it; } - + // Insert, make iterator point to inserted entry _entries.emplace_after(it, key, 0); ++it; @@ -90,52 +101,63 @@ class Substitution { return it->second; } - inline int operator[](const int& key) const { + inline int operator[](const int &key) const + { return at(key); } - inline int at(const int& key) const { + inline int at(const int &key) const + { auto it = _entries.begin(); - while (it != _entries.end() && it->first != key) ++it; + while (it != _entries.end() && it->first != key) + ++it; return it->second; } - inline std::forward_list::const_iterator find(int key) const { + inline std::forward_list::const_iterator find(int key) const + { auto it = _entries.begin(); - while (it != _entries.end() && it->first != key) ++it; + while (it != _entries.end() && it->first != key) + ++it; return it; } - inline std::forward_list::iterator find(int key) { + inline std::forward_list::iterator find(int key) + { std::forward_list::iterator it = _entries.begin(); - while (it != _entries.end() && it->first != key) ++it; + while (it != _entries.end() && it->first != key) + ++it; return it; } - inline int count(const int& key) const { + inline int count(const int &key) const + { auto it = _entries.begin(); - while (it != _entries.end() && it->first != key) ++it; + while (it != _entries.end() && it->first != key) + ++it; return it != _entries.end(); } - - inline bool operator==(const Substitution& other) const { + inline bool operator==(const Substitution &other) const + { return _entries == other._entries; } - inline bool operator!=(const Substitution& other) const { + inline bool operator!=(const Substitution &other) const + { return !(*this == other); } - inline void operator=(const Substitution& other) { + inline void operator=(const Substitution &other) + { _entries = other._entries; } private: - inline void add(int key, int val) { + inline void add(int key, int val) + { (*this)[key] = val; } - }; #endif \ No newline at end of file diff --git a/src/data/substitution_constraint.h b/src/data/substitution_constraint.h index e7d07da..0dc999f 100644 --- a/src/data/substitution_constraint.h +++ b/src/data/substitution_constraint.h @@ -8,10 +8,16 @@ typedef LiteralTree IntPairTree; -class SubstitutionConstraint { +class SubstitutionConstraint +{ public: - enum Polarity {UNDECIDED, ANY_VALID, NO_INVALID}; + enum Polarity + { + UNDECIDED, + ANY_VALID, + NO_INVALID + }; private: std::vector _involved_q_consts; @@ -20,20 +26,19 @@ class SubstitutionConstraint { Polarity _polarity = UNDECIDED; public: - SubstitutionConstraint(const std::vector& involvedQConsts) : _involved_q_consts(involvedQConsts) {} - SubstitutionConstraint(std::vector&& involvedQConsts) : _involved_q_consts(std::move(involvedQConsts)) {} - SubstitutionConstraint(const SubstitutionConstraint& other) : - _involved_q_consts(other._involved_q_consts), - _valid_substitutions(other._valid_substitutions), - _invalid_substitutions(other._invalid_substitutions), - _polarity(other._polarity) {} - SubstitutionConstraint(SubstitutionConstraint&& other) : - _involved_q_consts(other._involved_q_consts), - _valid_substitutions(std::move(other._valid_substitutions)), - _invalid_substitutions(std::move(other._invalid_substitutions)), - _polarity(other._polarity) {} - - SubstitutionConstraint& operator=(const SubstitutionConstraint& other) { + SubstitutionConstraint(const std::vector &involvedQConsts) : _involved_q_consts(involvedQConsts) {} + SubstitutionConstraint(std::vector &&involvedQConsts) : _involved_q_consts(std::move(involvedQConsts)) {} + SubstitutionConstraint(const SubstitutionConstraint &other) : _involved_q_consts(other._involved_q_consts), + _valid_substitutions(other._valid_substitutions), + _invalid_substitutions(other._invalid_substitutions), + _polarity(other._polarity) {} + SubstitutionConstraint(SubstitutionConstraint &&other) : _involved_q_consts(other._involved_q_consts), + _valid_substitutions(std::move(other._valid_substitutions)), + _invalid_substitutions(std::move(other._invalid_substitutions)), + _polarity(other._polarity) {} + + SubstitutionConstraint &operator=(const SubstitutionConstraint &other) + { _involved_q_consts = other._involved_q_consts; _valid_substitutions = other._valid_substitutions; _invalid_substitutions = other._invalid_substitutions; @@ -41,102 +46,132 @@ class SubstitutionConstraint { return *this; } - void addValid(const std::vector& vals) { + void addValid(const std::vector &vals) + { _valid_substitutions.insert(vals); } - void addInvalid(const std::vector& vals) { + void addInvalid(const std::vector &vals) + { _invalid_substitutions.insert(vals); } - void fixPolarity(Polarity polarity = UNDECIDED) { + void fixPolarity(Polarity polarity = UNDECIDED) + { size_t negSize = _invalid_substitutions.getSizeOfNegationEncoding(); size_t posSize = _valid_substitutions.getSizeOfEncoding(); - if (polarity == ANY_VALID || (polarity == UNDECIDED && negSize > posSize)) { + if (polarity == ANY_VALID || (polarity == UNDECIDED && negSize > posSize)) + { // More invalids _invalid_substitutions = IntPairTree(); _polarity = ANY_VALID; - } else { + } + else + { // More valids _valid_substitutions = IntPairTree(); _polarity = NO_INVALID; } } - bool involvesSupersetOf(const std::vector& involvedQConsts) const { + bool involvesSupersetOf(const std::vector &involvedQConsts) const + { // Every q-constant in the query must also be in the involved q-constants // (in the same order), otherwise no meaningful check can be done size_t j = 0; - for (size_t i = 0; i < involvedQConsts.size(); i++) { + for (size_t i = 0; i < involvedQConsts.size(); i++) + { while (j < _involved_q_consts.size() && _involved_q_consts[j] != involvedQConsts[i]) j++; - if (j == _involved_q_consts.size()) return false; + if (j == _involved_q_consts.size()) + return false; } return true; } - bool isValid(const std::vector& sub, bool sameReference) const { - if (_polarity == ANY_VALID) { + bool isValid(const std::vector &sub, bool sameReference) const + { + if (_polarity == ANY_VALID) + { // Same involved q-constants: Can perform exact (in)validity check return sameReference ? _valid_substitutions.contains(sub) : _valid_substitutions.subsumes(sub); - } else { + } + else + { return sameReference ? !_invalid_substitutions.contains(sub) : !_invalid_substitutions.hasPathSubsumedBy(sub); } } - bool canMerge(const SubstitutionConstraint& other) const { - if (_polarity != other._polarity) return false; - if (_polarity == UNDECIDED) return false; + bool canMerge(const SubstitutionConstraint &other) const + { + if (_polarity != other._polarity) + return false; + if (_polarity == UNDECIDED) + return false; // Must have same _involved_q_consts return _involved_q_consts == other._involved_q_consts; } - void merge(SubstitutionConstraint&& other) { - if (_polarity == ANY_VALID) { + void merge(SubstitutionConstraint &&other) + { + if (_polarity == ANY_VALID) + { // intersect paths of both literal trees _valid_substitutions.intersect(std::move(other._valid_substitutions)); } - if (_polarity == NO_INVALID) { + if (_polarity == NO_INVALID) + { // unite paths of both literal trees _invalid_substitutions.merge(std::move(other._invalid_substitutions)); } } - std::vector> getEncoding(Polarity p = UNDECIDED) const { - if (p == ANY_VALID) return _valid_substitutions.encode(); - if (p == NO_INVALID) return _invalid_substitutions.encodeNegation(); - if (_polarity == ANY_VALID) return _valid_substitutions.encode(); + std::vector> getEncoding(Polarity p = UNDECIDED) const + { + if (p == ANY_VALID) + return _valid_substitutions.encode(); + if (p == NO_INVALID) + return _invalid_substitutions.encodeNegation(); + if (_polarity == ANY_VALID) + return _valid_substitutions.encode(); return _invalid_substitutions.encodeNegation(); } - size_t getEncodedSize() const { + size_t getEncodedSize() const + { return _valid_substitutions.getSizeOfEncoding() + _invalid_substitutions.getSizeOfNegationEncoding(); } - Polarity getPolarity() const {return _polarity;} + Polarity getPolarity() const { return _polarity; } - const std::vector& getInvolvedQConstants() const {return _involved_q_consts;} + const std::vector &getInvolvedQConstants() const { return _involved_q_consts; } - static std::vector getSortedSubstitutedArgIndices(HtnInstance& htn, const std::vector& qargs, const std::vector& sorts) { + static std::basic_string getSortedSubstitutedArgIndices(HtnInstance &htn, const std::basic_string &qargs, const std::basic_string &sorts) + { // Collect indices of arguments which will be substituted - std::vector argIndices; - for (size_t i = 0; i < qargs.size(); i++) { - if (htn.isQConstant(qargs[i])) argIndices.push_back(i); + std::basic_string argIndices; + for (size_t i = 0; i < qargs.size(); i++) + { + if (htn.isQConstant(qargs[i])) + argIndices.push_back(i); } // Sort argument indices by the potential size of their domain - std::sort(argIndices.begin(), argIndices.end(), - [&](int i, int j) {return htn.getConstantsOfSort(sorts[i]).size() < htn.getConstantsOfSort(sorts[j]).size();}); + std::sort(argIndices.begin(), argIndices.end(), + [&](int i, int j) + { return htn.getConstantsOfSort(sorts[i]).size() < htn.getConstantsOfSort(sorts[j]).size(); }); return argIndices; } - static std::vector decodingToPath(const std::vector& qArgs, const std::vector& decArgs, const std::vector& sortedIndices) { - + static std::vector decodingToPath(const std::basic_string &qArgs, const std::basic_string &decArgs, const std::basic_string &sortedIndices) + { + // Write argument substitutions into the result in correct order std::vector path; path.reserve(sortedIndices.size()); - for (size_t x = 0; x < sortedIndices.size(); x++) { + for (size_t x = 0; x < sortedIndices.size(); x++) + { size_t argIdx = sortedIndices[x]; path.emplace_back(IntPair(qArgs[argIdx], decArgs[argIdx])); } diff --git a/src/sat/decoder.h b/src/sat/decoder.h index 50271ed..11fe9c3 100644 --- a/src/sat/decoder.h +++ b/src/sat/decoder.h @@ -8,155 +8,187 @@ #include "sat/variable_provider.h" #include "data/plan.h" -class Decoder { +#include + +class Decoder +{ private: - HtnInstance& _htn; - std::vector& _layers; - SatInterface& _sat; - VariableProvider& _vars; + HtnInstance &_htn; + std::vector &_layers; + SatInterface &_sat; + VariableProvider &_vars; public: - Decoder(HtnInstance& htn, std::vector& layers, SatInterface& sat, VariableProvider& vars) : - _htn(htn), _layers(layers), _sat(sat), _vars(vars) {} + Decoder(HtnInstance &htn, std::vector &layers, SatInterface &sat, VariableProvider &vars) : _htn(htn), _layers(layers), _sat(sat), _vars(vars) {} - enum PlanExtraction {ALL, PRIMITIVE_ONLY}; - std::vector extractClassicalPlan(PlanExtraction mode = PRIMITIVE_ONLY) { + enum PlanExtraction + { + ALL, + PRIMITIVE_ONLY + }; + std::vector extractClassicalPlan(PlanExtraction mode = PRIMITIVE_ONLY) + { - Layer& finalLayer = *_layers.back(); + Layer &finalLayer = *_layers.back(); int li = finalLayer.index(); - //VariableDomain::lock(); + // VariableDomain::lock(); std::vector plan(finalLayer.size()); - //log("(actions at layer %i)\n", li); - for (size_t pos = 0; pos < finalLayer.size(); pos++) { - //log("%i\n", pos); + // log("(actions at layer %i)\n", li); + for (size_t pos = 0; pos < finalLayer.size(); pos++) + { + // log("%i\n", pos); // Print out the state Log::d("PLANDBG %i,%i S ", li, pos); - for (const auto& [sig, fVar] : finalLayer[pos].getVariableTable(VarType::FACT)) { - if (_sat.holds(fVar)) Log::log_notime(Log::V4_DEBUG, "%s ", TOSTR(sig)); + for (const auto &[sig, fVar] : finalLayer[pos].getVariableTable(VarType::FACT)) + { + if (_sat.holds(fVar)) + Log::log_notime(Log::V4_DEBUG, "%s ", TOSTR(sig)); } Log::log_notime(Log::V4_DEBUG, "\n"); int chosenActions = 0; - //State newState = state; - for (const auto& [sig, aVar] : finalLayer[pos].getVariableTable(VarType::OP)) { - if (!_sat.holds(aVar)) continue; + // State newState = state; + for (const auto &[sig, aVar] : finalLayer[pos].getVariableTable(VarType::OP)) + { + if (!_sat.holds(aVar)) + continue; USignature aSig = sig; - if (mode == PRIMITIVE_ONLY && !_htn.isAction(aSig)) continue; + if (mode == PRIMITIVE_ONLY && !_htn.isAction(aSig)) + continue; - if (_htn.isActionRepetition(aSig._name_id)) { + if (_htn.isActionRepetition(aSig._name_id)) + { aSig._name_id = _htn.getActionNameFromRepetition(sig._name_id); } - //log(" %s ?\n", TOSTR(aSig)); + // log(" %s ?\n", TOSTR(aSig)); chosenActions++; - + Log::d("PLANDBG %i,%i A %s\n", li, pos, TOSTR(aSig)); // Decode q constants USignature aDec = getDecodedQOp(li, pos, aSig); - if (aDec == Sig::NONE_SIG) continue; + if (aDec == Sig::NONE_SIG) + continue; plan[pos] = {aVar, aDec, aDec, std::vector()}; } assert(chosenActions <= 1 || Log::e("Plan error: Added %i actions at step %i!\n", chosenActions, pos)); - if (chosenActions == 0) { + if (chosenActions == 0) + { plan[pos] = {-1, USignature(), USignature(), std::vector()}; } } - //log("%i actions at final layer of size %i\n", plan.size(), _layers->back().size()); + // log("%i actions at final layer of size %i\n", plan.size(), _layers->back().size()); return plan; } - Plan extractPlan() { + Plan extractPlan() + { auto result = Plan(); - auto& [classicalPlan, plan] = result; + auto &[classicalPlan, plan] = result; classicalPlan = extractClassicalPlan(); - + std::vector itemsOldLayer, itemsNewLayer; - for (size_t layerIdx = 0; layerIdx < _layers.size(); layerIdx++) { - Layer& l = *_layers.at(layerIdx); - //log("(decomps at layer %i)\n", l.index()); + for (size_t layerIdx = 0; layerIdx < _layers.size(); layerIdx++) + { + Layer &l = *_layers.at(layerIdx); + // log("(decomps at layer %i)\n", l.index()); itemsNewLayer.resize(l.size()); - - for (size_t pos = 0; pos < l.size(); pos++) { + + for (size_t pos = 0; pos < l.size(); pos++) + { size_t predPos = 0; - if (layerIdx > 0) { - Layer& lastLayer = *_layers.at(layerIdx-1); - while (predPos+1 < lastLayer.size() && lastLayer.getSuccessorPos(predPos+1) <= pos) + if (layerIdx > 0) + { + Layer &lastLayer = *_layers.at(layerIdx - 1); + while (predPos + 1 < lastLayer.size() && lastLayer.getSuccessorPos(predPos + 1) <= pos) predPos++; - } - //log("%i -> %i\n", predPos, pos); + } + // log("%i -> %i\n", predPos, pos); int actionsThisPos = 0; int reductionsThisPos = 0; - for (const auto& [opSig, v] : l[pos].getVariableTable(VarType::OP)) { + for (const auto &[opSig, v] : l[pos].getVariableTable(VarType::OP)) + { - if (_sat.holds(v)) { + if (_sat.holds(v)) + { - if (_htn.isAction(opSig)) { + if (_htn.isAction(opSig)) + { // Action actionsThisPos++; - const USignature& aSig = opSig; + const USignature &aSig = opSig; - if (aSig == _htn.getBlankActionSig()) continue; - if (_htn.isActionRepetition(aSig._name_id)) { + if (aSig == _htn.getBlankActionSig()) + continue; + if (_htn.isActionRepetition(aSig._name_id)) + { continue; } - + int v = _vars.getVariable(VarType::OP, layerIdx, pos, aSig); Action a = _htn.getOpTable().getAction(aSig); // TODO check this is a valid subtask relationship - Log::d("[%i] %s @ (%i,%i)\n", v, TOSTR(aSig), layerIdx, pos); + Log::d("[%i] %s @ (%i,%i)\n", v, TOSTR(aSig), layerIdx, pos); // Find the actual action variable at the final layer, not at this (inner) layer size_t l = layerIdx; int aPos = pos; - while (l+1 < _layers.size()) { - //log("(%i,%i) => ", l, aPos); + while (l + 1 < _layers.size()) + { + // log("(%i,%i) => ", l, aPos); aPos = _layers.at(l)->getSuccessorPos(aPos); l++; - //log("(%i,%i)\n", l, aPos); + // log("(%i,%i)\n", l, aPos); } v = classicalPlan[aPos].id; // *_layers.at(l-1)[aPos]._vars.getVariable(aSig); - //assert(v > 0 || Log::e("%s : v=%i\n", TOSTR(aSig), v)); - if (v > 0 && layerIdx > 0) { + // assert(v > 0 || Log::e("%s : v=%i\n", TOSTR(aSig), v)); + if (v > 0 && layerIdx > 0) + { itemsOldLayer[predPos].subtaskIds.push_back(v); - } else if (v <= 0) { + } + else if (v <= 0) + { Log::d(" -- invalid: not part of classical plan\n"); } - //itemsNewLayer[pos] = PlanItem({v, aSig, aSig, std::vector()}); - - } else if (_htn.isReduction(opSig)) { + // itemsNewLayer[pos] = PlanItem({v, aSig, aSig, std::vector()}); + } + else if (_htn.isReduction(opSig)) + { // Reduction - const USignature& rSig = opSig; - const Reduction& r = _htn.getOpTable().getReduction(rSig); + const USignature &rSig = opSig; + const Reduction &r = _htn.getOpTable().getReduction(rSig); - //log("%s:%s @ (%i,%i)\n", TOSTR(r.getTaskSignature()), TOSTR(rSig), layerIdx, pos); + // log("%s:%s @ (%i,%i)\n", TOSTR(r.getTaskSignature()), TOSTR(rSig), layerIdx, pos); USignature decRSig = getDecodedQOp(layerIdx, pos, rSig); - if (decRSig == Sig::NONE_SIG) continue; + if (decRSig == Sig::NONE_SIG) + continue; Reduction rDecoded = r.substituteRed(Substitution(r.getArguments(), decRSig._args)); Log::d("[%i] %s:%s @ (%i,%i)\n", v, TOSTR(rDecoded.getTaskSignature()), TOSTR(decRSig), layerIdx, pos); - if (layerIdx == 0) { + if (layerIdx == 0) + { // Initial reduction - PlanItem root(0, - USignature(_htn.nameId("root"), std::vector()), - decRSig, std::vector()); + PlanItem root(0, + USignature(_htn.nameId("root"), {}), + decRSig, std::vector()); itemsNewLayer[0] = root; reductionsThisPos++; continue; @@ -164,18 +196,20 @@ class Decoder { // Lookup parent reduction Reduction parentRed; - size_t offset = pos - _layers.at(layerIdx-1)->getSuccessorPos(predPos); - PlanItem& parent = itemsOldLayer[predPos]; - assert(parent.id >= 0 || Log::e("Plan error: No parent at %i,%i!\n", layerIdx-1, predPos)); - assert(_htn.isReduction(parent.reduction) || - Log::e("Plan error: Invalid reduction id=%i at %i,%i!\n", parent.reduction._name_id, layerIdx-1, predPos)); + size_t offset = pos - _layers.at(layerIdx - 1)->getSuccessorPos(predPos); + PlanItem &parent = itemsOldLayer[predPos]; + assert(parent.id >= 0 || Log::e("Plan error: No parent at %i,%i!\n", layerIdx - 1, predPos)); + assert(_htn.isReduction(parent.reduction) || + Log::e("Plan error: Invalid reduction id=%i at %i,%i!\n", parent.reduction._name_id, layerIdx - 1, predPos)); parentRed = _htn.toReduction(parent.reduction._name_id, parent.reduction._args); // Is the current reduction a proper subtask? assert(offset < parentRed.getSubtasks().size()); - if (parentRed.getSubtasks()[offset] == rDecoded.getTaskSignature()) { - if (itemsOldLayer[predPos].subtaskIds.size() > offset) { + if (parentRed.getSubtasks()[offset] == rDecoded.getTaskSignature()) + { + if (itemsOldLayer[predPos].subtaskIds.size() > offset) + { // This subtask has already been written! Log::d(" -- is a redundant child -> dismiss\n"); continue; @@ -183,7 +217,9 @@ class Decoder { itemsNewLayer[pos] = PlanItem(v, rDecoded.getTaskSignature(), decRSig, std::vector()); itemsOldLayer[predPos].subtaskIds.push_back(v); reductionsThisPos++; - } else { + } + else + { Log::d(" -- invalid : %s != %s\n", TOSTR(parentRed.getSubtasks()[offset]), TOSTR(rDecoded.getTaskSignature())); } } @@ -194,8 +230,7 @@ class Decoder { assert(actionsThisPos <= 1 || Log::e("Plan error: %i actions at (%i,%i)!\n", actionsThisPos, layerIdx, pos)); // Either actions OR reductions per position (not both) - assert(actionsThisPos == 0 || reductionsThisPos == 0 - || Log::e("Plan error: %i actions and %i reductions at (%i,%i)!\n", actionsThisPos, reductionsThisPos, layerIdx, pos)); + assert(actionsThisPos == 0 || reductionsThisPos == 0 || Log::e("Plan error: %i actions and %i reductions at (%i,%i)!\n", actionsThisPos, reductionsThisPos, layerIdx, pos)); } plan.insert(plan.end(), itemsOldLayer.begin(), itemsOldLayer.end()); @@ -208,51 +243,61 @@ class Decoder { return result; } - bool value(VarType type, int layer, int pos, const USignature& sig) { + bool value(VarType type, int layer, int pos, const USignature &sig) + { int v = _vars.getVariable(type, layer, pos, sig); Log::d("VAL %s@(%i,%i)=%i %i\n", TOSTR(sig), layer, pos, v, _sat.holds(v)); return _sat.holds(v); } - - USignature getDecodedQOp(int layer, int pos, const USignature& origSig) { - //assert(isEncoded(VarType::OP, layer, pos, origSig)); - //assert(value(VarType::OP, layer, pos, origSig)); + USignature getDecodedQOp(int layer, int pos, const USignature &origSig) + { + // assert(isEncoded(VarType::OP, layer, pos, origSig)); + // assert(value(VarType::OP, layer, pos, origSig)); USignature sig = origSig; - while (true) { + while (true) + { bool containsQConstants = false; - for (int arg : sig._args) if (_htn.isQConstant(arg)) { - // q constant found - containsQConstants = true; - - int numSubstitutions = 0; - for (int argSubst : _htn.getDomainOfQConstant(arg)) { - const USignature& sigSubst = _vars.sigSubstitute(arg, argSubst); - if (_vars.isEncodedSubstitution(sigSubst) && _sat.holds(_vars.varSubstitution(arg, argSubst))) { - Log::d("SUBSTVAR [%s/%s] TRUE => %s ~~> ", TOSTR(arg), TOSTR(argSubst), TOSTR(sig)); - numSubstitutions++; - Substitution sub; - sub[arg] = argSubst; - sig.apply(sub); - Log::d("%s\n", TOSTR(sig)); - } else { - //Log::d("%i FALSE\n", varSubstitution(sigSubst)); + for (int arg : sig._args) + if (_htn.isQConstant(arg)) + { + // q constant found + containsQConstants = true; + + int numSubstitutions = 0; + for (int argSubst : _htn.getDomainOfQConstant(arg)) + { + const USignature &sigSubst = _vars.sigSubstitute(arg, argSubst); + if (_vars.isEncodedSubstitution(sigSubst) && _sat.holds(_vars.varSubstitution(arg, argSubst))) + { + Log::d("SUBSTVAR [%s/%s] TRUE => %s ~~> ", TOSTR(arg), TOSTR(argSubst), TOSTR(sig)); + numSubstitutions++; + Substitution sub; + sub[arg] = argSubst; + sig.apply(sub); + Log::d("%s\n", TOSTR(sig)); + } + else + { + // Log::d("%i FALSE\n", varSubstitution(sigSubst)); + } } - } - if (numSubstitutions == 0) { - Log::v("(%i,%i) No substitutions for arg %s of %s\n", layer, pos, TOSTR(arg), TOSTR(origSig)); - return Sig::NONE_SIG; + if (numSubstitutions == 0) + { + Log::v("(%i,%i) No substitutions for arg %s of %s\n", layer, pos, TOSTR(arg), TOSTR(origSig)); + return Sig::NONE_SIG; + } + assert(numSubstitutions == 1 || Log::e("%i substitutions for arg %s of %s\n", numSubstitutions, TOSTR(arg), TOSTR(origSig))); } - assert(numSubstitutions == 1 || Log::e("%i substitutions for arg %s of %s\n", numSubstitutions, TOSTR(arg), TOSTR(origSig))); - } - if (!containsQConstants) break; // done + if (!containsQConstants) + break; // done } - //if (origSig != sig) Log::d("%s ~~> %s\n", TOSTR(origSig), TOSTR(sig)); - + // if (origSig != sig) Log::d("%s ~~> %s\n", TOSTR(origSig), TOSTR(sig)); + return sig; } }; diff --git a/src/sat/variable_provider.h b/src/sat/variable_provider.h index ca7b2c4..45bc722 100644 --- a/src/sat/variable_provider.h +++ b/src/sat/variable_provider.h @@ -6,52 +6,60 @@ #include "data/layer.h" #include "util/params.h" -class VariableProvider { +class VariableProvider +{ private: - HtnInstance& _htn; - std::vector& _layers; - + HtnInstance &_htn; + std::vector &_layers; + NodeHashMap _substitution_variables; USignature _sig_primitive; USignature _sig_substitution; int _substitute_name_id; FlatHashMap, int, IntPairHasher> _q_equality_variables; - -public: - VariableProvider(Parameters& params, HtnInstance& htn, std::vector& layers) : _htn(htn), _layers(layers) { - _sig_primitive = USignature(_htn.nameId("__PRIMITIVE___"), std::vector()); +public: + VariableProvider(Parameters ¶ms, HtnInstance &htn, std::vector &layers) : _htn(htn), _layers(layers) + { + _sig_primitive = USignature(_htn.nameId("__PRIMITIVE___"), {}); _substitute_name_id = _htn.nameId("__SUBSTITUTE___"); - _sig_substitution = USignature(_substitute_name_id, std::vector(2)); + _sig_substitution = USignature(_substitute_name_id, std::basic_string(2, 0)); VariableDomain::init(params); } - inline bool isEncoded(VarType type, int layer, int pos, const USignature& sig) { + inline bool isEncoded(VarType type, int layer, int pos, const USignature &sig) + { return _layers.at(layer)->at(pos).hasVariable(type, sig); } - inline int getVariable(VarType type, int layer, int pos, const USignature& sig) { + inline int getVariable(VarType type, int layer, int pos, const USignature &sig) + { return getVariable(type, _layers[layer]->at(pos), sig); } - inline int getVariable(VarType type, const Position& pos, const USignature& sig) { + inline int getVariable(VarType type, const Position &pos, const USignature &sig) + { return pos.getVariable(type, sig); } - inline int encodeVariable(VarType type, Position& pos, const USignature& sig) { + inline int encodeVariable(VarType type, Position &pos, const USignature &sig) + { int var = pos.getVariableOrZero(type, sig); - if (var == 0) var = pos.encode(type, sig); + if (var == 0) + var = pos.encode(type, sig); return var; } - bool isEncodedSubstitution(const USignature& sig) { + bool isEncodedSubstitution(const USignature &sig) + { return _substitution_variables.count(sig); } - const USignature& sigSubstitute(int qConstId, int trueConstId) { - //assert(!_htn.isQConstant(trueConstId) || trueConstId < qConstId); - auto& args = _sig_substitution._args; + const USignature &sigSubstitute(int qConstId, int trueConstId) + { + // assert(!_htn.isQConstant(trueConstId) || trueConstId < qConstId); + auto &args = _sig_substitution._args; assert(_htn.isQConstant(qConstId)); assert(!_htn.isQConstant(trueConstId)); @@ -60,42 +68,53 @@ class VariableProvider { return _sig_substitution; } - int varSubstitution(int qConstId, int trueConstId) { - const USignature& sigSubst = sigSubstitute(qConstId, trueConstId); + int varSubstitution(int qConstId, int trueConstId) + { + const USignature &sigSubst = sigSubstitute(qConstId, trueConstId); int var; - if (!_substitution_variables.count(sigSubst)) { + if (!_substitution_variables.count(sigSubst)) + { assert(!VariableDomain::isLocked() || Log::e("Unknown substitution variable %s queried!\n", TOSTR(sigSubst))); var = VariableDomain::nextVar(); _substitution_variables[sigSubst] = var; VariableDomain::printVar(var, -1, -1, sigSubst); //_no_decision_variables.push_back(var); - } else var = _substitution_variables[sigSubst]; + } + else + var = _substitution_variables[sigSubst]; return var; } - int encodeVarPrimitive(int layer, int pos) { + int encodeVarPrimitive(int layer, int pos) + { return encodeVariable(VarType::OP, _layers.at(layer)->at(pos), _sig_primitive); } - int getVarPrimitiveOrZero(int layer, int pos) { + int getVarPrimitiveOrZero(int layer, int pos) + { return _layers.at(layer)->at(pos).getVariableOrZero(VarType::OP, _sig_primitive); } - bool isQConstantEqualityEncoded(int qconst1, int qconst2) { + bool isQConstantEqualityEncoded(int qconst1, int qconst2) + { return _q_equality_variables.count(IntPair(qconst1, qconst2)); } - int encodeQConstantEqualityVar(int qconst1, int qconst2) { + int encodeQConstantEqualityVar(int qconst1, int qconst2) + { int var = VariableDomain::nextVar(); _q_equality_variables[IntPair(qconst1, qconst2)] = var; return var; } - int getQConstantEqualityVar(int qconst1, int qconst2) { + int getQConstantEqualityVar(int qconst1, int qconst2) + { return _q_equality_variables[IntPair(qconst1, qconst2)]; } - void skipVariable() { + void skipVariable() + { VariableDomain::nextVar(); } - int getNumVariables() { + int getNumVariables() + { return VariableDomain::getMaxVar(); } }; diff --git a/src/test/test_arg_iterator.cpp b/src/test/test_arg_iterator.cpp index 2e8b9df..6fdc63c 100644 --- a/src/test/test_arg_iterator.cpp +++ b/src/test/test_arg_iterator.cpp @@ -6,14 +6,16 @@ #include "algo/arg_iterator.h" #include "algo/sample_arg_iterator.h" -void printSig(const USignature& sig) { +void printSig(const USignature &sig) +{ Log::i("(%i", sig._name_id); - for (int arg : sig._args) Log::log_notime(Log::V2_INFORMATION, " %i", arg); - Log::log_notime(Log::V2_INFORMATION, ")\n"); + for (int arg : sig._args) + Log::log_notime(Log::V2_INFORMATION, " %i", arg); + Log::log_notime(Log::V2_INFORMATION, ")\n"); } - -int main(int argc, char** argv) { +int main(int argc, char **argv) +{ Timer::init(); @@ -26,13 +28,14 @@ int main(int argc, char** argv) { int nameId = 42; { - std::vector args1{1, 2, 3, 4}; - std::vector args2{5}; - std::vector args3{6, 7}; - std::vector> eligibleArgs{args1, args2, args3}; + std::basic_string args1{1, 2, 3, 4}; + std::basic_string args2{5}; + std::basic_string args3{6, 7}; + std::vector> eligibleArgs{args1, args2, args3}; size_t numInstantiations = 0; - for (const auto& sig : ArgIterator(nameId, std::move(eligibleArgs))) { + for (const auto &sig : ArgIterator(nameId, std::move(eligibleArgs))) + { assert(sig._name_id == nameId); printSig(sig); numInstantiations++; @@ -41,11 +44,12 @@ int main(int argc, char** argv) { } { - std::vector args{1, 2}; - std::vector> eligibleArgs{args}; + std::basic_string args{1, 2}; + std::vector> eligibleArgs{args}; size_t numInstantiations = 0; - for (const auto& sig : ArgIterator(nameId, std::move(eligibleArgs))) { + for (const auto &sig : ArgIterator(nameId, std::move(eligibleArgs))) + { assert(sig._name_id == nameId); printSig(sig); numInstantiations++; @@ -54,13 +58,14 @@ int main(int argc, char** argv) { } { - std::vector args1{1}; - std::vector args2{2}; - std::vector args3{3}; - std::vector> eligibleArgs{args1, args2, args3}; + std::basic_string args1{1}; + std::basic_string args2{2}; + std::basic_string args3{3}; + std::vector> eligibleArgs{args1, args2, args3}; size_t numInstantiations = 0; - for (const auto& sig : ArgIterator(nameId, std::move(eligibleArgs))) { + for (const auto &sig : ArgIterator(nameId, std::move(eligibleArgs))) + { assert(sig._name_id == nameId); printSig(sig); numInstantiations++; @@ -69,26 +74,28 @@ int main(int argc, char** argv) { } { - std::vector> eligibleArgs{}; + std::vector> eligibleArgs{}; size_t numInstantiations = 0; - for (const auto& sig : ArgIterator(nameId, std::move(eligibleArgs))) { + for (const auto &sig : ArgIterator(nameId, std::move(eligibleArgs))) + { assert(sig._name_id == nameId); printSig(sig); numInstantiations++; } assert(numInstantiations == 0); } - + { - std::vector args1{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::vector args2{1, 2, 3, 4, 5, 6, 7, 8}; - std::vector args3{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::vector args4{1, 2, 3, 4, 5, 6, 7, 8, 9}; - std::vector> eligibleArgs{args1, args2, args3, args4}; + std::basic_string args1{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + std::basic_string args2{1, 2, 3, 4, 5, 6, 7, 8}; + std::basic_string args3{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + std::basic_string args4{1, 2, 3, 4, 5, 6, 7, 8, 9}; + std::vector> eligibleArgs{args1, args2, args3, args4}; size_t numInstantiations = 0; - for (const auto& sig : ArgIterator(nameId, std::move(eligibleArgs))) { + for (const auto &sig : ArgIterator(nameId, std::move(eligibleArgs))) + { assert(sig._name_id == nameId); printSig(sig); numInstantiations++; @@ -96,27 +103,28 @@ int main(int argc, char** argv) { assert(numInstantiations == args1.size() * args2.size() * args3.size() * args4.size()); } - /////// SampleArgIterator //////// { Random::init(1, 1); - std::vector args1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - std::vector args2{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - std::vector args3{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - std::vector args4{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - std::vector> eligibleArgs{args1, args2, args3, args4}; + std::basic_string args1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + std::basic_string args2{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + std::basic_string args3{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + std::basic_string args4{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + std::vector> eligibleArgs{args1, args2, args3, args4}; size_t numInstantiations = 0; size_t numSamples = 100; auto c = eligibleArgs; - for (const auto& sig : SampleArgIterator(nameId, std::move(c), numSamples)) { + for (const auto &sig : SampleArgIterator(nameId, std::move(c), numSamples)) + { printSig(sig); assert(sig._name_id == nameId); assert(sig._args.size() == eligibleArgs.size()); - for (size_t i = 0; i < sig._args.size(); i++) { - const auto& a = eligibleArgs[i]; + for (size_t i = 0; i < sig._args.size(); i++) + { + const auto &a = eligibleArgs[i]; assert(std::find(a.begin(), a.end(), sig._args[i]) != a.end()); } numInstantiations++; diff --git a/src/util/names.cpp b/src/util/names.cpp index d6d339b..4e8dddf 100644 --- a/src/util/names.cpp +++ b/src/util/names.cpp @@ -5,131 +5,169 @@ #include "util/names.h" #include "util/log.h" -NodeHashMap* nbt; +NodeHashMap *nbt; -namespace Names { - - void init(NodeHashMap& nameBackTable) { +namespace Names +{ + + void init(NodeHashMap &nameBackTable) + { nbt = &nameBackTable; } - std::string to_string(int nameId) { - if (nameId <= 0) return std::to_string(nameId); + std::string to_string(int nameId) + { + if (nameId <= 0) + return std::to_string(nameId); assert(nbt->count(nameId) || Log::e("No name known with ID %i!\n", nameId)); return nbt->at(nameId); } - std::string to_string(const std::vector& nameIds) { + std::string to_string(const std::vector &nameIds) + { std::string out = "("; bool first = true; - for (const int& id : nameIds) { + for (const int &id : nameIds) + { out += (first ? "" : " ") + std::string(id < 0 ? "-" : "") + Names::to_string(std::abs(id)); first = false; } return out + ")"; } - std::string to_string(const std::vector& nameIdPairs) { + std::string to_string(const std::vector &nameIdPairs) + { std::string out = "("; bool first = true; - for (const auto& [left, right] : nameIdPairs) { - out += (first ? "(" : " (") - + std::string(left < 0 ? "-" : "") + Names::to_string(std::abs(left)) - + "," - + std::string(right < 0 ? "-" : "") + Names::to_string(std::abs(right)) - + ")"; + for (const auto &[left, right] : nameIdPairs) + { + out += (first ? "(" : " (") + std::string(left < 0 ? "-" : "") + Names::to_string(std::abs(left)) + "," + std::string(right < 0 ? "-" : "") + Names::to_string(std::abs(right)) + ")"; first = false; } return out + ")"; } - std::string to_string(const USignature& sig) { + std::string to_string(const USignature &sig) + { std::string out = ""; out += "(" + to_string(sig._name_id); - for (int arg : sig._args) { + for (int arg : sig._args) + { out += " " + to_string(arg); } out += ")"; return out; } - std::string to_string(const Signature& sig) { + std::string to_string(const Signature &sig) + { std::string out = ""; - if (sig._negated) out += "!"; + if (sig._negated) + out += "!"; out += "(" + to_string(sig._usig._name_id); - for (int arg : sig._usig._args) { + for (int arg : sig._usig._args) + { out += " " + to_string(arg); } out += ")"; return out; } - std::string to_string(const PositionedUSig& sig) { + std::string to_string(const PositionedUSig &sig) + { std::string out = to_string(sig.usig) + "@(" + std::to_string(sig.layer) + "," + std::to_string(sig.pos) + ")"; return out; } - std::string to_string_nobrackets(const USignature& sig) { + std::string to_string_nobrackets(const USignature &sig) + { std::string out = ""; out += to_string(sig._name_id); - for (int arg : sig._args) { + for (int arg : sig._args) + { out += " " + to_string(arg); } return out; } - std::string to_string(const FlatHashMap& s) { + std::string to_string(const FlatHashMap &s) + { std::string out = ""; - for (const auto& pair : s) { + for (const auto &pair : s) + { out += "[" + to_string(pair.first) + "/" + to_string(pair.second) + "]"; } return out; } - std::string to_string(const Action& a) { + std::string to_string(const Action &a) + { std::string out = "{ "; - for (const Signature& pre : a.getPreconditions()) { + for (const Signature &pre : a.getPreconditions()) + { out += to_string(pre) + " "; } out += "} " + to_string(a.getSignature()) + " { "; - for (const Signature& eff : a.getEffects()) { + for (const Signature &eff : a.getEffects()) + { out += to_string(eff) + " "; } return out + "}"; } - std::string to_string(const USigSet& set) { + std::string to_string(const USigSet &set) + { std::string out = "{ "; - for (const USignature& sig : set) { + for (const USignature &sig : set) + { out += to_string(sig) + " "; } return out + "}"; } - std::string to_string(const SigSet& set) { + std::string to_string(const SigSet &set) + { std::string out = "{ "; - for (const Signature& sig : set) { + for (const Signature &sig : set) + { out += to_string(sig) + " "; } return out + "}"; } - std::string to_string(const FactFrame& f) { + std::string to_string(const FactFrame &f) + { std::string out = "{\n"; - for (const Signature& pre : f.preconditions) { + for (const Signature &pre : f.preconditions) + { out += " " + to_string(pre) + "\n"; } out += "} " + to_string(f.sig) + " {\n"; - for (const auto& eff : f.effects) { + for (const auto &eff : f.effects) + { out += " " + to_string(eff) + "\n"; } return out + "}"; } - std::string to_string(const Substitution& s) { + std::string to_string(const Substitution &s) + { std::string out = ""; - for (const auto& [src, dest] : s) { + for (const auto &[src, dest] : s) + { out += "[" + to_string(src) + "/" + to_string(dest) + "]"; } return out; } + + std::string to_string(const std::basic_string &str) + { + std::string out = "("; + bool first = true; + for (const int &id : str) + { + out += (first ? "" : " ") + std::string(id < 0 ? "-" : "") + Names::to_string(std::abs(id)); + first = false; + } + return out + ")"; + } } \ No newline at end of file diff --git a/src/util/names.h b/src/util/names.h index 4dfc5f2..6fe7fa4 100644 --- a/src/util/names.h +++ b/src/util/names.h @@ -10,21 +10,23 @@ #define TOSTR(x) Names::to_string(x).c_str() -namespace Names { - void init(NodeHashMap& nameBackTable); +namespace Names +{ + void init(NodeHashMap &nameBackTable); std::string to_string(int nameId); - std::string to_string(const std::vector& nameIds); - std::string to_string(const std::vector& nameIds); - std::string to_string(const USignature& sig); - std::string to_string(const Signature& sig); - std::string to_string(const PositionedUSig& sig); - std::string to_string_nobrackets(const USignature& sig); - std::string to_string(const FlatHashMap& s); - std::string to_string(const Action& a); - std::string to_string(const SigSet& set); - std::string to_string(const USigSet& set); - std::string to_string(const FactFrame& f); - std::string to_string(const Substitution& s); + std::string to_string(const std::vector &nameIds); + std::string to_string(const std::vector &nameIds); + std::string to_string(const USignature &sig); + std::string to_string(const Signature &sig); + std::string to_string(const PositionedUSig &sig); + std::string to_string_nobrackets(const USignature &sig); + std::string to_string(const FlatHashMap &s); + std::string to_string(const Action &a); + std::string to_string(const SigSet &set); + std::string to_string(const USigSet &set); + std::string to_string(const FactFrame &f); + std::string to_string(const Substitution &s); + std::string to_string(const std::basic_string &str); } #endif \ No newline at end of file