Beispiel #1
0
def test_spinors():

    p1 = Symbol('p1', real=True)
    p2 = Symbol('p2', real=True)
    p3 = Symbol('p3', real=True)
    M  = Symbol('M',  real=True)
    p0 = sqrt(p1**2+p2**2+p3**2+M**2)

    dct = {var:uniform(1.,100.) for var in [p1,p2,p3,M]}
    
    # Check normalization of spinors: u*ubar = +2M, v*vbar = -2M
    assert(evaluate((uminus(p0,p1,p2,p3,'a')*uminusbar(p0,p1,p2,p3,'a') )._array[0].subs(dct)) - 2.0*M.subs(dct) < 1.e-11)
    assert(evaluate((vminus(p0,p1,p2,p3,'a')*vminusbar(p0,p1,p2,p3,'a') )._array[0].subs(dct)) + 2.0*M.subs(dct) < 1.e-11)
    assert(evaluate((uplus (p0,p1,p2,p3,'a')*uplusbar (p0,p1,p2,p3,'a') )._array[0].subs(dct)) - 2.0*M.subs(dct) < 1.e-11)
    assert(evaluate((vplus (p0,p1,p2,p3,'a')*vplusbar (p0,p1,p2,p3,'a') )._array[0].subs(dct)) + 2.0*M.subs(dct) < 1.e-11)

    # Check if spinors satisfy Dirac's equation
    dop_u = dirac_op([p0,p1,p2,p3], +M, 'a', 'b')
    dop_v = dirac_op([p0,p1,p2,p3], -M, 'a', 'b')

    d1 = dop_u *(uplus    (p0,p1,p2,p3,'b'))
    d2 = dop_u *(uminus   (p0,p1,p2,p3,'b'))
    d3 = dop_v *(vplus    (p0,p1,p2,p3,'b'))
    d4 = dop_v *(vminus   (p0,p1,p2,p3,'b'))

    for i in range(4):
        assert(Abs(evaluate(d1._array[i]._array[0].subs(dct))) < 1.e-11)
        assert(Abs(evaluate(d2._array[i]._array[0].subs(dct))) < 1.e-11)
        assert(Abs(evaluate(d3._array[i]._array[0].subs(dct))) < 1.e-11)
        assert(Abs(evaluate(d4._array[i]._array[0].subs(dct))) < 1.e-11)
Beispiel #2
0
def str2expr(s, local_dict={}):
    """
    Convert a latex string into a mathematical expression.

    >>> str2expr("x+3+2x")
    x + 2*x + 3
    
    >>> str2expr("2^3")
    2**3
    
    >>> str2expr("sin 2pi")
    sin(2*pi)
    
    >>> str2expr("3!")
    factorial(3)
    """

    pattern = re.compile(r'\\frac\s*{(.*)}{(.*)}')
    s = pattern.sub(r"(\1)/(\2)", s)
    s = s.replace("\\times", "*")
    s = s.replace("\left", "")
    s = s.replace("\right", "")
    s = s.replace('\\', "")
    s = s.replace("{", "(")
    s = s.replace("}", ")")

    transformations = prs.standard_transformations + (
        prs.implicit_multiplication_application, prs.convert_xor)
    with sp.evaluate(False):
        return prs.parse_expr(s,
                              local_dict=local_dict,
                              transformations=transformations,
                              evaluate=False)
def calculate(math_string, x):
    sinA = sympy.sin(30)
    print(sinA)
    result = sympy.evaluate(x + sinA + 4)
    print(sinA)
    result = (sympy.pi + sympy.exp(1)).evalf()
    print(result)
    x = 4
    print((x + sinA).evalf())
Beispiel #4
0
def convert2decim(expr, prec=None):
    if not isinstance(expr, Basic):
        return expr
    dico = {}
    for a in expr.atoms():
        if a.is_Rational:
            dico[a] = Decim(a, prec=prec)
    with evaluate(False):
        return expr.subs(dico)
Beispiel #5
0
def test_hill_function_dwdx():
    """Kinetic laws with Hill functions, may lead to NaNs in the Jacobian
    if involved states are zero if not properly arranged symbolically.
    Test that what we are applying the right sympy simplification."""

    w = sp.Matrix([[sp.sympify('Pow(x1, p1) / (Pow(x1, p1) + a)')]])
    dwdx = w.diff(sp.Symbol('x1'))

    # Verify that without simplification we fail
    with pytest.raises(ZeroDivisionError):
        with sp.evaluate(False):
            res = dwdx.subs({'x1': 0.0})
        _ = str(res)

    # Test that powsimp does the job
    dwdx = dwdx.applyfunc(lambda x: sp.powsimp(x, deep=True))
    with sp.evaluate(False):
        res = dwdx.subs({'x1': 0.0})
    _ = str(res)
Beispiel #6
0
 def generate(self):
     x, y, z = symbols('x y z')
     a, b, c, d, e, f = symbols('a b c d e f')
     substitutions, eqn, LQ = [], None, None
     if self.difficulty == 1:
         eqn, LQ = random.choice([
             (a * (b * x + c), r'{a}({b}x+{c})'),
             (a / d * (b * x + c), r'\frac{{ {a} }}{{ {d} }} ({b}x+{c})'),
             (d + a * (b * x - c), r'{d}+{a}({b}x-{c})'),
             (d + a * (b * x - c / e),
              r'{d}+{a}({b}x-\frac{{ {c} }}{{ {e} }})'),
             (-a * (b * x + c * y), r'-{a}({b}x+{c}y)'),
             (d - a * (-b * x + c * y), r'{d}-{a}(-{b}x+{c}y)'),
             (a * x * (b * y + c * z), r'{a}x({b}y+{c}z)'),
         ])
         substitutions = [
             (a, random.randint(2, 10)),
             (b, random.randint(2, 7)),
             (c, random.randint(2, 10)),
             (d, random.randint(2, 7)),
             (e, random.randint(2, 10)),
         ]
     elif self.difficulty == 2:
         eqn, LQ = random.choice([
             ((a * x + b) * (c * x + d), r'({a}x+{b})({c}x+{d})'),
             ((a / e * x + b) * (c * x + d),
              r'(\frac{{ {a}x }}{{ {e} }}+{b})({c}x+{d})'),
             ((-a * x + b) * (c * x - d),
              random.choice(
                  [r'(-{a}x+{b})({c}x-{d})', r'({c}x-{d})(-{a}x+{b})'])),
             ((a * y + b * x) * (c * y + d + e * z),
              r'({a}y+{b}x)({c}y+{d}+{e}z)'),
         ])
         substitutions = [
             (a, random.randint(2, 7)),
             (b, random.randint(2, 10)),
             (c, random.randint(2, 7)),
             (d, random.randint(2, 10)),
             (e, random.randint(2, 5)),
         ]
     for old, new in substitutions:
         with evaluate(False):
             eqn = eqn.replace(old, new)
     soln = expand(eqn)
     a = substitutions[0][1]
     b = substitutions[1][1]
     c = substitutions[2][1]
     d = substitutions[3][1]
     e = substitutions[4][1]
     Q = getPretty(eqn)
     A = getPretty(soln)
     LQ = '$\displaystyle {}$'.format(LQ.format(a=a, b=b, c=c, d=d, e=e))
     LA = '$\displaystyle {}$'.format(latex(soln))
     return Q, A, LQ, LA
