def random_polynomial_term():
    err = False
    build_op = tr2narr.sup
    t1 = random_tok()

    if 'order2' == nonUniformChoice(
        ['order1', 'order2'],
        [0.5, 0.5]
    ):
        sign = nonUniformChoice(
            [+1, -1],
            [0.5, 0.5]
        )

        if sign < 0:
            t0 = tr2narr.null_reduce([])
            t1 = tr2narr.minus([t0, t1])

        t2 = random_tok(only_number=True, small_number=True)
        t1 = build_op([t1, t2])

    try:
        tex = expression.narr2tex(t1)
        expression.tex2narr(tex)
    except Exception as err_msg:
        err = True

    return tex, err
def random_exp(complexity=2):
    """
    按照复杂度指示生成随机数学表达式
    """
    err = False
    tex = ''
    t1 = tr2narr.null_reduce([])
    for _ in range(complexity):
        # null-reduce must be commutative
        commutative = (len(t1) == 0)

        n_oprands, build_op = random_operator(commutative=commutative)

        if n_oprands == 2:
            always_t12 = False

            if tr2narr.sup == build_op:
                t2 = random_tok(only_number=True, small_number=True)
                always_t12 = True

            elif 'simple' == nonUniformChoice(
                ['complex', 'simple'],
                [0.2, 0.8]
            ):
                t2 = random_tok()
            else:
                random_complexity = bounded_guassian_sample(3, 5)
                tex, err = random_exp(complexity=random_complexity)
                if err: break
                t2 = expression.tex2narr(tex)

            if always_t12 or random.choice(['12', '21']) == '12':
                t1 = build_op([t1, t2])
            else:
                t1 = build_op([t2, t1])
        else:
            t1 = build_op([t1])

        try:
            tex = expression.narr2tex(t1)
            expression.tex2narr(tex)
        except Exception as err_msg:
            err = True
            #rich.print('[red]invalid random expression')
            break

    return tex, err
def random_equations():
    """
    生成等号两边由随机表达式组成的等式
    """
    build_op = tr2narr.eq
    tex1, err1 = random_terms()
    tex2, err2 = random_terms()

    if err1 or err2:
        return '', True

    try:
        t1 = expression.tex2narr(tex1)
        t2 = expression.tex2narr(tex2)
        t1 = build_op([t1, t2])
        tex = expression.narr2tex(t1)
        expression.tex2narr(tex)
    except Exception as err_msg:
        return '', True

    return tex, False
Example #4
0
    def add_rule(self, src, dest, dynamic_procedure=None, animation=None):
        dests = dest if isinstance(dest, list) else [dest]

        for i, dest_output in enumerate(dests):
            A, B, C = self._preprocess(src, dest_output)

            for (a, b, signs) in zip(A, B, C):
                if a not in self.rules:
                    self.rules[a] = b
                elif isinstance(self.rules[a], list):
                    self.rules[a].append(b)
                else:
                    self.rules[a] = [self.rules[a], b]

                self.dp[a] = dynamic_procedure
                self.signs[a] = signs

                # cache some results for speedup
                self.narrs[a] = expression.tex2narr(a)
                self.narrs[b] = expression.tex2narr(b)
                self.wildcards_idx[a] = expression.get_wildcards_index(
                    self.narrs[a])

            if animation:
                ani_output = animation[i] if isinstance(dest,
                                                        list) else animation
                A, B, _ = self._preprocess(src, ani_output)
                for (a, b) in zip(A, B):
                    if a not in self.animation:
                        self.animation[a] = b
                    elif isinstance(self.animation[a], list):
                        self.animation[a].append(b)
                    else:
                        self.animation[a] = [self.animation[a], b]

                    self.narrs[b] = expression.tex2narr(b)

        return self
