def test_diopcoverage(): eq = (2 * x + y + 1)**2 assert diop_solve(eq) == set([(t_0, -2 * t_0 - 1)]) eq = 2 * x**2 + 6 * x * y + 12 * x + 4 * y**2 + 18 * y + 18 assert diop_solve(eq) == set([(t_0, -t_0 - 3), (2 * t_0 - 3, -t_0)]) assert diop_quadratic(x + y**2 - 3) == set([(-t**2 + 3, -t)]) assert diop_linear(x + y - 3) == (t_0, 3 - t_0) assert base_solution_linear(0, 1, 2, t=None) == (0, 0) ans = (3 * t - 1, -2 * t + 1) assert base_solution_linear(4, 8, 12, t) == ans assert base_solution_linear(4, 8, 12, t=None) == tuple(_.subs(t, 0) for _ in ans) assert cornacchia(1, 1, 20) is None assert cornacchia(1, 1, 5) == set([(2, 1)]) assert cornacchia(1, 2, 17) == set([(3, 2)]) raises(ValueError, lambda: reconstruct(4, 20, 1)) assert gaussian_reduce(4, 1, 3) == (1, 1) eq = -w**2 - x**2 - y**2 + z**2 assert diop_general_pythagorean(eq) == \ diop_general_pythagorean(-eq) == \ (m1**2 + m2**2 - m3**2, 2*m1*m3, 2*m2*m3, m1**2 + m2**2 + m3**2) assert check_param(S(3) + x / 3, S(4) + x / 2, S(2), x) == (None, None) assert check_param(S(3) / 2, S(4) + x, S(2), x) == (None, None) assert check_param(S(4) + x, S(3) / 2, S(2), x) == (None, None) assert _nint_or_floor(16, 10) == 2 assert _odd(1) == (not _even(1)) == True assert _odd(0) == (not _even(0)) == False assert _remove_gcd(2, 4, 6) == (1, 2, 3) raises(TypeError, lambda: _remove_gcd((2, 4, 6))) assert sqf_normal(2 * 3**2 * 5, 2 * 5 * 11, 2 * 7**2 * 11) == \ (11, 1, 5) # it's ok if these pass some day when the solvers are implemented raises(NotImplementedError, lambda: diophantine(x**2 + y**2 + x * y + 2 * y * z - 12)) raises(NotImplementedError, lambda: diophantine(x**3 + y**2)) assert diop_quadratic(x**2 + y**2 - 1**2 - 3**4) == \ set([(-9, -1), (-9, 1), (-1, -9), (-1, 9), (1, -9), (1, 9), (9, -1), (9, 1)])
def test_diopcoverage(): eq = (2*x + y + 1)**2 assert diop_solve(eq) == set([(t_0, -2*t_0 - 1)]) eq = 2*x**2 + 6*x*y + 12*x + 4*y**2 + 18*y + 18 assert diop_solve(eq) == set([(t_0, -t_0 - 3), (2*t_0 - 3, -t_0)]) assert diop_quadratic(x + y**2 - 3) == set([(-t**2 + 3, -t)]) assert diop_linear(x + y - 3) == (t_0, 3 - t_0) assert base_solution_linear(0, 1, 2, t=None) == (0, 0) ans = (3*t - 1, -2*t + 1) assert base_solution_linear(4, 8, 12, t) == ans assert base_solution_linear(4, 8, 12, t=None) == tuple(_.subs(t, 0) for _ in ans) assert cornacchia(1, 1, 20) is None assert cornacchia(1, 1, 5) == set([(2, 1)]) assert cornacchia(1, 2, 17) == set([(3, 2)]) raises(ValueError, lambda: reconstruct(4, 20, 1)) assert gaussian_reduce(4, 1, 3) == (1, 1) eq = -w**2 - x**2 - y**2 + z**2 assert diop_general_pythagorean(eq) == \ diop_general_pythagorean(-eq) == \ (m1**2 + m2**2 - m3**2, 2*m1*m3, 2*m2*m3, m1**2 + m2**2 + m3**2) assert check_param(S(3) + x/3, S(4) + x/2, S(2), x) == (None, None) assert check_param(S(3)/2, S(4) + x, S(2), x) == (None, None) assert check_param(S(4) + x, S(3)/2, S(2), x) == (None, None) assert _nint_or_floor(16, 10) == 2 assert _odd(1) == (not _even(1)) == True assert _odd(0) == (not _even(0)) == False assert _remove_gcd(2, 4, 6) == (1, 2, 3) raises(TypeError, lambda: _remove_gcd((2, 4, 6))) assert sqf_normal(2 * 3**2 * 5, 2 * 5 * 11, 2 * 7**2 * 11) == \ (11, 1, 5) # it's ok if these pass some day when the solvers are implemented raises(NotImplementedError, lambda: diophantine(x**2 + y**2 + x*y + 2*y*z - 12)) raises(NotImplementedError, lambda: diophantine(x**3 + y**2)) assert diop_quadratic(x**2 + y**2 - 1**2 - 3**4) == \ set([(-9, -1), (-9, 1), (-1, -9), (-1, 9), (1, -9), (1, 9), (9, -1), (9, 1)])
def intersection_sets(a, b): from sympy.solvers.diophantine import diop_linear from sympy.core.numbers import ilcm from sympy import sign # non-overlap quick exits if not b: return S.EmptySet if not a: return S.EmptySet if b.sup < a.inf: return S.EmptySet if b.inf > a.sup: return S.EmptySet # work with finite end at the start r1 = a if r1.start.is_infinite: r1 = r1.reversed r2 = b if r2.start.is_infinite: r2 = r2.reversed # If both ends are infinite then it means that one Range is just the set # of all integers (the step must be 1). if r1.start.is_infinite: return b if r2.start.is_infinite: return a # this equation represents the values of the Range; # it's a linear equation eq = lambda r, i: r.start + i * r.step # we want to know when the two equations might # have integer solutions so we use the diophantine # solver va, vb = diop_linear(eq(r1, Dummy('a')) - eq(r2, Dummy('b'))) # check for no solution no_solution = va is None and vb is None if no_solution: return S.EmptySet # there is a solution # ------------------- # find the coincident point, c a0 = va.as_coeff_Add()[0] c = eq(r1, a0) # find the first point, if possible, in each range # since c may not be that point def _first_finite_point(r1, c): if c == r1.start: return c # st is the signed step we need to take to # get from c to r1.start st = sign(r1.start - c) * step # use Range to calculate the first point: # we want to get as close as possible to # r1.start; the Range will not be null since # it will at least contain c s1 = Range(c, r1.start + st, st)[-1] if s1 == r1.start: pass else: # if we didn't hit r1.start then, if the # sign of st didn't match the sign of r1.step # we are off by one and s1 is not in r1 if sign(r1.step) != sign(st): s1 -= st if s1 not in r1: return return s1 # calculate the step size of the new Range step = abs(ilcm(r1.step, r2.step)) s1 = _first_finite_point(r1, c) if s1 is None: return S.EmptySet s2 = _first_finite_point(r2, c) if s2 is None: return S.EmptySet # replace the corresponding start or stop in # the original Ranges with these points; the # result must have at least one point since # we know that s1 and s2 are in the Ranges def _updated_range(r, first): st = sign(r.step) * step if r.start.is_finite: rv = Range(first, r.stop, st) else: rv = Range(r.start, first + st, st) return rv r1 = _updated_range(a, s1) r2 = _updated_range(b, s2) # work with them both in the increasing direction if sign(r1.step) < 0: r1 = r1.reversed if sign(r2.step) < 0: r2 = r2.reversed # return clipped Range with positive step; it # can't be empty at this point start = max(r1.start, r2.start) stop = min(r1.stop, r2.stop) return Range(start, stop, step)
def _intersect(self, other): from sympy.functions.elementary.integers import ceiling, floor from sympy.functions.elementary.complexes import sign if other is S.Naturals: return self._intersect(Interval(1, S.Infinity)) if other is S.Integers: return self if other.is_Interval: if not all(i.is_number for i in other.args[:2]): return # In case of null Range, return an EmptySet. if self.size == 0: return S.EmptySet # trim down to self's size, and represent # as a Range with step 1. start = ceiling(max(other.inf, self.inf)) if start not in other: start += 1 end = floor(min(other.sup, self.sup)) if end not in other: end -= 1 return self.intersect(Range(start, end + 1)) if isinstance(other, Range): from sympy.solvers.diophantine import diop_linear from sympy.core.numbers import ilcm # non-overlap quick exits if not other: return S.EmptySet if not self: return S.EmptySet if other.sup < self.inf: return S.EmptySet if other.inf > self.sup: return S.EmptySet # work with finite end at the start r1 = self if r1.start.is_infinite: r1 = r1.reversed r2 = other if r2.start.is_infinite: r2 = r2.reversed # this equation represents the values of the Range; # it's a linear equation eq = lambda r, i: r.start + i * r.step # we want to know when the two equations might # have integer solutions so we use the diophantine # solver a, b = diop_linear(eq(r1, Dummy()) - eq(r2, Dummy())) # check for no solution no_solution = a is None and b is None if no_solution: return S.EmptySet # there is a solution # ------------------- # find the coincident point, c a0 = a.as_coeff_Add()[0] c = eq(r1, a0) # find the first point, if possible, in each range # since c may not be that point def _first_finite_point(r1, c): if c == r1.start: return c # st is the signed step we need to take to # get from c to r1.start st = sign(r1.start - c) * step # use Range to calculate the first point: # we want to get as close as possible to # r1.start; the Range will not be null since # it will at least contain c s1 = Range(c, r1.start + st, st)[-1] if s1 == r1.start: pass else: # if we didn't hit r1.start then, if the # sign of st didn't match the sign of r1.step # we are off by one and s1 is not in r1 if sign(r1.step) != sign(st): s1 -= st if s1 not in r1: return return s1 # calculate the step size of the new Range step = abs(ilcm(r1.step, r2.step)) s1 = _first_finite_point(r1, c) if s1 is None: return S.EmptySet s2 = _first_finite_point(r2, c) if s2 is None: return S.EmptySet # replace the corresponding start or stop in # the original Ranges with these points; the # result must have at least one point since # we know that s1 and s2 are in the Ranges def _updated_range(r, first): st = sign(r.step) * step if r.start.is_finite: rv = Range(first, r.stop, st) else: rv = Range(r.start, first + st, st) return rv r1 = _updated_range(self, s1) r2 = _updated_range(other, s2) # work with them both in the increasing direction if sign(r1.step) < 0: r1 = r1.reversed if sign(r2.step) < 0: r2 = r2.reversed # return clipped Range with positive step; it # can't be empty at this point start = max(r1.start, r2.start) stop = min(r1.stop, r2.stop) return Range(start, stop, step) else: return
def convert_eq(U: Set[Equation], func: str): var_count=dict() first=True for e in U: LS=get_vars(e.left_side) RS=get_vars(e.right_side) for x in list(LS): num = LS.count(x) - RS.count(x) if x in var_count: if first: var_count[x] = var_count[x] + num else: var_count[x] = var_count[x] - num else: if first: var_count[x] = num else: var_count[x] = -num LS[:] = [y for y in LS if y != x] RS[:] = [y for y in RS if y != x] if len(RS) != 0: for x in RS: var_count[x] = -RS.count(x) RS[:] = [y for y in RS if y != x] first=False #convert to an equation i=0 e = "" variables = list() row = list() for x in var_count: temp = str(x) i += 1 e = e + str(var_count[x]) +"*"+ temp + (" + " if i < len(var_count) else "") temp = symbols(temp, integer=True, positive=True) variables.append(temp) row.append(var_count[x]) e = parse_expr(e) #This will give solutions, but not limited to positive, so ACU sol = diop_linear(e) F = deepcopy(func) j = 0 delta = SubstituteTerm() zeros = set() for term in sol: regex = r'-[\d]*[\*]*[-]*(t_[\d]+)' match = re.findall(regex, str(term)) for m in match: zeros.add(m) sol2 = list() for term in sol: for z in zeros: term = re.sub(z, '0', str(term)) sol2.append(term) for x in range(0, len(variables)): if row[x] == 0: temp = Variable(str(variables[x])) delta.add(temp, temp) else: var_list = list() num = '0' if '*' in str(sol2[j]): num, var = str(sol2[j]).split("*", 1) else: var = str(sol2[j]) var = Variable(var) try: num = int(num) except: num = parse_expr(num) func = Function(func, 2) ran = str() if num > 0: for y in range(0, num): if y == 0: ran = ran if y >= 1 and y <= num-2: ran = ran + F + '(' + str(var) + ',' if y == num-1: ran = ran + str(var) if y == num: num = num for y in range(2, num): ran = ran + ')' else: ran = var y = Variable(str(sol2[j])) if num > 0: T = FuncTerm(Function(str(func.symbol), 2), [str(var),ran]) else: T = var z= Variable(str(variables[x])) delta.add(z, T) j+= 1 return delta
def _intersect(self, other): from sympy.functions.elementary.integers import ceiling, floor from sympy.functions.elementary.complexes import sign if other is S.Naturals: return self._intersect(Interval(1, S.Infinity)) if other is S.Integers: return self if other.is_Interval: if not all(i.is_number for i in other.args[:2]): return # In case of null Range, return an EmptySet. if self.size == 0: return S.EmptySet # trim down to self's size, and represent # as a Range with step 1. start = ceiling(max(other.inf, self.inf)) if start not in other: start += 1 end = floor(min(other.sup, self.sup)) if end not in other: end -= 1 return self.intersect(Range(start, end + 1)) if isinstance(other, Range): from sympy.solvers.diophantine import diop_linear from sympy.core.numbers import ilcm # non-overlap quick exits if not other: return S.EmptySet if not self: return S.EmptySet if other.sup < self.inf: return S.EmptySet if other.inf > self.sup: return S.EmptySet # work with finite end at the start r1 = self if r1.start.is_infinite: r1 = r1.reversed r2 = other if r2.start.is_infinite: r2 = r2.reversed # this equation represents the values of the Range; # it's a linear equation eq = lambda r, i: r.start + i*r.step # we want to know when the two equations might # have integer solutions so we use the diophantine # solver a, b = diop_linear(eq(r1, Dummy()) - eq(r2, Dummy())) # check for no solution no_solution = a is None and b is None if no_solution: return S.EmptySet # there is a solution # ------------------- # find the coincident point, c a0 = a.as_coeff_Add()[0] c = eq(r1, a0) # find the first point, if possible, in each range # since c may not be that point def _first_finite_point(r1, c): if c == r1.start: return c # st is the signed step we need to take to # get from c to r1.start st = sign(r1.start - c)*step # use Range to calculate the first point: # we want to get as close as possible to # r1.start; the Range will not be null since # it will at least contain c s1 = Range(c, r1.start + st, st)[-1] if s1 == r1.start: pass else: # if we didn't hit r1.start then, if the # sign of st didn't match the sign of r1.step # we are off by one and s1 is not in r1 if sign(r1.step) != sign(st): s1 -= st if s1 not in r1: return return s1 # calculate the step size of the new Range step = abs(ilcm(r1.step, r2.step)) s1 = _first_finite_point(r1, c) if s1 is None: return S.EmptySet s2 = _first_finite_point(r2, c) if s2 is None: return S.EmptySet # replace the corresponding start or stop in # the original Ranges with these points; the # result must have at least one point since # we know that s1 and s2 are in the Ranges def _updated_range(r, first): st = sign(r.step)*step if r.start.is_finite: rv = Range(first, r.stop, st) else: rv = Range(r.start, first + st, st) return rv r1 = _updated_range(self, s1) r2 = _updated_range(other, s2) # work with them both in the increasing direction if sign(r1.step) < 0: r1 = r1.reversed if sign(r2.step) < 0: r2 = r2.reversed # return clipped Range with positive step; it # can't be empty at this point start = max(r1.start, r2.start) stop = min(r1.stop, r2.stop) return Range(start, stop, step) else: return
def intersection_sets(a, b): from sympy.solvers.diophantine import diop_linear from sympy.core.numbers import ilcm from sympy import sign # non-overlap quick exits if not b: return S.EmptySet if not a: return S.EmptySet if b.sup < a.inf: return S.EmptySet if b.inf > a.sup: return S.EmptySet # work with finite end at the start r1 = a if r1.start.is_infinite: r1 = r1.reversed r2 = b if r2.start.is_infinite: r2 = r2.reversed # this equation represents the values of the Range; # it's a linear equation eq = lambda r, i: r.start + i*r.step # we want to know when the two equations might # have integer solutions so we use the diophantine # solver va, vb = diop_linear(eq(r1, Dummy()) - eq(r2, Dummy())) # check for no solution no_solution = va is None and vb is None if no_solution: return S.EmptySet # there is a solution # ------------------- # find the coincident point, c a0 = va.as_coeff_Add()[0] c = eq(r1, a0) # find the first point, if possible, in each range # since c may not be that point def _first_finite_point(r1, c): if c == r1.start: return c # st is the signed step we need to take to # get from c to r1.start st = sign(r1.start - c)*step # use Range to calculate the first point: # we want to get as close as possible to # r1.start; the Range will not be null since # it will at least contain c s1 = Range(c, r1.start + st, st)[-1] if s1 == r1.start: pass else: # if we didn't hit r1.start then, if the # sign of st didn't match the sign of r1.step # we are off by one and s1 is not in r1 if sign(r1.step) != sign(st): s1 -= st if s1 not in r1: return return s1 # calculate the step size of the new Range step = abs(ilcm(r1.step, r2.step)) s1 = _first_finite_point(r1, c) if s1 is None: return S.EmptySet s2 = _first_finite_point(r2, c) if s2 is None: return S.EmptySet # replace the corresponding start or stop in # the original Ranges with these points; the # result must have at least one point since # we know that s1 and s2 are in the Ranges def _updated_range(r, first): st = sign(r.step)*step if r.start.is_finite: rv = Range(first, r.stop, st) else: rv = Range(r.start, first + st, st) return rv r1 = _updated_range(a, s1) r2 = _updated_range(b, s2) # work with them both in the increasing direction if sign(r1.step) < 0: r1 = r1.reversed if sign(r2.step) < 0: r2 = r2.reversed # return clipped Range with positive step; it # can't be empty at this point start = max(r1.start, r2.start) stop = min(r1.stop, r2.stop) return Range(start, stop, step)