コード例 #1
0
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)
コード例 #2
0
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)
コード例 #3
0
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='Пусть {self} {composed}.',
                                  composed=composed)
コード例 #4
0
def mul(value, sample_args, context=None):
  """Returns random question for multiplying two numbers."""
  del value  # unused
  is_question = context is None
  if context is None:
    context = composition.Context()
  entropy, sample_args = sample_args.peel()
  entropy_p, entropy_q = _entropy_for_pair(entropy)
  p = number.integer_or_decimal(entropy_p, True)
  q = number.integer_or_decimal(entropy_q, True)
  p, q = context.sample(sample_args, [p, q])
  answer = p.value * q.value

  if is_question:
    # templates = [
    #     '{p}' + ops.MUL_SYMBOL + '{q}',
    #     '{p} ' + ops.MUL_SYMBOL + ' {q}',
    #     'Calculate {p}' + ops.MUL_SYMBOL + '{q}.',
    #     'Work out {p} ' + ops.MUL_SYMBOL + ' {q}.',
    #     'Multiply {p} and {q}.',
    #     'Product of {p} and {q}.',
    #     'What is the product of {p} and {q}?',
    #     '{p} times {q}',
    #     'What is {p} times {q}?',
    # ]
    templates = [
        '{p}' + ops.MUL_SYMBOL + '{q}',
        '{p} ' + ops.MUL_SYMBOL + ' {q}',
        'Вычислите {p}' + ops.MUL_SYMBOL + '{q}.',
        'Рассчитайте {p} ' + ops.MUL_SYMBOL + ' {q}.',
        'Умножьте {p} и {q}.',
        'Чему равно произведение {p} и {q}?',
        'Умножьте {p} на {q}.',
        'Сколько будет {p} умножить на {q}?',
        'Каков результат произведения {p} и {q}?',
    ]
    template = random.choice(templates)
    return example.Problem(
        question=example.question(context, template, p=p, q=q),
        answer=answer
    )
  else:
    return composition.Entity(
        context=context,
        value=answer,
        description='Пусть {self} = {p} * {q}.',
        p=p, q=q)
コード例 #5
0
def _calculate(value, sample_args, context, add_sub, mul_div, length=None):
  """Questions for evaluating arithmetic expressions."""
  is_question = context is None
  if context is None:
    context = composition.Context()

  entropy, sample_args = sample_args.peel()

  if value in [_INT, _INT_OR_RATIONAL]:
    value_entropy = max(1.0, entropy / 4)
    entropy = max(1.0, entropy - value_entropy)
    sampler = _value_sampler(value)
    value = sampler(value_entropy)

  op = arithmetic.arithmetic(
      value=value, entropy=entropy, add_sub=add_sub, mul_div=mul_div,
      length=length)
  context.sample_by_replacing_constants(sample_args, op)

  if is_question:
    # template = random.choice([
    #     '{op}',
    #     'What is {op}?',
    #     'Evaluate {op}.',
    #     'Calculate {op}.',
    #     'What is the value of {op}?',
    # ])
    template = random.choice([
        # '{op}',
        'Чему равно {op}?',
        'Решите {op}.',
        'Вычислите {op}.',
        # 'What is the value of {op}?',
    ])
    return example.Problem(
        question=example.question(context, template, op=op),
        answer=value)
  else:
    return composition.Entity(
        context=context,
        value=value,
        expression=op,
        description='Пусть {self} равняется {op}.',
        op=op)
コード例 #6
0
def gcd(value, sample_args, context=None):
    """Question for greatest common divisor of p and q."""
    is_question = context is None
    if context is None:
        context = composition.Context()

    entropy, sample_args = sample_args.peel()
    if value is None:
        value_entropy = 1 + random.uniform(0, entropy / 3)
        entropy = max(1, entropy - value_entropy)
        value = number.integer(value_entropy, False, min_abs=1)

    p_mult, q_mult = _random_coprime_pair(entropy)

    p = value * p_mult
    q = value * q_mult
    assert sympy.gcd(p, q) == value

    p, q = context.sample(sample_args, [p, q])

    adjective = (random.choice(['наибольший', 'самый большой']) + ' общий ' +
                 random.choice(['знаменатель']))

    if is_question:
        template = random.choice([
            'Расчитайте {adjective} {p} и {q}.',
            'Чему равен {adjective} {p} и {q}?',
        ])
        return example.Problem(question=example.question(context,
                                                         template,
                                                         adjective=adjective,
                                                         p=p,
                                                         q=q),
                               answer=value)
    else:
        return composition.Entity(
            context=context,
            value=value,
            description='Пусть {self} - это {adjective} {p} и {q}.',
            adjective=adjective,
            p=p,
            q=q)
