def compose(value, sample_args, context=None): """E.g., "Let f(x)=2x+1, let g(x)=3x+10. What is f(g(x))?".""" del value # unused if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() entropy_f, entropy_g = entropy * np.random.dirichlet([1, 1]) coeffs_f = polynomials.sample_coefficients([random.randint(1, 2)], entropy_f) coeffs_g = polynomials.sample_coefficients([random.randint(1, 2)], entropy_g) entity_f, entity_g = context.sample( sample_args, [composition.Polynomial(coeffs_f), composition.Polynomial(coeffs_g)]) variable = sympy.var(context.pop()) poly_f = polynomials.coefficients_to_polynomial(coeffs_f, variable) poly_g = polynomials.coefficients_to_polynomial(coeffs_g, variable) poly_f_g = poly_f.sympy().subs(variable, poly_g.sympy()).expand() expression = composition.FunctionHandle(entity_f, entity_g).apply(variable) template = random.choice(_TEMPLATES) return example.Problem(question=example.question(context, template, composed=expression), answer=poly_f_g)
def coefficient_named(value, sample_args, context=None): """E.g., "Express x^2 + 2x in the form h * x^2 + k * x + t and give h.".""" del value # not used if context is None: context = composition.Context() variable = sympy.Symbol(context.pop()) entropy, sample_args = sample_args.peel() degree = random.randint(1, 4) if random.choice([False, True]): coefficients = polynomials.sample_coefficients( degree, entropy / 2, min_non_zero=random.randint(degree - 1, degree)) expanded = polynomials.expand_coefficients(coefficients, entropy / 2) expression = polynomials.coefficients_to_polynomial(expanded, variable) else: expression = polynomials.sample_with_brackets(variable, degree, entropy) coefficients = list(reversed(sympy.Poly(expression).all_coeffs())) named_coeffs = [sympy.Symbol(context.pop()) for _ in range(degree + 1)] canonical = polynomials.coefficients_to_polynomial(named_coeffs, variable) if random.random() < 0.2: # only small probability of non-zero power power = random.randint(0, degree) else: non_zero_powers = [ i for i in range(degree + 1) if coefficients[i] != 0 ] power = random.choice(non_zero_powers) value = coefficients[power] named_coeff = named_coeffs[power] template = random.choice([ 'Выразите {expression} в форме {canonical} и найдите {target}.', 'Преобразуйте {expression} в форму {canonical} и найдите {target}.', # 'Express {expression} in the form {canonical} and give {target}.', # 'Rearrange {expression} to the form {canonical} and give {target}.', ]) return example.Problem(question=example.question(context, template, expression=expression, canonical=canonical, target=named_coeff), answer=value)
def testMultivariate(self): # Test generation for: x**2 + 2*x*y + 3*y**2 - x + 5 x, y = sympy.symbols('x y') coeffs = [[5, 0, 3], [-1, 2, 0], [1, 0, 0]] for _ in range(10): expanded = polynomials.expand_coefficients(coeffs, 5.0, length=10) polynomial = polynomials.coefficients_to_polynomial(expanded, [x, y]) sympified = sympy.sympify(polynomial) self.assertEqual(sympified, x*x + 2*x*y + 3*y*y - x + 5)
def testUnivariate(self): # Test generation for: x**2 + 2*x + 1 x = sympy.Symbol('x') coeffs = [1, 2, 3] for _ in range(10): expanded = polynomials.expand_coefficients(coeffs, 5.0) polynomial = polynomials.coefficients_to_polynomial(expanded, [x]) sympified = sympy.sympify(polynomial) self.assertEqual(sympified, 1 + 2*x + 3*x*x)
def collect(value, sample_args, context=None): """Collect terms in an unsimplified polynomial.""" is_question = context is None if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() if value is None: entropy_value, entropy = entropy * np.random.dirichlet([2, 3]) degrees = [random.randint(1, 3)] value = composition.Polynomial( polynomials.sample_coefficients(degrees, entropy_value)) assert isinstance(value, composition.Polynomial) coefficients = value.coefficients all_coefficients_are_integer = True for coeff in coefficients.flat: if not number.is_integer(coeff): all_coefficients_are_integer = False break if all_coefficients_are_integer: coefficients = polynomials.expand_coefficients(coefficients, entropy) else: # put back the unused entropy sample_args = composition.SampleArgs(sample_args.num_modules, sample_args.entropy + entropy) num_variables = coefficients.ndim variables = [sympy.Symbol(context.pop()) for _ in range(num_variables)] unsimplified = polynomials.coefficients_to_polynomial( coefficients, variables) simplified = unsimplified.sympy().expand() # Bit of a hack: handle the very rare case where no number constants appearing if not ops.number_constants(unsimplified): unsimplified = ops.Add(unsimplified, ops.Constant(0)) context.sample_by_replacing_constants(sample_args, unsimplified) if is_question: template = 'Упростите {unsimplified}.' return example.Problem(question=example.question( context, template, unsimplified=unsimplified), answer=simplified) else: function_symbol = context.pop() function = sympy.Function(function_symbol)(*variables) return composition.Entity( context=context, value=value, handle=composition.FunctionHandle(function_symbol), expression=unsimplified, polynomial_variables=variables, description='Пусть {function} = {unsimplified}.', function=function, unsimplified=unsimplified)
def testPolynomialRoots(self): variable = sympy.Symbol('x') for _ in range(10): roots = random.sample(list(range(-9, 10)), 3) coeffs = algebra._polynomial_coeffs_with_roots(roots, scale_entropy=10.0) polynomial = polynomials.coefficients_to_polynomial( coeffs, variable) calc_roots = sympy.polys.polytools.real_roots(polynomial) self.assertEqual(calc_roots, sorted(roots))
def add(value, sample_args, context=None): """E.g., "Let f(x)=2x+1, g(x)=3x+2. What is 5*f(x) - 7*g(x)?".""" is_question = context is None if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() if value is None: max_degree = 3 degree = random.randint(1, max_degree) entropy -= math.log10(max_degree) entropy_value = entropy / 2 entropy -= entropy_value value = polynomials.sample_coefficients(degree, entropy=entropy_value, min_non_zero=random.randint( 1, 3)) value = composition.Polynomial(value) c1, c2, coeffs1, coeffs2 = polynomials.coefficients_linear_split( value.coefficients, entropy) coeffs1 = polynomials.trim(coeffs1) coeffs2 = polynomials.trim(coeffs2) c1, c2, fn1, fn2 = context.sample(sample_args, [ c1, c2, composition.Polynomial(coeffs1), composition.Polynomial(coeffs2) ]) var = sympy.var(context.pop()) expression = (c1.handle * fn1.handle.apply(var) + c2.handle * fn2.handle.apply(var)) if is_question: answer = polynomials.coefficients_to_polynomial( value.coefficients, var) answer = answer.sympy() template = random.choice(_TEMPLATES) return example.Problem(question=example.question(context, template, composed=expression), answer=answer) else: intermediate_symbol = context.pop() intermediate = sympy.Function(intermediate_symbol)(var) return composition.Entity( context=context, value=value, description='Пусть {intermediate} = {composed}.', handle=composition.FunctionHandle(intermediate_symbol), intermediate=intermediate, composed=expression)
def _polynomial_entity(value, context): """Create a generic `Entity` describing a polynomial.""" assert isinstance(value, Polynomial) coefficients = np.asarray(value.coefficients) num_variables = coefficients.ndim variables = [sympy.Symbol(context.pop()) for _ in range(num_variables)] function_symbol = context.pop() handle = FunctionHandle(function_symbol) handle_description = sympy.Function(function_symbol)(*variables) polynomial = polynomials.coefficients_to_polynomial( coefficients, variables) polynomial = polynomial.sympy() return Entity(context=context, value=value, expression=polynomial, polynomial_variables=variables, description='Пусть {function} = {polynomial}.', handle=handle, function=handle_description, polynomial=polynomial)
def testCoefficientsToPolynomial(self): coeffs = [3, 2, 1] x = sympy.Symbol('x') polynomial = polynomials.coefficients_to_polynomial(coeffs, [x]) polynomial = sympy.sympify(polynomial) self.assertEqual(polynomial, x*x + 2*x + 3)
def _differentiate_polynomial(value, sample_args, context, num_variables): """Generates a question for differentiating a polynomial.""" is_question = context is None if context is None: context = composition.Context() if value is not None: num_variables = value.coefficients.ndim entropy, sample_args = sample_args.peel() max_derivative_order = 3 derivative_order = random.randint(1, max_derivative_order) entropy = max(0, entropy - math.log10(max_derivative_order)) derivative_axis = random.randint(0, num_variables - 1) if value is None: coefficients = _generate_polynomial(num_variables, entropy, derivative_order, derivative_axis) else: coefficients = _sample_integrand(value.coefficients, derivative_order, derivative_axis, entropy) (entity, ) = context.sample(sample_args, [composition.Polynomial(coefficients)]) value = coefficients for _ in range(derivative_order): value = polynomials.differentiate(value, axis=derivative_axis) nth = display.StringOrdinal(derivative_order) nth_fem = display.StringOrdinal_fem(derivative_order) nth_fem_gen = display.StringOrdinal_fem_gen(derivative_order) if entity.has_expression(): polynomial = entity.expression variables = entity.polynomial_variables else: variables = [sympy.Symbol(context.pop()) for _ in range(num_variables)] polynomial = entity.handle.apply(*variables) variable = variables[derivative_axis] if is_question: template = _template(context.module_count, derivative_order, len(variables)) answer = polynomials.coefficients_to_polynomial(value, variables).sympy() return example.Problem(question=example.question( context, template, eq=polynomial, var=variable, nth=nth, nth_fem=nth_fem, nth_fem_gen=nth_fem_gen), answer=answer) else: fn_symbol = context.pop() variables_string = ', '.join(str(variable) for variable in variables) assert len( variables) == 1 # since below we don't specify var we diff wrt return composition.Entity( context=context, value=composition.Polynomial(value), description= 'Пусть {fn}({variables}) - это {nth_fem} производная функции {eq}.', handle=composition.FunctionHandle(fn_symbol), fn=fn_symbol, variables=variables_string, nth=nth, nth_fem=nth_fem, nth_fem_gen=nth_fem_gen, eq=polynomial)