def sample_messy_power(variable, entropy): """Returns unsimplified power expression like ((x**2)**3/x**4)**2/x**3.""" if entropy <= 0: return variable which = random.choice([1, 2, 3]) if which == 1: exponent_entropy = min(2, entropy) entropy -= exponent_entropy exponent = number.integer_or_rational(exponent_entropy, signed=True) left = sample_messy_power(variable, entropy) return ops.Pow(left, exponent) entropy_left = entropy / 2 if entropy_left < 1: entropy_left = 0 entropy_right = entropy - entropy_left if random.choice([False, True]): entropy_left, entropy_right = entropy_right, entropy_left left = sample_messy_power(variable, entropy_left) right = sample_messy_power(variable, entropy_right) if which == 2: return ops.Mul(left, right) else: return ops.Div(left, right)
def _polynomial_coeffs_with_roots(roots, scale_entropy): """Returns a polynomial with the given roots. The polynomial is generated by expanding product_{root in roots} (x - root), and then (1) scaling by the coefficients so they are all integers with lcm 1, and then (2) further scaling the coefficients by a random integer or rational with `scale_entropy` digits. Args: roots: List of values. scale_entropy: Float; entropy of the random coefficient scaling. Returns: List of coefficients `coeffs`, such that `coeffs[i]` is the coefficient of variable ** i. """ variable = sympy.Symbol('x') # doesn't matter, only use coefficients polynomial = sympy.Poly(sympy.prod([variable - root for root in roots])) coeffs_reversed = polynomial.all_coeffs() assert len(coeffs_reversed) == len(roots) + 1 coeffs = list(reversed(coeffs_reversed)) # Multiply terms to change rationals to integers, and then maybe reintroduce. lcm = sympy.lcm([sympy.denom(coeff) for coeff in coeffs]) if scale_entropy > 0: while True: scale = number.integer_or_rational(scale_entropy, signed=True) if scale != 0: break else: scale = 1 return [coeff * scale * lcm for coeff in coeffs]
def testArithmeticLength(self): """Tests that the generated arithmetic expressions have given length.""" for _ in range(1000): target = number.integer_or_rational(4, signed=True) entropy = 8.0 length = random.randint(2, 10) expression = arithmetic.arithmetic(target, entropy, length) # Note: actual length is #ops = #numbers - 1. actual_length = len(ops.number_constants(expression)) - 1 self.assertEqual(actual_length, length)
def _sub_op(value, sample_args, rationals_allowed): """Returns sampled args for `ops.Sub`.""" entropy, sample_args = sample_args.peel() if rationals_allowed and sample_args.count >= 3: x = number.integer_or_rational(entropy, True) else: x = number.integer(entropy, True) if random.choice([False, True]): op_args = [x, x - value] else: op_args = [value + x, x] return ops.Sub, op_args, sample_args
def testArithmetic(self): for _ in range(1000): target = number.integer_or_rational(4, signed=True) entropy = 8.0 expression = arithmetic.arithmetic(target, entropy) self.assertEqual(sympy.sympify(expression), target)
def integer_or_rational_or_decimal(entropy): if random.choice([False, True]): return number.integer_or_decimal(entropy, signed=True) else: return number.integer_or_rational(entropy, signed=True)
#https://github.com/deepmind/mathematics_dataset/blob/master/mathematics_dataset/sample/arithmetic_test.py from mathematics_dataset.sample import arithmetic from mathematics_dataset.sample import number for ix in range(100): target = number.integer_or_rational(4, signed=True) entropy = 9.0 expression = arithmetic.arithmetic(target, entropy) print(expression)
def testIntegerOrRational(self, signed): # Tests we can call it. Do it a few times so both code paths get executed. for _ in range(10): number.integer_or_rational(2, signed)