diff --git a/core/Storage.hh b/core/Storage.hh index ece1cf6fbb..13884d6ddb 100644 --- a/core/Storage.hh +++ b/core/Storage.hh @@ -161,7 +161,14 @@ namespace cadabra { /// FIXME: the following should implement a stack of states, /// so that it can be used with nested functions. - enum result_t { l_checkpointed, l_no_action, l_applied, l_applied_no_new_dummies, l_error }; + enum result_t { + l_checkpointed, + l_no_action, + l_applied, + l_applied_no_new_dummies, + l_error, + l_cached + }; result_t state() const; void update_state(result_t); void reset_state(); @@ -170,6 +177,14 @@ namespace cadabra { /// apply algorithms until they converge. Returns true when the /// expression is in 'checkpointed' or 'applied' state. Will /// set the state to 'no_action'. + /// + /// This is used in `cadabra::convert_line` defined in `CdbPython.cc`, + /// which essentially defines `converge(ex): [block]` to mean + /// + /// ex.reset_state() + /// while ex.changed(): + /// [block] + bool changed_state(); /// Test if the expression is a rational number. diff --git a/core/algorithms/substitute.cc b/core/algorithms/substitute.cc index b56a3289c9..874ce8e5e2 100644 --- a/core/algorithms/substitute.cc +++ b/core/algorithms/substitute.cc @@ -473,6 +473,7 @@ void substitute::Rules::store(Ex& rules, cleanup_threshold = max_size; } } + // If we're too big, don't add anything else. if (properties.size() >= max_size) { return; @@ -480,8 +481,9 @@ void substitute::Rules::store(Ex& rules, std::weak_ptr rules_ptr = rules.shared_from_this(); properties[rules_ptr] = { lhs_contains_dummies, rhs_contains_dummies }; - // Set state of rules to l_checkpointed to track if the rules ever change - rules.reset_state(); + // Mark this expression as cached; any change will remove that state + // and ensure that we do not use the cached expression later. + rules.update_state(result_t::l_cached); } catch(const std::bad_weak_ptr& error) { return; @@ -490,16 +492,16 @@ void substitute::Rules::store(Ex& rules, void substitute::Rules::retrieve(Ex& rules, std::map& lhs_contains_dummies, - std::map& rhs_contains_dummies) { - + std::map& rhs_contains_dummies) const + { // Rules::present is assumed to have been called to check that the rules are valid std::weak_ptr rules_ptr = rules.shared_from_this(); - lhs_contains_dummies = properties[rules_ptr].first; - rhs_contains_dummies = properties[rules_ptr].second; -} + lhs_contains_dummies = properties.at(rules_ptr).first; + rhs_contains_dummies = properties.at(rules_ptr).second; + } -bool substitute::Rules::is_present(Ex& rules) +bool substitute::Rules::is_present(Ex& rules) const { // Look to see if the rules are present in the map @@ -509,7 +511,7 @@ bool substitute::Rules::is_present(Ex& rules) if (!rule_found) return false; // rules should have l_checkpointed set - bool rule_unchanged = (rules.state() == result_t::l_checkpointed); + bool rule_unchanged = (rules.state() == result_t::l_cached); // If rule has been changed, erase it. if (!rule_unchanged) { @@ -525,11 +527,13 @@ bool substitute::Rules::is_present(Ex& rules) } } -int substitute::Rules::size() { +int substitute::Rules::size() const + { return properties.size(); -} + } -void substitute::Rules::cleanup() { +void substitute::Rules::cleanup() + { // Erase rules that are pointing to garbage-collected Ex expressions // or rules that have possibly been changed. for (auto it = properties.begin(); it != properties.end(); ) { @@ -543,4 +547,4 @@ void substitute::Rules::cleanup() { ++it; } } - } + } diff --git a/core/algorithms/substitute.hh b/core/algorithms/substitute.hh index c4543e959b..995270f79d 100644 --- a/core/algorithms/substitute.hh +++ b/core/algorithms/substitute.hh @@ -36,24 +36,46 @@ namespace cadabra { Ex_comparator comparator; - // Rules is a class for caching properties of substitution rules to avoid - // processing them in subsequent calls + + private: + Ex& args; + + iterator use_rule; + iterator conditions; + + std::map lhs_contains_dummies, rhs_contains_dummies; + + // For object swap testing routines: + sort_product sort_product_; + bool partial; + + // Rules is a class for caching properties of substitution + // rules to avoid processing them in subsequent calls. + class Rules { public: // Associate rule properties with a specific object - void store(Ex& rules, std::map& lhs_contains_dummies, std::map& rhs_contains_dummies); + void store(Ex& rules, + std::map& lhs_contains_dummies, + std::map& rhs_contains_dummies); + // Check if rules are present - bool is_present(Ex& rules); + bool is_present(Ex& rules) const; + // Retrieve properties from rules - void retrieve(Ex& rules, std::map& lhs_contains_dummies, std::map& rhs_contains_dummies); + void retrieve(Ex& rules, + std::map& lhs_contains_dummies, + std::map& rhs_contains_dummies) const; + // Count number of rules - int size(); + int size() const; + // Eliminate rules that are expired void cleanup(); private: // Map storing weak pointers to `Ex` and pairs of lhs/rhs maps as values - std::map, + mutable std::map, std::pair, std::map>, std::owner_less>> properties; @@ -63,19 +85,6 @@ namespace cadabra { unsigned int max_size = 1000; }; - - private: - Ex& args; - - iterator use_rule; - iterator conditions; - - std::map lhs_contains_dummies, rhs_contains_dummies; - - // For object swap testing routines: - sort_product sort_product_; - bool partial; - // Shared instance of all replacement rules. static Rules replacement_rules;