Example #5
0
def value_v1(narr, debug=False):
    """
    计算 表达式的价值(等于各个符号频率的自定义加权和)
    """
    if isinstance(narr, str):
        return value(expression.tex2narr(narr))

    narr = expression.trim_animations_copy(narr)

    value_dict = {
        'VAR': 10,
        'NUMBER_integer': 0.1,
        'NUMBER_decimal': 2,
        'NUMBER_pad_zeros': -0.25,
        'NUMBER_one': -0.1,
        'NUMBER_zero': 0.1,
        'NUMBER_in_sqrt': 0.5,
        'eq': 0,
        'neg': 0.5,
        'add': 2,
        'mul': 1,
        'div': 10,
        'frac': 8,
        'ifrac': 20,
        'sup': 4,
        'abs': 1,
        'sqrt': 1,
        'n_terms': 0.6,
        'n_terms_in_sqrt': 25,
        'n_deepest_var_level': 100,
        'right_side_of_eq': 200,
    }
    stats = token_stats(narr, {})

    if debug:
        print('[value_v1]', expression.narr2tex(narr))
        print(stats)

    accum = 0
    # symbol type values
    for key in stats:
        if key in value_dict:
            accum += stats[key] * value_dict[key]
    # number sum values
    if 'NUMBER_sum' in stats:
        accum += math.log(1 + stats['NUMBER_sum']) / 2
    if 'NUMBER_in_sqrt' in stats:
        accum += 1.5 * math.log(1 + stats['NUMBER_in_sqrt'])
    return -accum
Example #6
0
def test(tex, state_value):
    """
    包装测试函数
    """
    import expression
    global g_test_last_val

    narr = expression.tex2narr(tex)
    value = state_value(narr, debug=True)

    print(value)
    if value > g_test_last_val:
        rich.print('[green][[pass]][/]')
    else:
        rich.print('[red][[failed]][/]')
    print()

    g_test_last_val = value
def random_terms():
    """
    将随机表达式按项组合,生成随机加和表达式
    """
    any_err = True
    build_op = tr2narr.add
    t1 = tr2narr.null_reduce([])

    # the number of terms is sampled from normal distribution
    n_terms = bounded_guassian_sample(3, 6)

    for _ in range(n_terms):
        if 'nested' == nonUniformChoice(
            ['nested', 'polynomial'],
            [0.2, 0.8]
        ):
            tex_t2, err = random_exp()
        else:
            tex_t2, err = random_polynomial_term()

        if err:
            continue
        else:
            any_err = False

        t2 = expression.tex2narr(tex_t2)
        if random.choice(['12', '21']) == '12':
            t1 = build_op([t1, t2])
        else:
            t1 = build_op([t2, t1])

    if len(t1) == 0:
        return '', True
    else:
        tex = expression.narr2tex(t1)
        return tex, any_err
Example #8
0
    def test(self,
             tex=None,
             debug=False,
             render=True,
             printNarr=False,
             printTrim=False,
             printJSON=False):
        # construct test pairs (TeX, expected TeX)
        tests = self.tests if tex is None else [(tex, None)]
        if len(tests) == 0: print('[no test case]')
        # test through each testcase for this axiom ...
        for test, expect in tests:
            expr = test if isinstance(test, str) else expression.narr2tex(test)
            narr = expression.tex2narr(expr) if isinstance(test, str) else test
            results = self.apply(narr, debug=debug)
            # render texs is for HTML preview
            render_texs = [expr]

            rich.print('[bold cyan][[test]][/]', end=" ")
            print(expr)
            #if printNarr:
            #    expression.narr_prettyprint(narr)

            for applied_narr, ani_narr in results:
                # print transition animations
                if ani_narr:
                    ani_tex = expression.narr2tex(ani_narr)
                    rich.print('[bold cyan][[transition]][/]', end=" ")
                    print(ani_tex)
                else:
                    rich.print('[bold cyan][[transition]][/]', None)

                # print result expression
                applied_tex = expression.narr2tex(applied_narr)
                rich.print('[bold cyan][[result]][/]', end=" ")
                print(applied_tex, end=" ")
                if expect is not None:
                    if applied_tex in expect:
                        rich.print('[bold green]pass[/]')
                    else:
                        rich.print('[bold red]failed[/]')
                else:
                    print()

                # render texs is for HTML preview
                render_texs.append(applied_tex)

                if printNarr:
                    rich.print("[red]narr[/]:")
                    expression.narr_prettyprint(applied_narr)

                if printTrim:
                    rich.print("[red]trim[/]:")
                    expression.trim_animations(applied_narr)
                    expression.narr_prettyprint(applied_narr)

                if printJSON:
                    rich.print('[red]JSON[/]:')
                    json = mathjs.tex2json(applied_tex, indent=4)
                    print(json)

            if render:
                import render_math
                render_math.render_equations(render_texs)
