def test_sets(): x = Integer(2) y = Integer(3) x1 = sympy.Integer(2) y1 = sympy.Integer(3) assert Interval(x, y) == Interval(x1, y1) assert Interval(x1, y) == Interval(x1, y1) assert Interval(x, y)._sympy_() == sympy.Interval(x1, y1) assert sympify(sympy.Interval(x1, y1)) == Interval(x, y) assert sympify(sympy.EmptySet()) == EmptySet() assert sympy.EmptySet() == EmptySet()._sympy_() assert FiniteSet(x, y) == FiniteSet(x1, y1) assert FiniteSet(x1, y) == FiniteSet(x1, y1) assert FiniteSet(x, y)._sympy_() == sympy.FiniteSet(x1, y1) assert sympify(sympy.FiniteSet(x1, y1)) == FiniteSet(x, y) x = Interval(1, 2) y = Interval(2, 3) x1 = sympy.Interval(1, 2) y1 = sympy.Interval(2, 3) assert Union(x, y) == Union(x1, y1) assert Union(x1, y) == Union(x1, y1) assert Union(x, y)._sympy_() == sympy.Union(x1, y1) assert sympify(sympy.Union(x1, y1)) == Union(x, y) assert Complement(x, y) == Complement(x1, y1) assert Complement(x1, y) == Complement(x1, y1) assert Complement(x, y)._sympy_() == sympy.Complement(x1, y1) assert sympify(sympy.Complement(x1, y1)) == Complement(x, y)
def __init__(self, difficulty, var=None): if var is None: var = x if difficulty == 1: c = 0 m = random.randint(-coefficients_bound + 2, coefficients_bound - 4) if m >= 0: # make sure m is not 0 or 1 m += 2 elif difficulty == 2: c = not_named_yet.randint_no_zero(-coefficients_bound, coefficients_bound) m = 1 elif difficulty == 3: c = not_named_yet.randint_no_zero(-coefficients_bound, coefficients_bound) m = random.randint(-coefficients_bound + 2, coefficients_bound - 4) if m >= 0: # make sure m is not 0 or 1 m += 2 else: raise ValueError( 'You have supplied an invalid difficulty level! Choose between 1, 2 or 3.' ) self.equation = m * var + c self.domain = sympy.Interval(-sympy.oo, sympy.oo, True, True) self.range = sympy.Interval(-sympy.oo, sympy.oo, True, True)
def __init__(self, difficulty): if difficulty not in [1, 2, 3]: raise ValueError('You gave an invalid difficulty of %d!' % difficulty) while True: a = not_named_yet.randint_no_zero(-coefficients_bound + 2, coefficients_bound - 2) b = random.randint(-coefficients_bound * 4, coefficients_bound * 4) c = random.randint(-coefficients_bound * 4, coefficients_bound * 4) discriminant = b**2 - 4 * a * c if difficulty == 1 and discriminant == 0 and (b == 0 or c == 0): break elif difficulty == 2 and discriminant > 0 and gmpy.is_square( discriminant): break elif difficulty == 3 and discriminant > 0 and not gmpy.is_square( discriminant): break self.equation = a * x**2 + b * x + c self.discriminant = b**2 - 4 * a * c self.domain = sympy.Interval(-sympy.oo, sympy.oo, True, True) vertex_x = -sympy.Rational(b, 2 * a) vertex_y = self.equation.subs({x: vertex_x}) if a > 0: self.range = sympy.Interval(vertex_y, sympy.oo, False, True) else: self.range = sympy.Interval(-sympy.oo, vertex_y, True, False)
def __init__(self, difficulty): a = not_named_yet.randint_no_zero(-3, 2) k = not_named_yet.randint_no_zero(-2, 2) c = not_named_yet.randint_no_zero(-5, 5) if a == 1: a += 1 if difficulty == 1: self.equation = sympy.exp(k * x) + c elif difficulty == 2: self.equation = a * sympy.exp(k * x) + c elif difficulty == 3: inner_function = request_linear(difficulty=3).equation self.equation = a * sympy.exp(inner_function) + c else: raise ValueError( 'You have given an invalid difficulty level! Please use difficulty levels 1-3' ) self.domain = sympy.Interval(-sympy.oo, sympy.oo, True, True) if a < 0: self.range = sympy.Interval(-sympy.oo, c, True, True) else: self.range = sympy.Interval(c, sympy.oo, True, True)
def __init__(self, part): self.num_lines, self.num_marks = 2, 1 self._qp = copy.deepcopy(part._qp) self._qp['interval'] = random.choice([ sympy.Interval(-sympy.oo, self._qp['mean']), sympy.Interval(self._qp['mean'], sympy.oo) ])
def to_port_annotation(parsed): # convert both single port and ranges into sympy.Interval # (open intervals) if isinstance(parsed, int): rv = sm.Interval(parsed - 1, parsed + 1, True, True) else: rv = sm.Interval(parsed[0] - 1, parsed[1] + 1, True, True) return rv
def Inflection_Interval(self): I=self.inflection_points() if len(I)>1: a=min(I) b=max(I) return sp.Interval(a,b) else: return sp.Interval(-10,10)
def __init__(self, part): self.num_lines, self.num_marks = 12, 3 self._qp = copy.deepcopy(part._qp) domain = sympy.Interval(-2 * sympy.pi, 2 * sympy.pi) bounds = sensible_values.integral_domain(self._qp['equation'], domain) self._qp['domain'] = sympy.Interval(bounds[0], bounds[1]) self._qp['answer'] = self._qp['hidden_objective'].integrate( (x, self._qp['domain'].left, self._qp['domain'].right))
def solution_statement(self): lines = solutions.Lines() left_pr = sympy.Rational(1, 2) if self._qp['event_provided_to_student'].left == -sympy.oo: symmetrically_opposite_event = sympy.Interval( self._qp['mean'], self._qp['point']) opposite_half_of_normal_distribution = sympy.Interval( self._qp['mean'], sympy.oo) event_provided_to_student = sympy.Interval( self._qp['event_provided_to_student'].right, sympy.oo) right_pr = self._qi['unknown_variable'] elif self._qp['event_provided_to_student'].right == sympy.oo: symmetrically_opposite_event = sympy.Interval( self._qp['point'], self._qp['mean']) opposite_half_of_normal_distribution = sympy.Interval( -sympy.oo, self._qp['mean']) event_provided_to_student = sympy.Interval( -sympy.oo, self._qp['event_provided_to_student'].left) right_pr = 1 - self._qi['unknown_variable'] elif self._qp['point'] < self._qp['mean']: symmetrically_opposite_event = sympy.Interval( -sympy.oo, self._qp['point']) opposite_half_of_normal_distribution = sympy.Interval( -sympy.oo, self._qp['mean']) event_provided_to_student = self._qp['event_provided_to_student'] right_pr = self._qi['unknown_variable'] else: symmetrically_opposite_event = sympy.Interval( self._qp['point'], sympy.oo) opposite_half_of_normal_distribution = sympy.Interval( self._qp['mean'], sympy.oo) event_provided_to_student = self._qp['event_provided_to_student'] right_pr = 1 - self._qi['unknown_variable'] # e.g. Pr(56 <= X <= 60) = Pr(60 <= X <= 64) = Pr(X >= 60) - Pr(X >= 64) lines += r'''$Pr({desired_event}) = Pr({symmetrically_opposite_event}) = Pr({opposite_half_of_normal_distribution}) - Pr({event_provided_to_student})$'''.format( desired_event=expressions.relation(self._qp['desired_event'], var=X), symmetrically_opposite_event=expressions.relation( symmetrically_opposite_event, var=X), opposite_half_of_normal_distribution=expressions.relation( opposite_half_of_normal_distribution, var=X), event_provided_to_student=expressions.relation( event_provided_to_student, var=X), ) # e.g. = (1/2) - (-c + 1) = c - 1/2 lines += r'$= ({half_interval_probability}) - ({probability_derived_from_question}) = {answer}$'.format( half_interval_probability=sympy.latex(left_pr), probability_derived_from_question=sympy.latex(right_pr), answer=sympy.latex(self._qp['answer'])) return lines.write()
def test_is_monotone_increasing(): assert functions.is_monotone_increasing(sympy.exp(x)) assert functions.is_monotone_increasing(x**3) assert functions.is_monotone_increasing(x**2, sympy.Interval(0, oo, False, True)) assert functions.is_monotone_increasing( sympy.sin(x), sympy.Interval(0, sympy.pi / 2, False, False)) assert functions.is_monotone_increasing(-1 / x) assert not functions.is_monotone_increasing(x**4)
def detect_multi_stability(cls, chnk_stable, chnk_unstable, bi_data_np): if cls.is_list_empty(chnk_stable) or cls.is_list_empty(chnk_unstable): return False chnk_stable_pcp_ranges = [] for i in range(len(chnk_stable)): end_ind = len(chnk_stable[i]) - 1 chnk_stable_pcp_ranges.append([ bi_data_np[chnk_stable[i][0], 0], bi_data_np[chnk_stable[i][end_ind], 0] ]) [i.sort() for i in chnk_stable_pcp_ranges] chnk_unstable_pcp_ranges = [] for i in range(len(chnk_unstable)): end_ind = len(chnk_unstable[i]) - 1 chnk_unstable_pcp_ranges.append([ bi_data_np[chnk_unstable[i][0], 0], bi_data_np[chnk_unstable[i][end_ind], 0] ]) [i.sort() for i in chnk_unstable_pcp_ranges] chnk_unstable_pcp_intervals = [] chnk_stable_pcp_intervals = [] for i in range(len(chnk_unstable)): chnk_unstable_pcp_intervals.append( sympy.Interval(chnk_unstable_pcp_ranges[i][0], chnk_unstable_pcp_ranges[i][1])) for i in range(len(chnk_stable)): chnk_stable_pcp_intervals.append( sympy.Interval(chnk_stable_pcp_ranges[i][0], chnk_stable_pcp_ranges[i][1])) # building intersections of unstable branch with stable branches unstable_intersections = [] for i in chnk_unstable_pcp_intervals: temp_list = [] for j in chnk_stable_pcp_intervals: temp = i.intersect(j) if temp != sympy.EmptySet(): if not temp.is_FiniteSet: temp_list.append(1) elif temp.is_FiniteSet and len(list(temp)) > 1: temp_list.append(1) unstable_intersections.append(temp_list) return any([sum(i) >= 2 for i in unstable_intersections])
def relation_to_interval(relation): if isinstance(relation, sympy.Or): return functools.reduce(operator.or_, [relation_to_interval(i) for i in relation.args]) elif isinstance(relation, sympy.And): return functools.reduce(operator.and_, [relation_to_interval(i) for i in relation.args]) if relation.rel_op == '>': if isinstance(relation.lhs, sympy.Symbol): return sympy.Interval(relation.rhs, sympy.oo, True, True) else: return sympy.Interval(-sympy.oo, relation.lhs, True, True) elif relation.rel_op == '>=': if isinstance(relation.lhs, sympy.Symbol): return sympy.Interval(relation.rhs, sympy.oo) else: return sympy.Interval(-sympy.oo, relation.lhs) elif relation.rel_op == '<': if isinstance(relation.lhs, sympy.Symbol): return sympy.Interval(-sympy.oo, relation.rhs, True, True) else: return sympy.Interval(relation.lhs, sympy.oo, True, True) elif relation.rel_op == '<=': if isinstance(relation.lhs, sympy.Symbol): return sympy.Interval(-sympy.oo, relation.rhs) else: return sympy.Interval(relation.lhs, sympy.oo)
def construct_interval(boundary1, boundary2): """Construct a sympy interval from two boundaries, when we don't know which boundary is bigger. >>> SimpleNormalDistribution.construct_interval(0, 1) [0, 1] >>> SimpleNormalDistribution.construct_interval(sympy.oo, 1) [1, oo) """ if boundary1 < boundary2: return sympy.Interval(boundary1, boundary2) else: return sympy.Interval(boundary2, boundary1)
def integer_domain(low=-5, high=5, minimum_distance=3): """ Return a sympy.Interval domain with min/max bounds of input variables low and high. The interval is chosen by selecting integers randomly: random.randint(low, high) """ while True: b1 = random.randint(low, high) b2 = random.randint(low, high) if b1 + minimum_distance <= b2: return sympy.Interval(b1, b2, False, False) elif b2 + minimum_distance <= b1: return sympy.Interval(b2, b1, False, False)
def rand_interval_type(a, b): """ Generate an interval with random type of bounds. """ bl = rd.choice([True, False]) br = rd.choice([True, False]) return sp.Interval(a, b, left_open=bl, right_open=br)
def remove_nonzero_factors(eqn, reduce_monomials=False, atom_bounds=None): if eqn == 0: return eqn result = 1 domains = {} for atom in [a for a in eqn.atoms() if a.is_symbol]: if atom_bounds and atom in atom_bounds: domains[atom] = sp.Interval(*atom_bounds[atom]) else: domains[atom] = sp.Reals for factor in sp.factor(sp.cancel(eqn)).args: if isinstance(factor, sp.Pow) and factor.args[1] < 0: continue if reduce_monomials: atoms = [a for a in factor.atoms() if a.is_symbol] if len(atoms) == 1: a, = atoms solve_set = sp.solveset(factor, domain=domains[a]) if not solve_set: continue result *= factor return result
def axvspan(self, axes=None, phase_offsets=[0], **kwargs): """ Overlay range on matplotlib axes. N.B. set phase_offsets=[0,1] to overlay on phaseogram that varies from 0 to 2 the phase range both on the 0-1 and the 1-2 part of the plot. """ import pylab as P if axes is None: axes=P.gca() label=kwargs.pop('label',None) if phase_offsets != [0] and phase_offsets !=0: # kind of ugly, but create a larger PhaseRange object # temporarily with the offsets. This allows for # merging needed offsets. # (a) create a giant list of all phases all_phases = reduce(add,[[[a+o,b+o] for a,b in self.tolist(dense=False)] for o in phase_offsets]) # (b) turn the list of ranges into a sympy object interval = sympy.Union([sympy.Interval(a,b) for a,b in all_phases]) # (c) cretae a temporary phase range object which spans all intervals temp = PhaseRange() temp.range = interval else: temp=self ret = [] for a,b in temp.tolist(dense=False): ret.append(axes.axvspan(a, b, label=label, **kwargs)) label=None return ret
def transform_set(x, expr, sympy_set): """ Transform a sympy_set by an expression >>> x = sympy.Symbol('x') >>> domain = sympy.Interval(-sympy.pi / 4, -sympy.pi / 6, False, True) | sympy.Interval(sympy.pi / 6, sympy.pi / 4, True, False) >>> transform_set(x, -2 * x, domain) [-pi/2, -pi/3) U (pi/3, pi/2] """ if isinstance(sympy_set, sympy.Union): return sympy.Union( transform_set(x, expr, arg) for arg in sympy_set.args) if isinstance(sympy_set, sympy.Intersection): return sympy.Intersection( transform_set(x, expr, arg) for arg in sympy_set.args) f = sympy.Lambda(x, expr) if isinstance(sympy_set, sympy.Interval): left, right = f(sympy_set.left), f(sympy_set.right) if left < right: new_left_open = sympy_set.left_open new_right_open = sympy_set.right_open else: new_left_open = sympy_set.right_open new_right_open = sympy_set.left_open return sympy.Interval(sympy.Min(left, right), sympy.Max(left, right), new_left_open, new_right_open) if isinstance(sympy_set, sympy.FiniteSet): return sympy.FiniteSet(list(map(f, sympy_set)))
def conditional_integral(expr, domain): ''' Return two points within the domain (excluding the end-points) on which to perform a conditional integral from one side of the domain. ''' modified_domain = sympy.Interval(domain.left, domain.right, True, True) return _delegate(expr, modified_domain, num=2)
def solution_statement(self): lines = solutions.Lines() X = sympy.Symbol('X') lines += r'Let $X = {exp_of_x}$'.format( exp_of_x=sympy.latex(sympy.exp(x)) ) hidden_quadratic = self._qp['equation'].replace(sympy.exp(x), X). replace(sympy.exp(2 * x), X ** 2) lines += r'$\therefore {equation} = {hidden_quadratic}$'.format( equation=sympy.latex(self._qp['equation']), hidden_quadratic=sympy.latex(hidden_quadratic) ) lines += r'$= {factorised_hidden_quadratic}$'.format( factorised_hidden_quadratic=sympy.latex(hidden_quadratic.factor()) ) lines += expressions.shrink_solution_set(expr=hidden_quadratic, domain=sympy.Interval(0, sympy.oo), var=X) valid_solution = [i for i in sympy.solve(hidden_quadratic) if i > 0][0] lines += r'${exp_of_x} = {valid_solution}$'.format( exp_of_x=sympy.latex(sympy.exp(x)), valid_solution=valid_solution ) answer = sympy.log(valid_solution) lines += r'$x = {answer}$'.format( answer=sympy.latex(answer) ) return lines.write()
def str2interval(s, local_dict={}): """ Convert a latex string into an interval. """ s = s.strip() s = s.replace("\emptyset", "EmptySet()") s = s.replace("\R", "S.Reals") s = s.replace("\infty", "oo") pattern = re.compile(r'\\{(.*)\\}') if pattern.search(s) is not None: return sp.FiniteSet(str2expr(pattern.search(s).group(1))) pattern = re.compile(r'\\lbrack(.*),(.*)\\rbrack') if pattern.search(s) is not None: return sp.Interval(str2expr(pattern.search(s).group(1)), str2expr(pattern.search(s).group(2))) pattern = re.compile(r'\\lbrack(.*),(.*)\\lbrack') if pattern.search(s) is not None: return sp.Interval.Ropen(str2expr(pattern.search(s).group(1)), str2expr(pattern.search(s).group(2))) pattern = re.compile(r'\\rbrack(.*),(.*)\\rbrack') if pattern.search(s) is not None: return sp.Interval.Lopen(str2expr(pattern.search(s).group(1)), str2expr(pattern.search(s).group(2))) pattern = re.compile(r'\\rbrack(.*),(.*)\\lbrack') if pattern.search(s) is not None: return sp.Interval.open(str2expr(pattern.search(s).group(1)), str2expr(pattern.search(s).group(2)))
def __init__(self): self.num_lines = 7 self.num_marks = 3 self._qp = {} function = all_functions.request_linear(difficulty=3).equation self._qp['equation'] = 1 / function # we can't integrate over a range of a hyperbola that has the vertical asymptote in the middle # we will only integrate on one side of the hyperbola vertical_asymptote = sympy.solve(function)[0] if random.randint(0, 1): # use the side to the left of the asymptote bound = vertical_asymptote.p // vertical_asymptote.q possible_x_values = list(range(bound - 5, bound)) else: bound = vertical_asymptote.p // vertical_asymptote.q + 1 possible_x_values = list(range(bound, bound + 5)) boundary = all_functions.choose_bounds(possible_x_values) self._qp['boundary'] = sympy.Interval(*boundary) integral_result = not_named_yet.soft_logcombine( self._qp['equation'].integrate( (x, self._qp['boundary'].left, self._qp['boundary'].right))) self._qp['answer'] = integral_result.match(sympy.log(x0) / x1)[x0] p = sympy.Symbol('p') self._qp['variable_expression'] = integral_result.replace( sympy.log(x0), sympy.log(p))
def piecewise_one(self, expr): if self.hs._dimension is None: to_val = sympy.oo else: to_val = self.hs.dimension return Piecewise( (1, sympy.Interval(0, to_val).as_relational(expr)), (0, True) )
def round_interval(interval): if interval.is_empty: return interval left = sp.floor(interval.left) if interval.left > 0 else sp.ceiling(interval.left) right = sp.floor(interval.right) if interval.right > 0 else sp.ceiling(interval.right) left_open = not interval.contains(left) right_open = not interval.contains(right) return sp.Interval(left, right, left_open=left_open, right_open=right_open)
def __init__(self, part): self.num_lines, self.num_marks = 6, 2 self._qp = copy.deepcopy(part._qp) self._qi = {} self._qi['unknown_variable'] = a self._qp['point'] = not_named_yet.randint(self._qp['mean'] - 10, self._qp['mean'] + 10, exclude=[self._qp['mean']]) self._qp['symmetrically_opposite_point'] = 2 * self._qp[ 'mean'] - self._qp['point'] # there are 4 connected intervals: # where "2*mean - point" is the symmetric opposite of "point" in terms of the mean # (-sympy.oo, point) pr = q # (2*mean - point, sympy.oo) pr = q # (mean, point) pr = 0.5 - q # (2*mean - point, mean) pr = 0.5 - q if random.choice([True, False ]): # we do not have infinity as one of the bounds self._qp[ 'event_provided_to_student'] = SimpleNormalDistribution.construct_interval( self._qp['mean'], self._qp['point']) if self._qp['point'] > self._qp['mean']: self._qp['desired_event'] = sympy.Interval( -sympy.oo, self._qp['symmetrically_opposite_point']) else: self._qp['desired_event'] = sympy.Interval( self._qp['symmetrically_opposite_point'], sympy.oo) self._qp['answer'] = sympy.Rational( 1, 2) - self._qi['unknown_variable'] else: # we do have infinity as one of the bounds self._qp[ 'desired_event'] = SimpleNormalDistribution.construct_interval( self._qp['symmetrically_opposite_point'], self._qp['mean']) if self._qp['point'] > self._qp['mean']: self._qp['event_provided_to_student'] = sympy.Interval( -sympy.oo, self._qp['point']) else: self._qp['event_provided_to_student'] = sympy.Interval( self._qp['point'], sympy.oo) self._qp['answer'] = -sympy.Rational( 1, 2) + self._qi['unknown_variable']
def test_sets(): x = Integer(2) y = Integer(3) x1 = sympy.Integer(2) y1 = sympy.Integer(3) assert Interval(x, y) == Interval(x1, y1) assert Interval(x1, y) == Interval(x1, y1) assert Interval(x, y)._sympy_() == sympy.Interval(x1, y1) assert sympify(sympy.Interval(x1, y1)) == Interval(x, y) assert sympify(sympy.S.EmptySet) == EmptySet() assert sympy.S.EmptySet == EmptySet()._sympy_() assert sympify(sympy.S.UniversalSet) == UniversalSet() assert sympy.S.UniversalSet == UniversalSet()._sympy_() assert sympify(sympy.S.Reals) == Reals() assert sympy.S.Reals == Reals()._sympy_() assert sympify(sympy.S.Rationals) == Rationals() assert sympy.S.Rationals == Rationals()._sympy_() assert sympify(sympy.S.Integers) == Integers() assert sympy.S.Integers == Integers()._sympy_() assert FiniteSet(x, y) == FiniteSet(x1, y1) assert FiniteSet(x1, y) == FiniteSet(x1, y1) assert FiniteSet(x, y)._sympy_() == sympy.FiniteSet(x1, y1) assert sympify(sympy.FiniteSet(x1, y1)) == FiniteSet(x, y) x = Interval(1, 2) y = Interval(2, 3) x1 = sympy.Interval(1, 2) y1 = sympy.Interval(2, 3) assert Union(x, y) == Union(x1, y1) assert Union(x1, y) == Union(x1, y1) assert Union(x, y)._sympy_() == sympy.Union(x1, y1) assert sympify(sympy.Union(x1, y1)) == Union(x, y) assert Complement(x, y) == Complement(x1, y1) assert Complement(x1, y) == Complement(x1, y1) assert Complement(x, y)._sympy_() == sympy.Complement(x1, y1) assert sympify(sympy.Complement(x1, y1)) == Complement(x, y)
def maximal_domain(expr, domain=sympy.Interval(-oo, oo)): ''' Return the maximal domain of an expression. >>> maximal_domain(sympy.log(x**2 - 1)) (-oo, -1) U (1, oo) >>> maximal_domain(1 / (x**2 - 4)) (-oo, -2) U (-2, 2) U (2, oo) >>> maximal_domain((x - 2) ** (sympy.Rational(3, 2))) (2, oo) ''' # 4 possible scenarios: # 1. 1/(a) -- a != 0 # 2. sqrt(b) -- b > 0 # 3. log(c) -- c > 0 # 4. tan(d) -- d != the solutions of tan for symbol in expr.free_symbols: if symbol == x: expr = expr.replace(x, sympy.Symbol('x', real=True)) else: raise NotImplementedError('only x is currently supported - but that can be easily changed') powers = expr.find(sympy.Pow) # case 1 for power in powers: if power.args[1] < 0: denominator = power.args[0] solution = sympy.solve(denominator) domain &= -sympy.FiniteSet(solution) # case 2 if isinstance(power.args[1], sympy.Rational): if power.args[1].q % 2 != 0: continue sqrt_interior = power.args[0] solution = sympy.solve(sqrt_interior > 0) domain &= relation_to_interval(solution) # case 3 logs = expr.find(sympy.log) for log in logs: interior = log.args[0] solution = sympy.solve(interior > 0) domain &= relation_to_interval(solution) # case 4 if expr.find(sympy.tan) or expr.find(sympy.cot) or expr.find(sympy.sec) or expr.find(sympy.csc): raise NotImplementedError('tan/cot/sec/csc are not supported') return domain
def __init__(self, *args): if len(args) == 1 and isinstance(args[0], PhaseRange): self.range = copy.deepcopy(args[0].range) return if len(args) == 1 and np.alltrue(len(i) == 2 for i in args): args = args[0] if len(args) == 2 and \ isinstance(args[0],numbers.Real) and \ isinstance(args[1],numbers.Real): args = [list(args)] ranges = [] for range in args: if range[0] not in PhaseRange.allowed_phase_input or \ range[1] not in PhaseRange.allowed_phase_input: raise Exception( "Error, phase range %s is outside allowed range." % str(range)) if np.allclose(range[0]-range[1],1) or \ np.allclose(range[1]-range[0],1): range = [0, 1] else: for i in [0, 1]: if range[i] != 1: range[i] %= 1 if range[0] > range[1]: # worry about wraping phase ranges, for example [0.6, 0.2] -> [0,0.2]U[0.6,1] if range[1] == 0: ranges.append(sympy.Interval(range[0], 1)) else: ranges += [ sympy.Interval(0, range[1]), sympy.Interval(range[0], 1) ] else: ranges.append(sympy.Interval(*range)) self.range = sympy.Union(*ranges)
def is_reasonable_tangent(tangent): """Check if the tangent has student-friendly coefficients. """ gradient = tangent.coeff(x, 1) if not isinstance(gradient, sympy.Integer): return False elif gradient not in sympy.Interval(-5, 5): return False elif gradient == 0: return False y_intercept = tangent.coeff(x, 0) if not isinstance(y_intercept, sympy.Integer): return False elif y_intercept not in sympy.Interval(-10, 10): return False return True
def solution_statement(self): inverse = all_functions.inverse(self._qp['equation']) maximal_domain_original = functions.maximal_domain(self._qp['equation']) maximal_domain_inverse = functions.maximal_domain(inverse) maximal_domain = maximal_domain_original & maximal_domain_inverse expr_domain = maximal_domain & sympy.Interval(-self._qp['MAX_PLOT_RANGE'], self._qp['MAX_PLOT_RANGE']) # an inverse of an inverse is always just "y = x" path = plot.plot(x, plot_domain=sympy.Interval(-self._qp['MAX_PLOT_RANGE'], self._qp['MAX_PLOT_RANGE']), plot_range=sympy.Interval(-self._qp['MAX_PLOT_RANGE'], self._qp['MAX_PLOT_RANGE']), expr_domain=expr_domain ) return r'''{0}'''.format(plot.latex(path))