Beispiel #7
0
def get_deviation(f, dct, ignoreset=set()):
    # {sumbol:(value, deviation)}
    sdct = dict((s, Symbol('sigma_' + str(s))) for s in dct)
    sdct2 = dict((sdct[s], dct[s][1]) for s in dct)
    res = sqrt(
        sum([(diff(f, s) * sdct[s])**2 for s in dct if s not in ignoreset]))
    res = simplify(res)
    vls = dict((s, dct[s][0]) for s in dct)
    vls.update(sdct2)
    with evaluate(False):
        step = res.subs(vls)
    return res, step, res.subs(vls)
    def __get_fraction_term(self, var):
        """ Generates a random term with the form "t/d" where t is a random parentesis term generated by __get_parentesis_term and d is a random number.

            Args:
                var: Variable to use in the term.

            Returns:
                A SymPy expression with the form "t/d".
        """
        num = self.__get_parentesis_term(var)
        den = get_random_number(range_list(1, self.maxcoef))
        with sympy.evaluate(False):
            return (num) / (den)
Beispiel #9
0
    def define_steps(self, replacements): 
        # print the base equation, then
        # print the base equation with variable substitution, then
        # print the solution
        expr2 = self.expr
        for _from, _to in replacements:
            with evaluate(False):
                expr2 = expr2.replace(_from,_to)
        
        expr3 = self.expr   
        for _from, _to in replacements:
            expr3 = expr3.subs(_from,_to)

        return self.expr, expr2, expr3
Beispiel #10
0
def test_polvecs():
    
    # Outgoing gluon mom
    k1 = Symbol('k1', real=True)
    k2 = Symbol('k2', real=True)
    k3 = Symbol('k3', real=True)
    k0 = sqrt(k1**2+k2**2+k3**2)
    k  = tensor1d([k0,k1,k2,k3], 'nu')

    # Outgoing gluon reference mom
    g1 = Symbol('g1', real=True)
    g2 = Symbol('g2', real=True)
    g3 = Symbol('g3', real=True)
    g0 = sqrt(g1**2+g2**2+g3**2)

    dct = {var:uniform(1.,100.) for var in [k1,k2,k3,g1,g2,g3]}

    em = epsilonminus(k0,k1,k2,k3, 'mu', g0, g1, g2, g3)
    ep = epsilonplus (k0,k1,k2,k3, 'mu', g0, g1, g2, g3)

    # Test transversality wrt. gluon momentum
    assert(Abs(evaluate((em*mink_metric('mu','nu')*k)._array[0].subs(dct))) < 1.e-11)
    assert(Abs(evaluate((ep*mink_metric('mu','nu')*k)._array[0].subs(dct))) < 1.e-11)

    # Test complex conjugation relation between two helicity states
    for el in (em-conjugate_tensor1d(ep)).elements():
        assert(Abs(evaluate(el._array[0].subs(dct))) < 1.e-11)

    # Test the completeness relation: t and s should be equal
    t  = ep*conjugate_tensor1d(epsilonplus (k0,k1,k2,k3, 'nu', g0, g1, g2, g3))
    t += em*conjugate_tensor1d(epsilonminus(k0,k1,k2,k3, 'nu', g0, g1, g2, g3))

    s  = -mink_metric('mu','nu')
    s += (tensor1d([k0,k1,k2,k3],'mu')*tensor1d([g0,g1,g2,g3],'nu')+tensor1d([k0,k1,k2,k3],'nu')*tensor1d([g0,g1,g2,g3],'mu'))/(tensor1d([k0,k1,k2,k3],'nu')*mink_metric('mu','nu')*tensor1d([g0,g1,g2,g3],'mu'))

    for el in (t-s).elements():
        assert(Abs(evaluate(el._array[0].subs(dct))) < 1.e-11)
Beispiel #11
0
def print_with_deviation(f, dct, ignoreset=set(), notebook=True):
    dct3 = {}
    for name in ignoreset:
        dct3[name] = dct[name][0]
    f = simplify(f.subs(dct3))
    dev = get_deviation(f, dct, ignoreset)
    dct2 = dict((s, dct[s][0]) for s in dct)
    rnd = rounding(float(f.subs(dct2)), float(dev[2]))
    with evaluate(False):
        rnd = (rnd[0], f.subs(dct2), rnd[1])
    res = latex(dev[0]) + '=' + latex(dev[1]) + '={}'.format(dev[2]) + r'\\' +\
          latex(f) + '= {} = {} \\pm {}'.format(rnd[1], rnd[0], rnd[2])
    if notebook:
        return res
    print('$$' + res + '$$')
Beispiel #12
0
    def to_sympy(
        self,
        simplify: Optional[bool] = True,
    ) -> List["sympy_expr.Expr"]:
        """Compile the function(s) represented by the graph to a SymPy expression.

        Generates one SymPy expression for each output node.

        Parameters
        ----------
        simplify : boolean, optional
            Whether to simplify the expression using SymPy's
            simplify() method. Defaults to True.

        Returns
        ----------
        List[sympy.core.expr.Expr]
            List of SymPy expressions.
        """
        if not sympy_available:
            raise ModuleNotFoundError(
                "No module named 'sympy' (extra requirement)")

        self._format_output_str_of_all_nodes()

        sympy_exprs = []
        for output_node in self.output_nodes:

            # replace all input-variable strings with sympy-compatible symbol
            # strings (i.e., x[0] -> x_0)
            s = output_node.output_str
            for input_node in self.input_nodes:
                s = s.replace(
                    input_node.output_str,
                    input_node.output_str.replace("[", "_").replace("]", ""))

            s = self._fill_parameter_values(s)
            # to get an expression that reflects the computational graph,
            # sympy should not automatically simplify the expression
            with sympy.evaluate(False):
                sympy_exprs.append(sympy.sympify(s))

        if not simplify:
            return sympy_exprs
        else:  # simplify expression if desired
            for i, expr in enumerate(sympy_exprs):
                sympy_exprs[i] = expr.simplify()
            return sympy_exprs