Example #9
0
    #testcases += test_case_from_log('./rational_8000.txt')
    #testcases += test_case_from_log('./full_random_1000.txt')

    #n_sample_times = 220
    n_sample_times = 440
    start = 0
    always_use_MCTS = True

    open('fallback.log', 'w')

    for i, expr in enumerate(testcases[-1:]):
    #for i, expr in enumerate(testcases[:]):
        if i < start: continue

        try:
            narr = expression.tex2narr(expr)

            err = None
            if not always_use_MCTS:
                # use DFS or mcts (as fallback) to generate steps
                steps, err = dfs(narr, basic_axioms, debug=True, maxsteps=150)
                steps = [(n, a, ai) for n, an, a, ai in steps]

            if err or always_use_MCTS:
                with open('fallback.log', 'a') as fh:
                    fh.write(f'#{i}: ' + expr + '\n')

                steps = mcts(narr, all_axioms, debug=False, n_sample_times=n_sample_times,
                    nn_models=None, force_single_thread=False)

            # make data pair
Example #10
0
def test(all_axioms):
    from render_math import render_steps
    from test_cases import test_cases_x3_rational, test_cases_wiki131278697

    testcases = []

    tmp, _ = test_cases_x3_rational()
    testcases += tmp

    tmp, _ = test_cases_wiki131278697()
    testcases += tmp

    testcases += [
        '\\frac{12a}{3a + a + 20a} - \\frac{1}{4}',
        '1 + \\frac{7}{3}',
        '4 -3 \\frac{1}{2}',
        '\\frac{(-3)^{3}}{2 \cdot \\frac{1}{4} \cdot (-\\frac{2}{3})^{2}} + 4 -4 \cdot \\frac{1}{3}',
        '\\frac{11}{2} (- \\frac{1}{6}) \\frac{3}{11} \\frac{4}{3}',
        'a - x^{2} + x^{2} \\times 0.609 + 1 = 0',
        "25 \cdot 48 + 103 \cdot 25 - 25 \cdot 51",
        "-13 \\times \\frac{2}{3} - 0.34 \\frac{2}{7} + \\frac{1}{3}(-13) - \\frac{5}{7} 0.34",
        '(-3\\frac{1}{3})\div2\\frac{1}{3}\\times\\frac{7}{10}',
        "(-18) \div ((2\\frac{1}{4}) \\times (1 - \\frac{3}{4}))",

        #"(-3 - \\frac{4}{17}) (14\\frac{13}{15}) - (3\\frac{4}{17}) (2 + \\frac{2}{15})",
        "b + 3x^{2} +2b + 3b + x^{2}= 0",
        "(3 + \\frac{4}{17}) (-14\\frac{13}{15} - \\frac{2}{15}) - 2 \times 3 - 2 \\times \\frac{4}{17}",
        "-(3 + \\frac{4}{17}) \\times (14\\frac{13}{15}) - (3 + \\frac{4}{17}) \\times (2\\frac{2}{15})",
        "\\frac{-1}{\\frac{2}{3} \cdot \\frac{7}{10}}",
        "\\frac{ 60 (1 - \\frac{2}{5}) + 3}{2}"

        ## some animation testcases
        #"1 + 0 + 0 + 0 + 0",
        #'-3 \\frac{-2}{4}',
        #'\\frac{2}{3} \div \\frac{4}{5}',
        #'(\sqrt{2})^{2}',
        #'0+1+2',
        #'-\\frac{1}{-2} \div \\frac{-3}{4}',
        #'\\frac{x}{3xy}',
        #'-x x',
        #'-\\frac{8}{-2}',
        #"a + b = 3 - c",
        #"x + b = 12",
        #'\\frac{2}{x} + y = a + b',
        #'\\frac{1}{y} \\frac{x}{1}',
        #'-7(a-b)',
        #'-(-2-3)^{2}',
        #"\left| -(5+\\frac{1}{2})\\right| (\\frac{1}{3} - \\frac{1}{2}) \\frac{3}{11} \\div (1 - \\frac{1}{4})",
        #"2 + 7 + 8",
        #"3x + 3 = 2x - 1",
        #'2(a + b) + 3',
        #'2(a + b)',
        #'(-7) + 10 + (-3) + 6 + (-6)',
        #'-(3 - 2)x',
        #"(-3 - \\frac{4}{17}) \\times (14\\frac{13}{15}) - (3\\frac{4}{17}) \\times (2\\frac{2}{15})",
        #"\\frac{1}{2} \\times 10.2 - (\\frac{5}{4} + 1 - 9 \\frac{1}{7})^{2}"
    ]

    begin_from = 0

    n_steps = 0
    timer = Timer()

    #for i, test in enumerate(testcases):
    for i, test in enumerate(testcases[-1:]):
        if i < begin_from: continue

        test_narr = expression.tex2narr(test)

        with timer:
            steps, err = dfs(test_narr,
                             all_axioms,
                             debug=True,
                             animation_mode=True,
                             printTrim=False)
            if err:
                print('DFS error:', err)

        for narr, ani_narr, axiom, axiom_idx in steps:
            rich.print(f'[red]{axiom.name()}')

            narr = expression.trim_animations_copy(narr)

            tex = expression.narr2tex(narr)
            if ani_narr:
                ani_tex = expression.narr2tex(ani_narr)
                print('\t', ani_tex)
            print('\t', tex)

            #animation_json = mathjs.tex2json(tex)
            #print('\t', animation_json)

        render_steps(steps)

        n_steps += len(steps)
        print(f'steps: {len(steps)}')
        print(f'test case: {i} / {len(testcases)}')

        #input('Enter to continue...')

    timer.show_stats(n_steps=n_steps)
