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 _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) 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), 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='Misalkan {fn} ({variables}) menjadi turunan ke-{nth} dari {eq}.', handle=composition.FunctionHandle(fn_symbol), fn=fn_symbol, variables=variables_string, nth=nth, eq=polynomial)
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='Misalkan {intermediate} = {composed}.', handle=composition.FunctionHandle(intermediate_symbol), intermediate=intermediate, composed=expression)
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 = 'Sederhanakan {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='Misalkan {function} = {unsimplified}.', function=function, unsimplified=unsimplified)
def evaluate(value, sample_args, context=None): """Entity for evaluating an integer-valued polynomial at a given point.""" is_question = context is None if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() if value is None: entropy_value = random.uniform(1, 1 + entropy / 3) entropy = max(0, entropy - entropy_value) value = number.integer(entropy_value, signed=True) entropy_input = random.uniform(1, 1 + entropy / 3) entropy = max(0, entropy - entropy_input) input_ = number.integer(entropy_input, signed=True) degree = random.randint(1, 3) entropies = entropy * np.random.dirichlet(list(range(1, degree + 1))) # Calculate coefficients in reverse order. target = value coeffs_reversed = [] for i, coeff_entropy in enumerate(entropies): power = degree - i coeff = number.integer(coeff_entropy, signed=True) if input_ != 0: coeff += int(round(target / input_**power)) if coeff == 0 and i == 0: # Don't allow zero in leading coefficient. coeff += random.choice([-1, 1]) coeffs_reversed.append(coeff) target -= coeff * (input_**power) coeffs_reversed.append(target) coefficients = list(reversed(coeffs_reversed)) (polynomial_entity, input_) = context.sample(sample_args, [composition.Polynomial(coefficients), input_]) composed = polynomial_entity.handle.apply(input_.handle) if is_question: template = random.choice(_TEMPLATES) return example.Problem(question=example.question(context, template, composed=composed), answer=value) else: return composition.Entity(context=context, value=value, expression=composed, description='Misalkan {self} be {composed}.', composed=composed)
def polynomial_roots(value, sample_args, context=None): """E.g., "Solve 2*x**2 - 18 = 0.".""" del value # not currently used # is_question = context is None if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() scale_entropy = min(entropy / 2, 1) roots = _sample_roots(entropy - scale_entropy) solutions = sorted(list(sympy.FiniteSet(*roots))) coeffs = _polynomial_coeffs_with_roots(roots, scale_entropy) (polynomial_entity, ) = context.sample(sample_args, [composition.Polynomial(coeffs)]) if random.choice([False, True]): # Ask for explicit roots. if len(solutions) == 1: answer = solutions[0] else: answer = display.NumberList(solutions) if polynomial_entity.has_expression(): equality = ops.Eq(polynomial_entity.expression, 0) variable = polynomial_entity.polynomial_variables[0] else: variable = sympy.Symbol(context.pop()) equality = ops.Eq(polynomial_entity.handle.apply(variable), 0) template = random.choice([ 'Misalkan {equality}. Berapakah {variable}?', 'Misalkan {equality}. Hitung {variable}.', 'Misalkan {equality}. Berapakah {variable}?', 'Misalkan {equality}. Hitung {variable}.', 'Berapakah {variable} dalam {equality}?', 'Selesaikan {equality} untuk {variable}.', 'Temukan {variable} sehingga {equality}.', 'Temukan {variable}, mengingat {equality}.', 'Tentukan {variable} sehingga {equality}.', 'Tentukan {variable}, mengingat bahwa {equality}.', 'Selesaikan {equality}.' ]) return example.Problem(question=example.question(context, template, equality=equality, variable=variable), answer=answer) else: if polynomial_entity.has_expression(): expression = polynomial_entity.expression variable = polynomial_entity.polynomial_variables[0] else: variable = sympy.Symbol(context.pop()) expression = polynomial_entity.handle.apply(variable) factored = sympy.factor( polynomials.coefficients_to_polynomial(coeffs, variable)) template = random.choice([ 'Faktor dari {expression}.', ]) return example.Problem(question=example.question( context, template, expression=expression), answer=factored)