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 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)
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)