Example #11
0
                  strict_simplify=True,
                  disable=False).add_rule(
                      '-(x + *{1}) *{2} ',
                      '(-x - *{1}) *{2}',
                      animation='`-(x + *{1})`[replace]{-x - *{1}} *{2}').
            add_test('-(3 - 2)x', '(-3 + 2) \\times x')
        ]

    else:
        from common_axioms import common_axioms
        all_axioms = common_axioms()

    args = sys.argv[1:]
    if len(args) > 0:
        tex = args[0]
        narr = expression.tex2narr(tex)
        steps, err = dfs(narr, all_axioms, debug=False, animation_mode=True)

        if err:
            print(err, file=sys.stderr)
            quit()

        ret_arr = []
        for i, (narr, ani_narr, axiom, axiom_idx) in enumerate(steps):
            trim_narr = expression.trim_animations_copy(narr)
            trim_tex = expression.narr2tex(trim_narr)

            animate_tex = expression.narr2tex(narr)
            animate_json = mathjs.tex2json(animate_tex)

            if ani_narr:
Example #12
0
    #narr1 = expression.tex2narr('-\\sqrt{x}^{2}')
    #narr2 = expression.tex2narr('-(\\sqrt{x})^{2}')

    #narr1 = expression.tex2narr('0 (-n)')
    #narr2 = expression.tex2narr('- 0 n')

    #narr1 = expression.tex2narr('-x \\times *{1} + x \\times *{2}')
    #narr2 = expression.tex2narr('-25 \\times 51 + 25 \\times 48')

    #narr1 = expression.tex2narr('+(-X)(-X)')
    #narr2 = expression.tex2narr('-yy')

    #narr1 = expression.tex2narr('a + *{1}')
    #narr1 = expression.tex2narr('- a - *{1}')
    narr1 = expression.tex2narr('-a')
    narr2 = [
        NarrRoot(1, 'add'), [NarrRoot(1, 'NUMBER'), 30.0],
        [
            NarrRoot(1, 'add'), [NarrRoot(1, 'NUMBER'), 1.0],
            [NarrRoot(1, 'NUMBER'), 3.0]
        ]
    ]

    is_equiv, rewrite_rules = test_alpha_equiv(narr1, narr2, debug=True)
    if is_equiv:
        rich.print('[bold green]Is alpha-equivalent')
        alpha = rewrite_rules[0]
        alpha_prettyprint(alpha)
        rewritten_narr = rewrite_by_alpha(narr1, alpha)
        rich.print('[[rewritten]]', expression.narr2tex(rewritten_narr))