Beispiel #13
0
def test_realnumber_field():
    x = sympy.Symbol("x")

    with sympy.evaluate(False):
        test.real = "x"
        assert test.real == x

        test.real = "1 / (x + 1)"
        assert test.real == 1 / (x + 1)

    assert "error" not in Foo.real.validate(5)

    with pytest.raises(TypeError):
        test.real = False
    with pytest.raises(ValueError):
        test.real = "/"
def c_filter(item):
    if isinstance(item, sp.Atom):
        return item

    with evaluate(False):
        rtn = item.__class__(*map(c_filter, item.args))

        # powers of 2 and 3 should just be shown as x*x*x in C; it's faster to skip the function call
        if item.__class__ == Pow and item.args[1] == 2:
            rtn = item.args[0] * item.args[0]
        elif item.__class__ == Pow and item.args[1] == 3:
            rtn = item.args[0] * item.args[0] * item.args[0]
        if item.__class__ == Pow and item.args[1] == -2:
            rtn = 1 / (item.args[0] * item.args[0])
        elif item.__class__ == Pow and item.args[1] == -3:
            rtn = 1 / (item.args[0] * item.args[0] * item.args[0])

        return rtn
    def get_inter_poly(self):
        N = len(self.dt[0])
        x = symbols('x')
        expr = self.dt[1][0]
        count = 1

        for i in range(2, N+1):
            with evaluate(False):
                next_expr = 1

                for j in range(count):
                    next_expr = next_expr * (x - self.dt[0][j])
                next_expr = next_expr * self.dt[i][0]

                expr = expr + next_expr
                count += 1

        self.inter_poly = expr

        return expr
Beispiel #16
0
def test_parse():
    x = Symbol("x")

    with evaluate(False):
        assert parse("5 x + 3") == 5 * x + 3

    assert parse("sqrt x") == sqrt(x)

    assert parse("sqrt 2x") == sqrt(2 * x)

    assert parse("4 + 3") == Add(4, 3, evaluate=False)

    with pytest.raises(TypeError):
        parse({})
    with pytest.raises(ValueError):
        parse("sin (")
    with pytest.raises(ValueError):
        parse("3 *")
    with pytest.raises(ValueError):
        parse("5 =")
Beispiel #17
0
    def create_quiz(self,
                    formula,
                    call,
                    reverse=False,
                    filt=None,
                    domain=None,
                    evaluate=True):
        # expects to parse expression from string and calculate:
        # problem_expr as sympy object (expr or eq)
        # answer_expr as sympy object of the same type

        #formula can be either string or tuple of strings
        if isinstance(formula, str): f = formula
        else: f = reduce(lambda x, y: x + y, formula)

        free_variables = sorted(set(n for n in f if n in 'abcdefghijkl'))
        if domain is None:
            domain = [self.domain for n in range(len(free_variables))]
        #else: expected to be list of lists
        choice = list(itertools.product(*domain))
        if filt is not None:
            choice = list(filter(lambda x: filt(*x), choice))

        if isinstance(formula, str):
            e = [parse_all(formula, transformations=transformations)]
        else:
            e = [
                parse_all(f, transformations=transformations) for f in formula
            ]
        for n in random.sample(choice, self.size):
            N = random.randint(0, len(e) - 1)
            if not (evaluate):
                with sp.evaluate(False):
                    problem_expr = e[N].subs(dict(zip(free_variables, n)))
            else:
                problem_expr = e[N].subs(dict(zip(free_variables, n)))
            answer_expr = call(problem_expr)
            # print(sp.latex(problem_expr))
            # print(sp.latex(answer_expr))
            self.quiz.add(Question(problem_expr, answer_expr))
        if reverse: self.quiz.flip()
Beispiel #18
0
def try_pl(request, pl=None, warning=None):
    with evaluate(False):
        exercise = request.session.get('exercise', None)
    success = None
    feedback = None

    if pl:
        messages.success(request,
                         "Le PL <b>" + pl.name + "</b> a bien été chargé.")
        messages.warning(request, warning)
        messages.error(
            request,
            "Attention, ceci est une session de test, les réponses ne seront pas enregistrer après la fermeture de la fenêtre (Pensez à copier/coller)."
        )

    if not exercise:
        pl_dic = pl.json
        exercise = PythonBuilderTest(pl_dic).get_exercise()
    else:
        exercise = ExerciseTest(exercise)

    if request.method == 'GET' or request.method == 'POST':
        status = None
        try:
            status = json.loads(request.body.decode())
        except:
            pass
        if status and status['requested_action'] == 'submit':
            success, feedback = exercise.evaluate(status['inputs'])
            if (success):
                feedback_type = "success"
            else:
                feedback_type = "failed"
            return HttpResponse(json.dumps({
                'feedback_type': feedback_type,
                'feedback': feedback
            }),
                                content_type='application/json')

    request.session['exercise'] = exercise.dic
    return HttpResponse(exercise.render(request, feedback, success))
Beispiel #19
0
def test_equation_field():
    x, y = sympy.symbols("x y")

    with sympy.evaluate(False):
        test.equation = "3 * x + 5 = 4"
        assert test.equation == sympy.Eq(3 * x + 5, 4)

        test.equation = "3 * x + 5"
        assert test.equation == sympy.Eq(3 * x + 5, 0)

        test.equation = 3 * x + 5
        assert test.equation == sympy.Eq(3 * x + 5, 0)

        test.equation = "2 x + 3 y = y = x + y"
        assert test.equation == (sympy.Eq(2 * x + 3 * y, y), sympy.Eq(y, x + y))

        # If evaluate=True, Eq(1 / x) is False
        test.equation = "1 / x"
        assert test.equation == sympy.Eq(1 / x, 0)

    with pytest.raises(TypeError):
        test.equation = False
    with pytest.raises(ValueError):
        test.equation = "3 x = **"