コード例 #7
0
def _add_question_or_entity(context, p, q, is_question):
  """Generates entity or question for adding p + q."""
  value = p.value + q.value

  if is_question:
    # template = random.choice([
    #     '{p} + {q}',
    #     '{p}+{q}',
    #     'Work out {p} + {q}.',
    #     'Add {p} and {q}.',
    #     'Put together {p} and {q}.',
    #     'Sum {p} and {q}.',
    #     'Total of {p} and {q}.',
    #     'Add together {p} and {q}.',
    #     'What is {p} plus {q}?',
    #     'Calculate {p} + {q}.',
    #     'What is {p} + {q}?',
    # ])

    template = random.choice([
        '{p} + {q}',
        '{p}+{q}',
        'Рассчитайте {p} + {q}.',
        'Сложите {p} и {q}.',
        'Прибавьте {p} к {q}.',
        'Найдите сумму {p} и {q}.',
        'Чему равна сумма {p} и {q}.',
        'Сколько получится, если сложить {p} и {q}.',
        'Сколько будет {p} плюс {q}?',
        'Вычислите {p} + {q}.',
        'Чему равно {p} + {q}?',
    ])
    return example.Problem(
        question=example.question(context, template, p=p, q=q),
        answer=value)
  else:
    return composition.Entity(
        context=context,
        value=value,
        description='Пусть {self} = {p} + {q}.',
        p=p, q=q)
コード例 #8
0
def _sub_question_or_entity(context, p, q, is_question):
  """Generates entity or question for subtraction p - q."""
  value = p.value - q.value

  if is_question:
    # templates = [
    #     '{p} - {q}',
    #     'Work out {p} - {q}.',
    #     'What is {p} minus {q}?',
    #     'What is {p} take away {q}?',
    #     'What is {q} less than {p}?',
    #     'Subtract {q} from {p}.',
    #     'Calculate {p} - {q}.',
    #     'What is {p} - {q}?',
    # ]
    templates = [
        '{p} - {q}',
        'Рассчитайте {p} - {q}.',
        'Сколько будет {p} минус {q}?',
        'Сколько будет {p} отнять {q}?',
        'Какое число на {q} меньше {p}?',
        'Отнимите {q} от {p}.',
        'Вычислите {p} - {q}.',
        'Чему равно {p} - {q}?',
    ]
    if sympy.Ge(p.value, q.value):
      # We calculate p - q, so the difference (|p - q|) is the correct answer.
      for adjective in ['разница']:
        for pair in ['{p} и {q}', '{q} и {p}']:
          templates.append('Чему равна {} {}?'.format(adjective, pair))
    template = random.choice(templates)
    return example.Problem(
        question=example.question(context, template, p=p, q=q),
        answer=value)
  else:
    return composition.Entity(
        context=context,
        value=value,
        description='Пусть {self} = {p} - {q}.',
        p=p, q=q)
コード例 #9
0
def div(value, sample_args, context=None):
  """Returns random question for dividing two numbers."""
  del value  # unused
  is_question = context is None
  if context is None:
    context = composition.Context()

  entropy, sample_args = sample_args.peel()
  entropy_1, entropy_q = _entropy_for_pair(entropy)

  q = number.integer(entropy_q, True, min_abs=1)

  if random.choice([False, True]):
    # Pick p/q with nice integer result.
    answer = number.integer(entropy_1, True)
    p = answer * q
  else:
    p = number.integer(entropy_1, True)
    answer = p / q

  p, q = context.sample(sample_args, [p, q])

  if is_question:
    template = random.choice([
        'Разделите {p} на {q}.',
        'Чему равно {p} разделить на {q}',
        'Сколько получится, если {p} поделить на {q}?',
        'Чему равен результат деления {p} на {q}.',
    ])
    return example.Problem(
        question=example.question(context, template, p=p, q=q),
        answer=answer
    )
  else:
    return composition.Entity(
        context=context,
        value=answer,
        description='Пусть {self} равно {p} разделить на {q}.',
        p=p, q=q)
コード例 #10
0
def div_remainder(value, sample_args, context=None):
    """E.g., "What is the remainder when 27 is divided by 5?"."""
    is_question = context is None
    if context is None:
        context = composition.Context()

    entropy, sample_args = sample_args.peel()

    if value is None:
        entropy_value = 1 + random.uniform(0, entropy / 3)
        entropy = max(0, entropy - entropy_value)
        value = number.integer(entropy_value, signed=False)

    entropy_a, entropy_q = entropy * np.random.dirichlet([1, 1])
    a = number.integer(entropy_a, signed=False, min_abs=1)
    q = value + number.integer(entropy_q, signed=False, min_abs=1)

    p = a * q + value
    assert p % q == value
    p, q = context.sample(sample_args, [p, q])

    if is_question:
        template = random.choice([
            'Расчитайте остаток от деления {p} на {q}.',
            'Чему равен остаток деления {p} на {q}?',
        ])
        return example.Problem(question=example.question(
            context,
            template,
            p=p.expression_else_handle,
            q=q.expression_else_handle),
                               answer=value)
    else:
        return composition.Entity(
            context=context,
            value=value,
            description='Пусть {self} - остаток от деления {p} на {q}.',
            p=p,
            q=q)
コード例 #11
0
 def testInit_valueErrorIfSelfAndHandle(self):
   with self.assertRaisesRegexp(ValueError, 'Cannot specify handle'):
     composition.Entity(context=composition.Context(),
                        value=0,
                        description='Something with {self}. ',
                        handle='additional')
コード例 #12
0
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)