Example #13
0
    testcase = (
        "(-3 - \\frac{4}{17}) \\times (14 + \\frac{13}{15}) - (3 + \\frac{4}{17}) \\times (2 + \\frac{2}{15})"
    )

    debug_NN = True

    if debug_NN:
        global nn_models
        nn_models = nn.NN_models('model-policy-nn.pretrain.pt',
                                 'model-value-nn.pretrain.pt', 'bow.pkl')

    state_value = nn_value if debug_NN else state.value_v2

    try:
        narr = expression.tex2narr(testcase)
        val0 = state_value(narr)
        steps = [(narr, None, Axiom(name='原式'), -1)]
        choices = [0]
        values = [val0]
        while len(steps) > 0:
            narr = steps[-1][0]
            value = state_value(narr)
            values.append(value)

            # only used in animation_mode
            expression.trim_animations(narr)

            if debug_NN:
                rules, probs, _ = nn.predict_policy(testcase, nn_models, k=4)
                rules = rules.tolist()
Example #14
0
def test():
    from test_cases import test_cases_x3_rational, test_cases_wiki131278697, test_case_from_log

    from common_axioms import common_axioms
    axioms = common_axioms(full=True)

    testcases = []

    tmp, _ = test_cases_x3_rational()
    testcases += tmp

    #testcases += [
    #    '\\frac{12a}{3a + a + 20a} - \\frac{1}{4}',
    #    '1 + \\frac{7}{3}',
    #    '4 -3 \\frac{1}{2}',
    #    '\\frac{(-3)^{3}}{2 \cdot \\frac{1}{4} \cdot (-\\frac{2}{3})^{2}} + 4 -4 \cdot \\frac{1}{3}',
    #    '\\frac{11}{2} (- \\frac{1}{6}) \\frac{3}{11} \\frac{4}{3}',
    #    '(-3\\frac{1}{3})\div2\\frac{1}{3}\\times\\frac{7}{10}',
    #    'a - x^{2} + x^{2} \\times 0.609 + 1 = 0',
    #    '1.609 \\times x^{2} + x^{2} + x^{2} \\times 2 \\times x = 0',
    #    '-x \\times 0.391 - 629 - x^{2} \\times 2 + y^{2} + x \\times \\frac{50}{x + y} = 0',

    #    # some tests for extracting common factors
    #    "25 \cdot 48 + 103 \cdot 25 - 25 \cdot 51",
    #    "-13 \\times \\frac{2}{3} - 0.34 \\frac{2}{7} + \\frac{1}{3}(-13) - \\frac{5}{7} 0.34",

    #    "-x 0.391 - 629 - 2 x^{2} + y^{2} + \\frac{50x}{x+y} = 0",
    #    "- (3\\frac{4}{17}) (2\\frac{2}{15}) - (7\\frac{4}{17}) (14 \\frac{13}{15}) - 4 (-14 \\frac{13}{15})",
    #    "(-3 - \\frac{4}{17}) \\times (14 + \\frac{13}{15}) - (3 + \\frac{4}{17}) \\times (2 + \\frac{2}{15})",
    #    #"-200.9 + 28 + 0.9 + (-8)",
    #    #"3+5\\times6-6\div3",
    #    #"\\frac{(-3)^{3}}{2 \\times \\frac{1}{4} (-\\frac{2}{3})^{2}} +4 -4 \\times\\frac{1}{3}",
    #    #"6 \div 3"
    #]

    nn_models = True
    debug = True
    force_single_thread = False

    n_steps = 0
    timer = Timer()
    open(rollout_logfile, 'w')
    #for i, expr in enumerate(testcases[-1:]):
    for i, expr in enumerate(testcases[:]):
        narr = expression.tex2narr(expr)

        n_sample_times = 22 if nn_models or force_single_thread else 440

        with timer:
            steps = mcts(narr,
                         axioms,
                         debug=debug,
                         n_sample_times=n_sample_times,
                         nn_models=nn_models,
                         force_single_thread=force_single_thread)

        for j, (narr, axiom, axiom_idx) in enumerate(steps):
            val = state_value(narr)
            expr = expression.narr2tex(narr)
            axiom_name = axiom.name() if axiom is not None else '原式'
            rich.print(f'step{j} {axiom_name} [blue]val={val:.2f}[/]', expr)

        render_steps(steps)
        n_steps += len(steps)
        print(f'steps: {len(steps)}')
        print(f'Test case: {i} / {len(testcases) - 1}')

        #print('Enter to continue')
        #input()

    timer.show_stats(n_steps=n_steps)