Beispiel #20
0
	def generate(self):
		a, b, c, d, e, f = symbols('a b c d e f')
		if self.difficulty == 1:
			expr = random.choice([
				a/b + c/d,
			])
			substitutions = [
				(a, random.randint(1, 7)),
				(b, random.randint(2, 7)),
				(c, random.randint(1, 7)),
				(d, random.randint(2, 7)),
			]
			for old, new in substitutions:
				with evaluate(False):
					expr = expr.replace(old, new)
			soln = simplify(expr)
			Q = getPretty(expr)
			A = getPretty(soln)
			LQ = '$\displaystyle {}$'.format(latex(expr))
			LA = '$\displaystyle {}$'.format(latex(soln))
			return Q, A, LQ, LA
		elif self.difficulty == 2:
			expr = random.choice([
				a/b + c/d,
				a/b + c,
				a + c/d,
			])
			substitutions = [
				(a, random.randint(1, 10)),
				(b, random.randint(2, 7)),
				(c, random.randint(1, 10)),
				(d, random.randint(2, 7)),
			]
			for old, new in substitutions:
				with evaluate(False):
					expr = expr.replace(old, new)
			soln = simplify(expr)
			Q = getPretty(expr)
			A = getPretty(soln)
			LQ = '$\displaystyle {}$'.format(latex(expr))
			LA = '$\displaystyle {}$'.format(latex(soln))
			return Q, A, LQ, LA
		elif self.difficulty == 3:
			expr = random.choice([
				a/b - c/d,
				-a/b + c/d,
			])
			substitutions = [
				(a, random.randint(1, 7)),
				(b, random.randint(2, 7)),
				(c, random.randint(1, 7)),
				(d, random.randint(2, 7)),
			]
			for old, new in substitutions:
				with evaluate(False):
					expr = expr.replace(old, new)
			soln = simplify(expr)
			Q = getPretty(expr)
			A = getPretty(soln)
			LQ = '$\displaystyle {}$'.format(latex(expr))
			LA = '$\displaystyle {}$'.format(latex(soln))
			return Q, A, LQ, LA
		elif self.difficulty == 4:
			expr = random.choice([
				a/b - c/d,
				a/b - c,
				a - c/d,
			])
			substitutions = [
				(a, random.randint(1, 10)),
				(b, random.randint(2, 7)),
				(c, random.randint(1, 10)),
				(d, random.randint(2, 7)),
			]
			for old, new in substitutions:
				with evaluate(False):
					expr = expr.replace(old, new)
			soln = simplify(expr)
			Q = getPretty(expr)
			A = getPretty(soln)
			LQ = '$\displaystyle {}$'.format(latex(expr))
			LA = '$\displaystyle {}$'.format(latex(soln))
			return Q, A, LQ, LA
		elif self.difficulty == 5:
			expr = random.choice([
				a/b + c/d,
				a/b + c,
				a + c/d,
				a/b - c/d,
				a/b - c,
				a - c/d,
			])
			substitutions = [
				(a, random.randint(1, 10)),
				(b, random.randint(2, 10)),
				(c, random.randint(1, 10)),
				(d, random.randint(2, 10)),
			]
			for old, new in substitutions:
				with evaluate(False):
					expr = expr.replace(old, new)
			soln = simplify(expr)
			Q = getPretty(expr)
			A = getPretty(soln)
			LQ = '$\displaystyle {}$'.format(latex(expr))
			LA = '$\displaystyle {}$'.format(latex(soln))
			return Q, A, LQ, LA
Beispiel #21
0
 def tosympy(self):  #uses plain text
     if self.plain != '' and self.sympy is None:
         with sp.evaluate(False):
             self.sympy = parse_all(self.get_plain(),
                                    transformations=transformations)
Beispiel #22
0
 def generate(self):
     x = symbols('x')
     a, b, c, d, e, f = symbols('a b c d e f')
     substitutions, eqn, LQ = [], None, None
     if self.difficulty == 1:
         eqn, LQ = random.choice([
             (Eq(x * (x + a), 0), r'x(x+{a}) = 0'),
             (Eq(x * (x + a / b), 0), r'x(x+\frac{{{a}}}{{{b}}}) = 0'),
             (Eq(x * (x - a), 0), r'x(x-{a}) = 0'),
             (Eq(a * x * (x + b), 0), r'{a}x(x+{b}) = 0'),
             (Eq(a * x * (x - b), 0), r'{a}x(x-{b}) = 0'),
             (Eq(a * x * (x - b / c),
                 0), r'{a}x(x-\frac{{{b}}}{{{c}}}) = 0'),
         ])
         substitutions = [
             (a, random.randint(2, 10)),
             (b, random.randint(1, 10)),
             (c, random.randint(1, 10)),
             (d, random.randint(1, 10)),
         ]
     elif self.difficulty == 2:
         eqn, LQ = random.choice([
             (Eq((x + a) * (x + b), 0), r'(x+{a})(x+{b}) = 0'),
             (Eq((x + a) * (x - b), 0),
              random.choice([r'(x+{a})(x-{b}) = 0',
                             r'(x-{b})(x+{a}) = 0'])),
         ])
         substitutions = [
             (a, random.randint(1, 10)),
             (b, random.randint(1, 10)),
             (c, random.randint(1, 10)),
             (d, random.randint(1, 10)),
         ]
     elif self.difficulty == 3:
         eqn, LQ = random.choice([
             (Eq((a * x + b) * (x + b), 0),
              random.choice(
                  [r'({a}x+{b})(x+{b}) = 0', r'(x+{b})({a}x+{b}) = 0'])),
             (Eq((a * x - b) * (x - b), 0),
              random.choice(
                  [r'({a}x-{b})(x-{b}) = 0', r'(x-{b})({a}x-{b}) = 0'])),
             (Eq((a * x + b) * (c * x - d), 0),
              random.choice([
                  r'({a}x+{b})({c}x-{d}) = 0', r'({c}x-{d})({a}x+{b}) = 0'
              ])),
         ])
         substitutions = [
             (a, random.randint(2, 10)),
             (b, random.randint(1, 10)),
             (c, random.randint(2, 10)),
             (d, random.randint(1, 10)),
         ]
     for old, new in substitutions:
         with evaluate(False):
             eqn = eqn.replace(old, new)
     try:
         soln = solve(eqn, x)[0], solve(eqn, x)[1]
     except IndexError:
         # no solution
         soln = 'No solution'
     a = substitutions[0][1]
     b = substitutions[1][1]
     c = substitutions[2][1]
     d = substitutions[3][1]
     Q = getPretty(eqn)
     A = getPretty(soln)
     LQ = '$\displaystyle {}$'.format(LQ.format(a=a, b=b, c=c, d=d))
     LA = '$\displaystyle x={}, \ {}$'.format(soln[0], soln[1])
     return Q, A, LQ, LA
