From 0329ee6384fe569d2ec847a9d2179802c9ac0a90 Mon Sep 17 00:00:00 2001 From: peepulp <56609938+peepulp@users.noreply.github.com> Date: Wed, 15 Oct 2025 12:30:51 -0400 Subject: [PATCH 1/3] Update Prior Knowledge & Cross-Domain CREFuncs for AL_Core compatibility --- apprentice/agents/cre_agents/cre_agent.py | 4 +- apprentice/agents/cre_agents/funcs.py | 61 +++++++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/apprentice/agents/cre_agents/cre_agent.py b/apprentice/agents/cre_agents/cre_agent.py index afc25c3..e7e92ba 100644 --- a/apprentice/agents/cre_agents/cre_agent.py +++ b/apprentice/agents/cre_agents/cre_agent.py @@ -1409,7 +1409,7 @@ def _recover_prev_skill_app(self, action=None, skill_app = None if(skill_uid in self.skills and skill_app_uid is not None): - if(uid in getattr(self.skills[skill_uid],"skill_apps", [])): + if(self.uid in getattr(self.skills[skill_uid],"skill_apps", [])): skill_app = self.skills[skill_uid].skill_apps[skill_app_uid] return skill_app @@ -1749,7 +1749,7 @@ def get_skills(self, skill_uids=None, skill_labels=None, if(skill_uids): skills = [self.skills[uid] for uid in skill_uids if uid in self.skills] elif(skill_labels): - skills = chain([skills_by_label.get(label,[]) for label in skill_labels]) + skills = chain([self.skills_by_label.get(label,[]) for label in skill_labels]) elif(states): raise NotImplemented() else: diff --git a/apprentice/agents/cre_agents/funcs.py b/apprentice/agents/cre_agents/funcs.py index 93b5328..15a2335 100644 --- a/apprentice/agents/cre_agents/funcs.py +++ b/apprentice/agents/cre_agents/funcs.py @@ -158,6 +158,67 @@ def AcrossMultiply(a, b): return (float(a.value) * float(b.value)) +# === Prior Knowledge & Cross-Domain Functions === + +@CREFunc(signature=f8(TextField), shorthand='Num({0})') +def Num(tf): + """Convert TextField value to a float.""" + return float(str(tf.value).replace(',', '').strip()) + +@CREFunc(signature=string(TextField), shorthand='Str({0})') +def StrTF(tf): + """Extract string from a TextField.""" + return str(tf.value) + +@CREFunc(signature=boolean(TextField), shorthand='IsDen({0})') +def IsDen(tf): + """Return True if this TextField looks like a denominator.""" + return 'den' in tf.id + +@CREFunc(signature=boolean(TextField), shorthand='IsNum({0})') +def IsNum(tf): + """Return True if this TextField looks like a numerator.""" + return 'num' in tf.id + +@CREFunc(signature=boolean(string, string), shorthand='lower({0}) == lower({1})', commutes=True) +def EqualsIgnoreCase(a, b): + """Case-insensitive equality for strings.""" + return a.lower() == b.lower() + +@CREFunc(signature=f8(string), shorthand='parse({0})') +def ParseFloat(s): + """Parse numeric string into float.""" + return float(s.replace(',', '').strip()) + +@CREFunc(signature=string(string, string), shorthand='join({0},{1})', commutes=False) +def JoinWithSpace(a, b): + """Join two strings with a space.""" + return f"{a} {b}" + +@CREFunc(signature=f8(f8), shorthand='sq({0})') +def Sq(a): + """Square a number.""" + return a * a + +@CREFunc(signature=f8(f8, f8), shorthand='sq({0}) + {1}') +def SqPlus(a, b): + """Square a number and add another.""" + return (a * a) + b + +@CREFunc(signature=f8(f8, f8), shorthand='Reuse({0},{1})', commutes=True) +def ReusePrior(a, b): + """Prefer previously known value a; otherwise use b.""" + return a if a != 0 else b + +@CREFunc(signature=f8(f8), shorthand='Recall({0})') +def RecallValue(a): + """Surface a previously computed value.""" + return a + +@CREFunc(signature=f8(f8, f8), shorthand='AvgPrior({0},{1})', commutes=True) +def AveragePrior(a, b): + """Combine earlier results (simple average).""" + return (a + b) / 2 ##### Define all CREFuncs above this line ##### From d82c0558907cf33250681d2bbd1b75e25c0041e7 Mon Sep 17 00:00:00 2001 From: Jennifer Reddig Date: Fri, 17 Oct 2025 11:29:29 -0400 Subject: [PATCH 2/3] exponents power rule functions --- apprentice/agents/cre_agents/funcs.py | 34 +++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/apprentice/agents/cre_agents/funcs.py b/apprentice/agents/cre_agents/funcs.py index 15a2335..8e6e99f 100644 --- a/apprentice/agents/cre_agents/funcs.py +++ b/apprentice/agents/cre_agents/funcs.py @@ -7,6 +7,40 @@ register_func = new_register_decorator("func", full_descr="CREFunc") register_all_funcs = new_register_all("func", types=[CREFunc], full_descr="CREFunc") +@CREFunc(signature=string(string), shorthand='exp_mult_pow({0})') +def MultiplyExponents(s): + i_close = s.index(')') # position of ')' + j_open = s.index('^{', i_close + 1) # must be right after ')' + k_end = s.index('}', j_open + 2) + e2 = s[j_open + 2 : k_end] + + inner = s[1 : i_close] # "base^{e1}" + i_pow = inner.index('^{') + k1_end = inner.index('}', i_pow + 2) + base = inner[:i_pow] + e1 = inner[i_pow + 2 : k1_end] + + out = base + "^{" + e1 + " \\cdot " + e2 + "}" + return out + +@CREFunc(signature=string(string), shorthand='exp_power_rule({0})') +def PowerRule(s): + s = s.rsplit("/", 1)[-1].strip() # e.g., "675^{6 \cdot 6}" + + i_pow = s.index('^{') # start of exponent + j_open = i_pow + 2 # first char inside '{' + k_end = s.index('}', j_open) # closing '}' + + base = s[:i_pow] # "675" + exp_str = s[j_open:k_end] # "6 \cdot 6" + + a_str, b_str = exp_str.split(r'\cdot') # exactly two factors + a = int(a_str.strip()) + b = int(b_str.strip()) + + out = base + "^{" + str(a * b) + "}" + return out + @CREFunc(signature=boolean(string,string), shorthand = '{0} == {1}', commutes=True) From fa36f3537d51e65f546a2f35c68d2d7995ffb9aa Mon Sep 17 00:00:00 2001 From: peepulp <56609938+peepulp@users.noreply.github.com> Date: Sun, 26 Oct 2025 23:13:02 -0400 Subject: [PATCH 3/3] Add prior knowledge functions for exponent product rule --- apprentice/agents/cre_agents/funcs.py | 70 +++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/apprentice/agents/cre_agents/funcs.py b/apprentice/agents/cre_agents/funcs.py index 8e6e99f..87040a0 100644 --- a/apprentice/agents/cre_agents/funcs.py +++ b/apprentice/agents/cre_agents/funcs.py @@ -41,6 +41,76 @@ def PowerRule(s): out = base + "^{" + str(a * b) + "}" return out +# --- Product rule: a^{m} * a^{n} -> a^{m + n} +@CREFunc(signature=string(string), shorthand='exp_product_rule({0})') +def ProductRule(s: str) -> str: + # make robust like PowerRule + s = s.rsplit("/", 1)[-1].strip() + + # split on either "\cdot" or "*" + if r'\cdot' in s: + left, right = [t.strip() for t in s.split(r'\cdot', 1)] + else: + left, right = [t.strip() for t in s.split('*', 1)] + + # Parse left: a^{m} + iL = left.index('^{'); jL = iL + 2; kL = left.index('}', jL) + baseL = left[:iL] + m = left[jL:kL].strip() + + # Parse right: a^{n} + iR = right.index('^{'); jR = iR + 2; kR = right.index('}', jR) + baseR = right[:iR] + n = right[jR:kR].strip() + + # optional safety + if baseL != baseR: + raise ValueError("ProductRule expects matching bases.") + + return f"{baseL}^{{{m} + {n}}}" + + +@CREFunc(signature=string(string), shorthand='exp_product_simplify({0})') +def SimplifyProduct(s: str) -> str: + s = s.rsplit("/", 1)[-1].strip() + i = s.index('^{'); j = i + 2; k = s.index('}', j) + base = s[:i] + m_str, n_str = [t.strip() for t in s[j:k].split('+', 1)] + val = int(m_str) + int(n_str) + return f"{base}^{{{val}}}" + + + +# --- Quotient rule: a^{m} / a^{n} -> a^{m - n} +@CREFunc(signature=string(string), shorthand='exp_quotient_rule({0})') +def QuotientRule(s: str) -> str: + s = s.rsplit("/", 1)[-1].strip() + left, right = [t.strip() for t in s.split('/', 1)] + + iL = left.index('^{'); jL = iL + 2; kL = left.index('}', jL) + baseL = left[:iL] + m = left[jL:kL].strip() + + iR = right.index('^{'); jR = iR + 2; kR = right.index('}', jR) + baseR = right[:iR] + n = right[jR:kR].strip() + + if baseL != baseR: + raise ValueError("QuotientRule expects matching bases.") + + return f"{baseL}^{{{m} - {n}}}" + + +@CREFunc(signature=string(string), shorthand='exp_quotient_simplify({0})') +def SimplifyQuotient(s: str) -> str: + s = s.rsplit("/", 1)[-1].strip() + i = s.index('^{'); j = i + 2; k = s.index('}', j) + base = s[:i] + m_str, n_str = [t.strip() for t in s[j:k].split('-', 1)] + val = int(m_str) - int(n_str) + return f"{base}^{{{val}}}" + + @CREFunc(signature=boolean(string,string), shorthand = '{0} == {1}', commutes=True)