Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def combine_terms_after_commuting(
min_terms=5, max_terms=8, commute_blockers=1, easy=True, powers=False
):
"""A problem with a bunch of terms that have no matches, and a single
set of two terms that do match, but are separated by one other term.
The challenge is to commute the terms to each other and simplify in
only a few moves.
Example: "4y + 12j + 73q + 19k + 13z + 24x + 56l + 12x + 43n + 17j"
^-----------^
"""
total_terms = random.randint(min_terms, max_terms)
num_noise_terms = total_terms - 2
var = rand_var()
noise_vars = get_rand_vars(num_noise_terms, [var])
power_chance = 80 if powers == True else 0
power = maybe_power(power_chance)
# Build up the blockers to put between the like terms
blockers = []
for i in range(commute_blockers):
current = noise_vars.pop()
blockers.append(f"{maybe_int()}{current}{maybe_power(power_chance)}")
focus_chunk = f"{maybe_int()}{var}{power} + {' + '.join(blockers)} + {maybe_int()}{var}{power}"
# About half of the time focus the agent by grouping the subtree for them
if rand_bool(50 if easy else 10):
focus_chunk = f"({focus_chunk})"
out_terms = []
def move_around_blockers_two(number_blockers):
# two like terms with three blockers: "7a + 4x + (2f + j) + x + 3d"
rand_vars = get_rand_vars(3)
[one_var, two_var, three_var] = rand_vars
complexity = 4 + number_blockers
problem = "{}{} + {}{} + {} + {}{} + {}{}".format(
maybe_int(),
one_var,
maybe_int(),
two_var,
get_blocker(number_blockers, rand_vars),
maybe_int(),
two_var,
maybe_int(),
three_var,
)
return problem, complexity
"4y + 12j + 73q + 19k + 13z + 56l + (24x + 12x) + 43n + 17j"
max_turns=3 actions=[DistributiveFactorOut, ConstantArithmetic]
NOTE: we usually add one more move than may strictly be necessary to help with
exploration where we inject Dirichlet noise in the root tree search node.
"""
total_terms = random.randint(min_terms, max_terms)
var = rand_var()
power_chance = 80 if powers == True else 0
power = maybe_power(power_chance)
focus_chunk = f"{maybe_int()}{var}{power} + {maybe_int()}{var}{power}"
if easy:
focus_chunk = f"({focus_chunk})"
num_noise_terms = total_terms - 2
noise_vars = get_rand_vars(num_noise_terms, [var])
out_terms = []
# We take the larger value for the left side to push the terms
# that have to be matched to the right side of expression. This is
# so that the model cannot use its existing knowledge about distributive
# factoring on smaller problems to solve this problem.
right_num, left_num = split_in_two_random(num_noise_terms)
for i in range(left_num):
current = noise_vars.pop()
out_terms.append(f"{maybe_int()}{current}{maybe_power(power_chance)}")
out_terms.append(focus_chunk)
for i in range(right_num):
current = noise_vars.pop()
out_terms.append(f"{maybe_int()}{current}{maybe_power(power_chance)}")
def get_blocker(num_blockers=1, exclude_vars=[]):
"""Get a string of terms to place between target simplification terms
in order to challenge the agent's ability to use commutative/associative
rules to move terms around."""
vars = get_rand_vars(num_blockers, exclude_vars)
out_terms = []
for i in range(num_blockers):
out_terms.append("{}{}".format(maybe_int(), vars[i]))
return " + ".join(out_terms)
def move_around_interleaved_like_terms(number_terms, number_pairs):
# interleaved multiple like variables: "4x + 2y + 6x + 3y"
complexity = number_terms * number_pairs
terms = []
rand_vars = get_rand_vars(number_terms)
for i in range(number_pairs):
for j in range(number_terms):
terms.append("{}{}".format(maybe_int(), rand_vars[j]))
return " + ".join(terms), complexity