Beispiel #23
0
def _LaTeX_helper(expr, local_dict, global_dict, evalf):
    if expr.strip() == "": return expr
    try:
        if evalf == 2 or type(evalf) == bool and evalf == True:
            if QtWidgets.QApplication.instance(
            ).optionWindow.cb_D_NoEvalFile.isChecked():
                print("True")
            expr = expr.replace("evalf", "", 1)
            rtnexpr = parse_expr(expr,
                                 evaluate=True,
                                 local_dict=local_dict,
                                 global_dict=global_dict)
            rtnexpr = sympy.latex(rtnexpr)
        elif evalf == 1 or type(evalf) == bool and evalf == False:
            if QtWidgets.QApplication.instance(
            ).optionWindow.cb_D_NoEvalFile.isChecked():
                print("False")
            rtnexpr = parse_expr(expr,
                                 evaluate=False,
                                 local_dict=local_dict,
                                 global_dict=global_dict)
            rtnexpr = sympy.latex(rtnexpr)
            try:
                if parse_expr(
                        expr, local_dict=local_dict, global_dict=global_dict
                ) - sympy.parsing.latex.parse_latex(rtnexpr) != 0:
                    rtnexpr = parse_expr(expr,
                                         evaluate=True,
                                         local_dict=local_dict,
                                         global_dict=global_dict)
                    rtnexpr = sympy.latex(rtnexpr)
            except common_exceptions:
                rtnexpr = parse_expr(expr,
                                     evaluate=True,
                                     local_dict=local_dict,
                                     global_dict=global_dict)
                rtnexpr = sympy.latex(rtnexpr)
        elif not QtWidgets.QApplication.instance(
        ).optionWindow.cb_D_NoEvalFile.isChecked():
            rtnexpr = parse_expr(expr,
                                 evaluate=False,
                                 local_dict=local_dict,
                                 global_dict=global_dict)
            rtnexpr = sympy.latex(rtnexpr)

        else:
            try:
                if QtWidgets.QApplication.instance(
                ).optionWindow.cb_D_NoEvalFile.isChecked():
                    print("File")
                Path = os.path.dirname(__file__)
                #if platform.system() == 'Windows':
                #    Path += r"\NoEvalParse.py"
                #elif platform.system() == 'Linux':
                #    Path += r"/NoEvalParse.py"
                Path = os.path.join(Path, "NoEvalParse.py")
                rtnexpr = subprocess.check_output(
                    [sys.executable, Path,
                     expr])  #, local_dict]) # IMPROVE: Make local_dict work
                rtnexpr = rtnexpr.decode("utf8")
                sympy.evaluate(True)
            except common_exceptions:
                ExceptionOutput(sys.exc_info())
                if QtWidgets.QApplication.instance(
                ).optionWindow.cb_D_NoEvalFile.isChecked():
                    print("Failed-->False")
                sympy.evaluate(True)
                rtnexpr = parse_expr(expr,
                                     evaluate=False,
                                     local_dict=local_dict)
                rtnexpr = sympy.latex(rtnexpr)
                try:
                    if parse_expr(
                            expr, local_dict=local_dict
                    ) - sympy.parsing.latex.parse_latex(rtnexpr) != 0:
                        rtnexpr = parse_expr(expr,
                                             evaluate=True,
                                             local_dict=local_dict)
                        rtnexpr = sympy.latex(rtnexpr)
                except common_exceptions:
                    rtnexpr = parse_expr(expr,
                                         evaluate=True,
                                         local_dict=local_dict)
                    rtnexpr = sympy.latex(rtnexpr)
    except common_exceptions:
        ExceptionOutput(sys.exc_info())
        if "=" in expr:
            if QtWidgets.QApplication.instance(
            ).optionWindow.cb_D_NoEvalFile.isChecked():
                print("Failed--> = detected --> Special Treatment")
            try:
                rtnexpr = parse_expr(expr,
                                     evaluate=True,
                                     local_dict=local_dict)
                rtnexpr = sympy.latex(rtnexpr)
                try:
                    if parse_expr(
                            expr, local_dict=local_dict
                    ) - sympy.parsing.latex.parse_latex(rtnexpr) != 0:
                        rtnexpr = parse_expr(expr,
                                             evaluate=True,
                                             local_dict=local_dict)
                        rtnexpr = sympy.latex(rtnexpr)
                except common_exceptions:
                    rtnexpr = parse_expr(expr,
                                         evaluate=True,
                                         local_dict=local_dict)
                    rtnexpr = sympy.latex(rtnexpr)
            except:
                eq = expr.split("=", 1)
                c = eq[0].rsplit("(", 1) + eq[1].split(")", 1)
                rtnexpr = sympy.latex(parse_expr(c[0],evaluate=False,local_dict=local_dict,global_dict=global_dict)) + "(" + \
                          sympy.latex(parse_expr(c[1],evaluate=False,local_dict=local_dict,global_dict=global_dict)) + "=" + \
                          sympy.latex(parse_expr(c[2],evaluate=False,local_dict=local_dict,global_dict=global_dict)) + ")"
                if len(c) == 4:
                    if c[3].strip() != "":
                        rtnexpr += sympy.latex(
                            parse_expr(c[3],
                                       evaluate=False,
                                       local_dict=local_dict,
                                       global_dict=global_dict))
        else:
            if QtWidgets.QApplication.instance(
            ).optionWindow.cb_D_NoEvalFile.isChecked():
                print("Failed-->True")
            sympy.evaluate(True)
            rtnexpr = parse_expr(expr, evaluate=True, local_dict=local_dict)
            rtnexpr = sympy.latex(rtnexpr)
            try:
                if parse_expr(
                        expr, local_dict=local_dict
                ) - sympy.parsing.latex.parse_latex(rtnexpr) != 0:
                    rtnexpr = parse_expr(expr,
                                         evaluate=True,
                                         local_dict=local_dict)
                    rtnexpr = sympy.latex(rtnexpr)
            except common_exceptions:
                rtnexpr = parse_expr(expr,
                                     evaluate=True,
                                     local_dict=local_dict)
                rtnexpr = sympy.latex(rtnexpr)

    return rtnexpr
Beispiel #24
0
import re
import sympy
from sympy.parsing.sympy_parser import parse_expr
from sympy import Matrix, linsolve
common_exceptions = (TypeError, SyntaxError, sympy.SympifyError,
                     sympy.parsing.sympy_parser.TokenError, re.error,
                     AttributeError, ValueError, NotImplementedError,
                     Exception, RuntimeError, ImportError)

if __name__ == "__main__":
    sympy.init_printing()
    if len(sys.argv) == 2:
        my_str_o = decode(sys.argv[1], 'unicode_escape')
        try:
            with sympy.evaluate(False):
                my_str = parse_expr(my_str_o, evaluate=False)
                my_str = sympy.latex(my_str)
        except common_exceptions:
            # The following may look weird but it totally is!!! It does not work in any other way...
            with sympy.evaluate(True):
                my_str = parse_expr(my_str_o, evaluate=True)
                my_str = sympy.latex(my_str)
            my_str = parse_expr(my_str_o, evaluate=False)
            try:
                my_str = sympy.latex(my_str)
            except common_exceptions:
                with sympy.evaluate(True):
                    my_str = parse_expr(my_str_o, evaluate=False)
                    my_str = sympy.latex(my_str)
        # alternatively you transform it to a bytes obj and
Beispiel #25
0
 def generate(self):
     x = symbols('x')
     a, b, c, d, e, f = symbols('a b c d e f')
     if self.difficulty == 1:
         eqn = random.choice([
             Eq(x + a, b),
             Eq(x - a, b),
             Eq(a * x, b),
             Eq(x / a, b),
         ])
         eqn = eqn.subs([
             (a, random.randint(2, 10)),
             (b, random.randint(0, 10)),
         ])
         soln = Eq(x, solve(eqn, x)[0])
         Q = getPretty(eqn)
         A = getPretty(soln)
         LQ = '$\displaystyle {}$'.format(latex(eqn))
         LA = '$\displaystyle {}$'.format(latex(soln))
         return Q, A, LQ, LA
     elif self.difficulty == 2:
         eqn = random.choice([
             Eq(a * x + b, c),
             Eq(a * x + b / d, c),
             Eq(a * x - b, c),
             Eq(a * x - b / d, c),
             Eq(x / a + b, c),
             Eq(x / a - b, c),
         ])
         # todo flip sides of equations randomly
         eqn = eqn.subs([
             (a, random.randint(2, 10)),
             (b, random.randint(1, 10)),
             (c, random.randint(0, 10)),
             (d, random.randint(2, 7)),
         ])
         # todo my own function that uses try/except to find no solutions
         soln = Eq(x, solve(eqn, x)[0])
         # todo Q, A = getPretty(eqn, soln)
         # todo LQ, LA = getLatex(eqn, soln)
         Q = getPretty(eqn)
         A = getPretty(soln)
         LQ = '$\displaystyle {}$'.format(latex(eqn))
         LA = '$\displaystyle {}$'.format(latex(soln))
         return Q, A, LQ, LA
     elif self.difficulty == 3:
         eqn = random.choice([
             Eq(a * x + b + c * x, d),
             Eq(a * x + b, d + c * x),
         ])
         substitutions = [
             (a, randIntExcept(-10, 10)),
             (b, randIntExcept(-10, 10)),
             (c, randIntExcept(-10, 10)),
             (d, randIntExcept(-10, 10)),
         ]
         for old, new in substitutions:
             with evaluate(False):
                 eqn = eqn.replace(old, new)
         try:
             soln = Eq(x, solve(eqn, x)[0])
         except IndexError:
             # no solution - lines are parallel
             soln = 'No solution'
         Q = getPretty(eqn)
         A = getPretty(soln)
         LQ = '$\displaystyle {}$'.format(latex(eqn))
         LA = '$\displaystyle {}$'.format(latex(soln))
         return Q, A, LQ, LA
     elif self.difficulty == 4:
         eqn = random.choice([
             Eq(a * x + b + c * x, d + e * x),
         ])
         substitutions = [
             (a, randIntExcept(-10, 10)),
             (b, randIntExcept(-10, 10)),
             (c, randIntExcept(-10, 10)),
             (d, randIntExcept(-10, 10)),
             (e, randIntExcept(-10, 10)),
         ]
         for old, new in substitutions:
             with evaluate(False):
                 eqn = eqn.replace(old, new)
         try:
             soln = Eq(x, solve(eqn, x)[0])
         except IndexError:
             # no solution - lines are parallel
             soln = 'No solution'
         Q = getPretty(eqn)
         A = getPretty(soln)
         LQ = '$\displaystyle {}$'.format(latex(eqn))
         LA = '$\displaystyle {}$'.format(latex(soln))
         return Q, A, LQ, LA
Beispiel #26
0
    def run(self, dag):
        """Translate an input DAGCircuit to the target basis.

        Args:
            dag (DAGCircuit): input dag

        Raises:
            TranspilerError: if the target basis cannot be reached

        Returns:
            DAGCircuit: translated circuit.
        """

        if self._target_basis is None:
            return dag

        # Names of instructions assumed to supported by any backend.
        basic_instrs = ['measure', 'reset', 'barrier', 'snapshot', 'delay']

        target_basis = set(self._target_basis).union(basic_instrs)

        source_basis = set()
        for node in dag.op_nodes():
            if not dag.has_calibration_for(node):
                source_basis.add((node.name, node.op.num_qubits))

        logger.info(
            'Begin BasisTranslator from source basis %s to target '
            'basis %s.', source_basis, target_basis)

        # Search for a path from source to target basis.

        search_start_time = time.time()
        basis_transforms = _basis_search(self._equiv_lib, source_basis,
                                         target_basis, _basis_heuristic)
        search_end_time = time.time()
        logger.info('Basis translation path search completed in %.3fs.',
                    search_end_time - search_start_time)

        if basis_transforms is None:
            raise TranspilerError(
                'Unable to map source basis {} to target basis {} '
                'over library {}.'.format(source_basis, target_basis,
                                          self._equiv_lib))

        # Compose found path into a set of instruction substitution rules.

        compose_start_time = time.time()
        instr_map = _compose_transforms(basis_transforms, source_basis, dag)

        compose_end_time = time.time()
        logger.info('Basis translation paths composed in %.3fs.',
                    compose_end_time - compose_start_time)

        # Replace source instructions with target translations.

        replace_start_time = time.time()
        for node in dag.op_nodes():
            if node.name in target_basis:
                continue

            if dag.has_calibration_for(node):
                continue

            if (node.op.name, node.op.num_qubits) in instr_map:
                target_params, target_dag = instr_map[node.op.name,
                                                      node.op.num_qubits]

                if len(node.op.params) != len(target_params):
                    raise TranspilerError(
                        'Translation num_params not equal to op num_params.'
                        'Op: {} {} Translation: {}\n{}'.format(
                            node.op.params, node.op.name, target_params,
                            target_dag))

                if node.op.params:
                    # Convert target to circ and back to assign_parameters, since
                    # DAGCircuits won't have a ParameterTable.
                    from qiskit.converters import dag_to_circuit, circuit_to_dag
                    target_circuit = dag_to_circuit(target_dag)

                    target_circuit.assign_parameters(dict(
                        zip_longest(target_params, node.op.params)),
                                                     inplace=True)

                    bound_target_dag = circuit_to_dag(target_circuit)
                else:
                    bound_target_dag = target_dag

                if (len(bound_target_dag.op_nodes()) == 1
                        and len(bound_target_dag.op_nodes()[0].qargs) == len(
                            node.qargs)):
                    dag_op = bound_target_dag.op_nodes()[0].op
                    # dag_op may be the same instance as other ops in the dag,
                    # so if there is a condition, need to copy
                    if node.op.condition:
                        dag_op = dag_op.copy()
                    dag.substitute_node(node, dag_op, inplace=True)

                    if bound_target_dag.global_phase:
                        from sympy import evaluate
                        with evaluate(False):
                            dag.global_phase += bound_target_dag.global_phase
                else:
                    dag.substitute_node_with_dag(node, bound_target_dag)
            else:
                raise TranspilerError('BasisTranslator did not map {}.'.format(
                    node.name))

        replace_end_time = time.time()
        logger.info('Basis translation instructions replaced in %.3fs.',
                    replace_end_time - replace_start_time)

        return dag
Beispiel #27
0
	def generate(self):
		a, b, c, d, e, f = symbols('a b c d e f')
		substitutions, expr, LQ = [], None, None
		if self.difficulty == 1:
			expr, LQ = random.choice([
				(a/b * c/d, r'\frac{{{a}}}{{{b}}} \times \frac{{{c}}}{{{d}}}')
			])
			substitutions = [
				(a, random.randint(1, 7)),
				(b, random.randint(2, 7)),
				(c, random.randint(1, 7)),
				(d, random.randint(2, 7)),
			]
		elif self.difficulty == 2:
			expr, LQ = random.choice([
				(a/b * c/d, r'\frac{{{a}}}{{{b}}} \times \frac{{{c}}}{{{d}}}'),
				(a/b * c, r'\frac{{{a}}}{{{b}}} \times {c}'),
				(a * c/d, r'{a} \times \frac{{{c}}}{{{d}}}'),
			])
			substitutions = [
				(a, random.randint(1, 10)),
				(b, random.randint(2, 7)),
				(c, random.randint(1, 10)),
				(d, random.randint(2, 7)),
			]
		elif self.difficulty == 3:
			expr, LQ = random.choice([
				((a/b) / (c/d), r'\frac{{{a}}}{{{b}}} \div \frac{{{c}}}{{{d}}}'),
				(-(a/b) / (c/d), r'-\frac{{{a}}}{{{b}}} \div \frac{{{c}}}{{{d}}}'),
			])
			substitutions = [
				(a, random.randint(1, 7)),
				(b, random.randint(2, 7)),
				(c, random.randint(1, 7)),
				(d, random.randint(2, 7)),
			]
		elif self.difficulty == 4:
			expr, LQ = random.choice([
				((a/b) / (c/d), r'\frac{{{a}}}{{{b}}} \div \frac{{{c}}}{{{d}}}'),
				((a/b) / c, r'\frac{{{a}}}{{{b}}} \div {c}'),
				(a / (c/d), r'{a} \div \frac{{{c}}}{{{d}}}'),
			])
			substitutions = [
				(a, random.randint(1, 10)),
				(b, random.randint(2, 7)),
				(c, random.randint(1, 10)),
				(d, random.randint(2, 7)),
			]
		elif self.difficulty == 5:
			expr, LQ = random.choice([
				(a/b * c/d, r'\frac{{{a}}}{{{b}}} \times \frac{{{c}}}{{{d}}}'),
				(a/b * c, r'\frac{{{a}}}{{{b}}} \times {c}'),
				(a * c/d, r'{a} \times \frac{{{c}}}{{{d}}}'),
				((a/b) / (c/d), r'\frac{{{a}}}{{{b}}} \div \frac{{{c}}}{{{d}}}'),
				((a/b) / c, r'\frac{{{a}}}{{{b}}} \div {c}'),
				(a / (c/d), r'{a} \div \frac{{{c}}}{{{d}}}'),
			])
			substitutions = [
				(a, random.randint(1, 10)),
				(b, random.randint(2, 10)),
				(c, random.randint(1, 10)),
				(d, random.randint(2, 10)),
			]
		assert len(substitutions) > 0
		for old, new in substitutions:
			with evaluate(False):
				expr = expr.replace(old, new)
		a = substitutions[0][1]
		b = substitutions[1][1]
		c = substitutions[2][1]
		d = substitutions[3][1]
		soln = simplify(expr)
		Q = getPretty(expr)
		A = getPretty(soln)
		LQ = '$\displaystyle {}$'.format(LQ.format(a=a, b=b, c=c, d=d))
		LA = '$\displaystyle {}$'.format(latex(soln))
		return Q, A, LQ, LA
Beispiel #28
0
def test_default_values():
    form = CustomForm(required="Hello")
    assert form.required == "Hello"

    with sympy.evaluate(False):
        assert form.equation == sympy.Eq(sympy.Symbol("x")**3, 0)
Beispiel #29
0
    def react(self, x, master=None):
        if x=='OK':
            if self.state == 'active': #if self.problem is None:
                self.compile = False
                self.specialform = Specialform()
                if self.winner.field.grid_info(): self.winner.field.grid_remove()
                if self.loser.field.grid_info(): self.loser.field.grid_remove()
                if self.unclear.field.grid_info(): self.unclear.field.grid_remove()
                try:
                    self.question = self.quiz.next()
                    #print(self.question.problem, self.question.answer)
                    self.problem.update(Symform(self.question.problem))
                except StopIteration:
                    if not(self.iteration_stopped):
                        write('register.txt', self.kwargs['type'],
                              tuple(datetime.now().timetuple())[1:5],
                              round(time.time() - self.inception_time), self.score)
                        self.iteration_stopped = True

                    if self.score >= 9:
                        self.finals_photo = ImageTk.PhotoImage(self.finals_image1)
                        self.level = Level(self, self.tasks)
                    elif self.score >= 7: self.finals_photo = ImageTk.PhotoImage(self.finals_image2)
                    else: self.finals_photo = ImageTk.PhotoImage(self.finals_image3)
                    self.finals_field = Label(master, image=self.finals_photo)
                    self.finals_field.grid(row=1, column=6, rowspan=2, sticky="nsew")
                    self.problem.update(Symform(''))
                    self.answer.update(Symform(''))
                else:
                    self.symform = Symform('')
                    self.state = 'not active'
                    self.timer.reset()
            else:
                if self.specialform.state == 2: #COPYPASTING
                    self.specialform.state = 0
                    self.superbutton.button.configure(bg='#007f7f', text='·/·', relief='raised')
                    with sp.evaluate(False):
                        self.compile = True
                        self.symform.add(
                            f'{self.specialform.symform1.get_plain()}/{self.specialform.symform2.get_plain()}')
                try:
                    self.symform.tosympy()
                except Exception as e:
                    print('Exception: can''t convert input form to sympy expression')
                    self.unclear.field.grid(row=1, column=6, rowspan=2, sticky="nsew")
                else:
                    print(f'input converted to: {self.symform.get_sympy()}, correct input: {self.question.answer}')
                    if self.is_equal(self.symform.get_sympy(), self.question.answer):
                        self.score += 1
                        self.answer.check(True)
                        self.winner.field.grid(row=1, column=6, rowspan=2, sticky="nsew")
                        self.starpacket.credit(True)
                    else:
                        self.answer.check(False, symform = Symform(self.question.answer))
                        self.loser.field.grid(row=1, column=6, rowspan=2, sticky="nsew")
                        self.starpacket.credit(False)
                    self.state = 'active'

        elif x=='back':
            self.symform.rewind()
        elif x=='²':
            self.symform.add('^2')
        elif x=='·/·':
            #self.symform.plain += r'\frac{\cdot}{\dots}' #???
            if self.specialform.state == 0:
                self.specialform.state = 1
                self.superbutton.button.configure(bg='orange', text='▯/·', relief='groove')
                #self.symform.add(x)
            elif self.specialform.state == 1:
                self.specialform.state = 2
                self.superbutton.button.configure(bg='green', text='·/▯', relief='groove')
            elif self.specialform.state == 2:
                self.specialform.state = 0
                self.superbutton.button.configure(bg='#007f7f', text='·/·', relief='raised')
                '''self.specialform.symform1.tosympy()
                self.specialform.symform2.tosympy()
                nom = self.specialform.symform1.get_sympy()
                denom = self.specialform.symform2.get_sympy()'''
                with sp.evaluate(False):
                    self.compile = True
                    self.symform.add(f'{self.specialform.symform1.get_plain()}/{self.specialform.symform2.get_plain()}')
        else:
            if self.specialform.state != 0:
                self.specialform.add(x)
            else:
                self.symform.add(x)
        if self.state == 'not active':
            try:
                if self.specialform.state == 0:
                    self.answer.update(self.symform, compile=self.compile)
                elif self.specialform.state == 1:
                    if self.specialform.symform1.get_plain()=='':
                        specplain = r'\frac{\ }{\ }'
                    else:
                        specplain = r'\frac{' + self.specialform.symform1.get_plain()+r'}{\ }'
                    self.answer.update(Symform(self.symform.plain + specplain), compile=False)
                elif self.specialform.state == 2:
                    if self.specialform.symform1.get_plain() == '':
                        self.specialform.state = 1
                        self.superbutton.button.configure(bg='orange', text='▯/·', relief='groove')
                        raise ValueError
                    if self.specialform.symform2.get_plain() == '':
                        specplain = r'\frac{' + self.specialform.symform1.get_plain() + r'}{\ }'
                    else:
                        specplain = r'\frac{' + self.specialform.symform1.get_plain() + r'}{'+\
                        self.specialform.symform2.get_plain()+r'}'
                    self.answer.update(Symform(self.symform.plain + specplain), compile=False)
            except ValueError:
                print('Exception: cant display your input:', self.symform.plain)
                self.unclear.field.grid(row=1, column=6, rowspan=2, sticky="nsew")
                self.symform.plain = ''
Beispiel #30
0
 def generate(self):
     x = symbols('x')
     a, b, c, d, e, f = symbols('a b c d e f')
     substitutions, eqn, LQ = [], None, None
     # HCF
     if self.difficulty == 1:
         expr = expand(random.choice([
             x * (x + a),
             x * (x - a),
         ]))
         if random.random() < 0.3:
             expr *= b
         if random.random() < 0.3:
             expr *= -1
         eqn = Eq(expr, 0)
         substitutions = [
             (a, random.randint(2, 10)),
             (b, random.randint(2, 10)),
             (c, random.randint(2, 10)),
             (d, random.randint(1, 10)),
         ]
     # Cross
     elif self.difficulty == 2:
         expr = expand(
             random.choice([
                 (x + a) * (x + b),
                 (x - a) * (x + b),
                 (x + a) * (x - b),
                 (x - a) * (x - b),
             ]))
         if random.random() < 0.5:
             expr *= c
         eqn = Eq(expr, 0)
         substitutions = [
             (a, random.randint(2, 10)),
             (b, random.randint(1, 6)),
             (c, random.randint(2, 5)),
             (d, random.randint(1, 10)),
         ]
     # DOPS
     elif self.difficulty == 3:
         expr = expand(
             random.choice([
                 (x + a) * (x - a),
                 (a * x + b) * (a * x - b),
             ]))
         if random.random() < 0.3:
             expr *= c
         eqn = Eq(expr, 0)
         substitutions = [
             (a, random.randint(2, 10)),
             (b, random.randint(1, 10)),
             (c, random.randint(2, 5)),
             (d, random.randint(1, 10)),
         ]
     # Non-monic
     elif self.difficulty == 4:
         expr = expand(
             random.choice([
                 (a * x + b) * (x + d),
                 (a * x + b) * (c * x + d),
             ]))
         if random.random() < 0.3:
             expr *= a
         eqn = Eq(expr, 0)
         substitutions = [
             (a, random.randint(2, 4)),
             (b, random.randint(2, 10)),
             (c, random.randint(2, 5)),
             (d, random.randint(2, 5)),
         ]
     for old, new in substitutions:
         with evaluate(True):
             eqn = eqn.replace(old, new)
     try:
         soln = solve(eqn, x)[0], solve(eqn, x)[1]
     except IndexError:
         # no solution
         soln = 'No solution'
     a = substitutions[0][1]
     b = substitutions[1][1]
     c = substitutions[2][1]
     d = substitutions[3][1]
     Q = getPretty(eqn)
     A = getPretty(soln)
     LQ = '$\displaystyle {}$'.format(latex(eqn))
     LA = '$\displaystyle x={}, \ {}$'.format(soln[0], soln[1])
     return Q, A, LQ, LA