Coverage for /usr/lib/python3/dist-packages/sympy/sets/fancysets.py: 22%

704 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-14 15:55 +0200

1from functools import reduce 

2from itertools import product 

3 

4from sympy.core.basic import Basic 

5from sympy.core.containers import Tuple 

6from sympy.core.expr import Expr 

7from sympy.core.function import Lambda 

8from sympy.core.logic import fuzzy_not, fuzzy_or, fuzzy_and 

9from sympy.core.mod import Mod 

10from sympy.core.numbers import oo, igcd, Rational 

11from sympy.core.relational import Eq, is_eq 

12from sympy.core.kind import NumberKind 

13from sympy.core.singleton import Singleton, S 

14from sympy.core.symbol import Dummy, symbols, Symbol 

15from sympy.core.sympify import _sympify, sympify, _sympy_converter 

16from sympy.functions.elementary.integers import ceiling, floor 

17from sympy.functions.elementary.trigonometric import sin, cos 

18from sympy.logic.boolalg import And, Or 

19from .sets import Set, Interval, Union, FiniteSet, ProductSet, SetKind 

20from sympy.utilities.misc import filldedent 

21 

22 

23class Rationals(Set, metaclass=Singleton): 

24 """ 

25 Represents the rational numbers. This set is also available as 

26 the singleton ``S.Rationals``. 

27 

28 Examples 

29 ======== 

30 

31 >>> from sympy import S 

32 >>> S.Half in S.Rationals 

33 True 

34 >>> iterable = iter(S.Rationals) 

35 >>> [next(iterable) for i in range(12)] 

36 [0, 1, -1, 1/2, 2, -1/2, -2, 1/3, 3, -1/3, -3, 2/3] 

37 """ 

38 

39 is_iterable = True 

40 _inf = S.NegativeInfinity 

41 _sup = S.Infinity 

42 is_empty = False 

43 is_finite_set = False 

44 

45 def _contains(self, other): 

46 if not isinstance(other, Expr): 

47 return False 

48 return other.is_rational 

49 

50 def __iter__(self): 

51 yield S.Zero 

52 yield S.One 

53 yield S.NegativeOne 

54 d = 2 

55 while True: 

56 for n in range(d): 

57 if igcd(n, d) == 1: 

58 yield Rational(n, d) 

59 yield Rational(d, n) 

60 yield Rational(-n, d) 

61 yield Rational(-d, n) 

62 d += 1 

63 

64 @property 

65 def _boundary(self): 

66 return S.Reals 

67 

68 def _kind(self): 

69 return SetKind(NumberKind) 

70 

71 

72class Naturals(Set, metaclass=Singleton): 

73 """ 

74 Represents the natural numbers (or counting numbers) which are all 

75 positive integers starting from 1. This set is also available as 

76 the singleton ``S.Naturals``. 

77 

78 Examples 

79 ======== 

80 

81 >>> from sympy import S, Interval, pprint 

82 >>> 5 in S.Naturals 

83 True 

84 >>> iterable = iter(S.Naturals) 

85 >>> next(iterable) 

86 1 

87 >>> next(iterable) 

88 2 

89 >>> next(iterable) 

90 3 

91 >>> pprint(S.Naturals.intersect(Interval(0, 10))) 

92 {1, 2, ..., 10} 

93 

94 See Also 

95 ======== 

96 

97 Naturals0 : non-negative integers (i.e. includes 0, too) 

98 Integers : also includes negative integers 

99 """ 

100 

101 is_iterable = True 

102 _inf = S.One 

103 _sup = S.Infinity 

104 is_empty = False 

105 is_finite_set = False 

106 

107 def _contains(self, other): 

108 if not isinstance(other, Expr): 

109 return False 

110 elif other.is_positive and other.is_integer: 

111 return True 

112 elif other.is_integer is False or other.is_positive is False: 

113 return False 

114 

115 def _eval_is_subset(self, other): 

116 return Range(1, oo).is_subset(other) 

117 

118 def _eval_is_superset(self, other): 

119 return Range(1, oo).is_superset(other) 

120 

121 def __iter__(self): 

122 i = self._inf 

123 while True: 

124 yield i 

125 i = i + 1 

126 

127 @property 

128 def _boundary(self): 

129 return self 

130 

131 def as_relational(self, x): 

132 return And(Eq(floor(x), x), x >= self.inf, x < oo) 

133 

134 def _kind(self): 

135 return SetKind(NumberKind) 

136 

137 

138class Naturals0(Naturals): 

139 """Represents the whole numbers which are all the non-negative integers, 

140 inclusive of zero. 

141 

142 See Also 

143 ======== 

144 

145 Naturals : positive integers; does not include 0 

146 Integers : also includes the negative integers 

147 """ 

148 _inf = S.Zero 

149 

150 def _contains(self, other): 

151 if not isinstance(other, Expr): 

152 return S.false 

153 elif other.is_integer and other.is_nonnegative: 

154 return S.true 

155 elif other.is_integer is False or other.is_nonnegative is False: 

156 return S.false 

157 

158 def _eval_is_subset(self, other): 

159 return Range(oo).is_subset(other) 

160 

161 def _eval_is_superset(self, other): 

162 return Range(oo).is_superset(other) 

163 

164 

165class Integers(Set, metaclass=Singleton): 

166 """ 

167 Represents all integers: positive, negative and zero. This set is also 

168 available as the singleton ``S.Integers``. 

169 

170 Examples 

171 ======== 

172 

173 >>> from sympy import S, Interval, pprint 

174 >>> 5 in S.Naturals 

175 True 

176 >>> iterable = iter(S.Integers) 

177 >>> next(iterable) 

178 0 

179 >>> next(iterable) 

180 1 

181 >>> next(iterable) 

182 -1 

183 >>> next(iterable) 

184 2 

185 

186 >>> pprint(S.Integers.intersect(Interval(-4, 4))) 

187 {-4, -3, ..., 4} 

188 

189 See Also 

190 ======== 

191 

192 Naturals0 : non-negative integers 

193 Integers : positive and negative integers and zero 

194 """ 

195 

196 is_iterable = True 

197 is_empty = False 

198 is_finite_set = False 

199 

200 def _contains(self, other): 

201 if not isinstance(other, Expr): 

202 return S.false 

203 return other.is_integer 

204 

205 def __iter__(self): 

206 yield S.Zero 

207 i = S.One 

208 while True: 

209 yield i 

210 yield -i 

211 i = i + 1 

212 

213 @property 

214 def _inf(self): 

215 return S.NegativeInfinity 

216 

217 @property 

218 def _sup(self): 

219 return S.Infinity 

220 

221 @property 

222 def _boundary(self): 

223 return self 

224 

225 def _kind(self): 

226 return SetKind(NumberKind) 

227 

228 def as_relational(self, x): 

229 return And(Eq(floor(x), x), -oo < x, x < oo) 

230 

231 def _eval_is_subset(self, other): 

232 return Range(-oo, oo).is_subset(other) 

233 

234 def _eval_is_superset(self, other): 

235 return Range(-oo, oo).is_superset(other) 

236 

237 

238class Reals(Interval, metaclass=Singleton): 

239 """ 

240 Represents all real numbers 

241 from negative infinity to positive infinity, 

242 including all integer, rational and irrational numbers. 

243 This set is also available as the singleton ``S.Reals``. 

244 

245 

246 Examples 

247 ======== 

248 

249 >>> from sympy import S, Rational, pi, I 

250 >>> 5 in S.Reals 

251 True 

252 >>> Rational(-1, 2) in S.Reals 

253 True 

254 >>> pi in S.Reals 

255 True 

256 >>> 3*I in S.Reals 

257 False 

258 >>> S.Reals.contains(pi) 

259 True 

260 

261 

262 See Also 

263 ======== 

264 

265 ComplexRegion 

266 """ 

267 @property 

268 def start(self): 

269 return S.NegativeInfinity 

270 

271 @property 

272 def end(self): 

273 return S.Infinity 

274 

275 @property 

276 def left_open(self): 

277 return True 

278 

279 @property 

280 def right_open(self): 

281 return True 

282 

283 def __eq__(self, other): 

284 return other == Interval(S.NegativeInfinity, S.Infinity) 

285 

286 def __hash__(self): 

287 return hash(Interval(S.NegativeInfinity, S.Infinity)) 

288 

289 

290class ImageSet(Set): 

291 """ 

292 Image of a set under a mathematical function. The transformation 

293 must be given as a Lambda function which has as many arguments 

294 as the elements of the set upon which it operates, e.g. 1 argument 

295 when acting on the set of integers or 2 arguments when acting on 

296 a complex region. 

297 

298 This function is not normally called directly, but is called 

299 from ``imageset``. 

300 

301 

302 Examples 

303 ======== 

304 

305 >>> from sympy import Symbol, S, pi, Dummy, Lambda 

306 >>> from sympy import FiniteSet, ImageSet, Interval 

307 

308 >>> x = Symbol('x') 

309 >>> N = S.Naturals 

310 >>> squares = ImageSet(Lambda(x, x**2), N) # {x**2 for x in N} 

311 >>> 4 in squares 

312 True 

313 >>> 5 in squares 

314 False 

315 

316 >>> FiniteSet(0, 1, 2, 3, 4, 5, 6, 7, 9, 10).intersect(squares) 

317 {1, 4, 9} 

318 

319 >>> square_iterable = iter(squares) 

320 >>> for i in range(4): 

321 ... next(square_iterable) 

322 1 

323 4 

324 9 

325 16 

326 

327 If you want to get value for `x` = 2, 1/2 etc. (Please check whether the 

328 `x` value is in ``base_set`` or not before passing it as args) 

329 

330 >>> squares.lamda(2) 

331 4 

332 >>> squares.lamda(S(1)/2) 

333 1/4 

334 

335 >>> n = Dummy('n') 

336 >>> solutions = ImageSet(Lambda(n, n*pi), S.Integers) # solutions of sin(x) = 0 

337 >>> dom = Interval(-1, 1) 

338 >>> dom.intersect(solutions) 

339 {0} 

340 

341 See Also 

342 ======== 

343 

344 sympy.sets.sets.imageset 

345 """ 

346 def __new__(cls, flambda, *sets): 

347 if not isinstance(flambda, Lambda): 

348 raise ValueError('First argument must be a Lambda') 

349 

350 signature = flambda.signature 

351 

352 if len(signature) != len(sets): 

353 raise ValueError('Incompatible signature') 

354 

355 sets = [_sympify(s) for s in sets] 

356 

357 if not all(isinstance(s, Set) for s in sets): 

358 raise TypeError("Set arguments to ImageSet should of type Set") 

359 

360 if not all(cls._check_sig(sg, st) for sg, st in zip(signature, sets)): 

361 raise ValueError("Signature %s does not match sets %s" % (signature, sets)) 

362 

363 if flambda is S.IdentityFunction and len(sets) == 1: 

364 return sets[0] 

365 

366 if not set(flambda.variables) & flambda.expr.free_symbols: 

367 is_empty = fuzzy_or(s.is_empty for s in sets) 

368 if is_empty == True: 

369 return S.EmptySet 

370 elif is_empty == False: 

371 return FiniteSet(flambda.expr) 

372 

373 return Basic.__new__(cls, flambda, *sets) 

374 

375 lamda = property(lambda self: self.args[0]) 

376 base_sets = property(lambda self: self.args[1:]) 

377 

378 @property 

379 def base_set(self): 

380 # XXX: Maybe deprecate this? It is poorly defined in handling 

381 # the multivariate case... 

382 sets = self.base_sets 

383 if len(sets) == 1: 

384 return sets[0] 

385 else: 

386 return ProductSet(*sets).flatten() 

387 

388 @property 

389 def base_pset(self): 

390 return ProductSet(*self.base_sets) 

391 

392 @classmethod 

393 def _check_sig(cls, sig_i, set_i): 

394 if sig_i.is_symbol: 

395 return True 

396 elif isinstance(set_i, ProductSet): 

397 sets = set_i.sets 

398 if len(sig_i) != len(sets): 

399 return False 

400 # Recurse through the signature for nested tuples: 

401 return all(cls._check_sig(ts, ps) for ts, ps in zip(sig_i, sets)) 

402 else: 

403 # XXX: Need a better way of checking whether a set is a set of 

404 # Tuples or not. For example a FiniteSet can contain Tuples 

405 # but so can an ImageSet or a ConditionSet. Others like 

406 # Integers, Reals etc can not contain Tuples. We could just 

407 # list the possibilities here... Current code for e.g. 

408 # _contains probably only works for ProductSet. 

409 return True # Give the benefit of the doubt 

410 

411 def __iter__(self): 

412 already_seen = set() 

413 for i in self.base_pset: 

414 val = self.lamda(*i) 

415 if val in already_seen: 

416 continue 

417 else: 

418 already_seen.add(val) 

419 yield val 

420 

421 def _is_multivariate(self): 

422 return len(self.lamda.variables) > 1 

423 

424 def _contains(self, other): 

425 from sympy.solvers.solveset import _solveset_multi 

426 

427 def get_symsetmap(signature, base_sets): 

428 '''Attempt to get a map of symbols to base_sets''' 

429 queue = list(zip(signature, base_sets)) 

430 symsetmap = {} 

431 for sig, base_set in queue: 

432 if sig.is_symbol: 

433 symsetmap[sig] = base_set 

434 elif base_set.is_ProductSet: 

435 sets = base_set.sets 

436 if len(sig) != len(sets): 

437 raise ValueError("Incompatible signature") 

438 # Recurse 

439 queue.extend(zip(sig, sets)) 

440 else: 

441 # If we get here then we have something like sig = (x, y) and 

442 # base_set = {(1, 2), (3, 4)}. For now we give up. 

443 return None 

444 

445 return symsetmap 

446 

447 def get_equations(expr, candidate): 

448 '''Find the equations relating symbols in expr and candidate.''' 

449 queue = [(expr, candidate)] 

450 for e, c in queue: 

451 if not isinstance(e, Tuple): 

452 yield Eq(e, c) 

453 elif not isinstance(c, Tuple) or len(e) != len(c): 

454 yield False 

455 return 

456 else: 

457 queue.extend(zip(e, c)) 

458 

459 # Get the basic objects together: 

460 other = _sympify(other) 

461 expr = self.lamda.expr 

462 sig = self.lamda.signature 

463 variables = self.lamda.variables 

464 base_sets = self.base_sets 

465 

466 # Use dummy symbols for ImageSet parameters so they don't match 

467 # anything in other 

468 rep = {v: Dummy(v.name) for v in variables} 

469 variables = [v.subs(rep) for v in variables] 

470 sig = sig.subs(rep) 

471 expr = expr.subs(rep) 

472 

473 # Map the parts of other to those in the Lambda expr 

474 equations = [] 

475 for eq in get_equations(expr, other): 

476 # Unsatisfiable equation? 

477 if eq is False: 

478 return False 

479 equations.append(eq) 

480 

481 # Map the symbols in the signature to the corresponding domains 

482 symsetmap = get_symsetmap(sig, base_sets) 

483 if symsetmap is None: 

484 # Can't factor the base sets to a ProductSet 

485 return None 

486 

487 # Which of the variables in the Lambda signature need to be solved for? 

488 symss = (eq.free_symbols for eq in equations) 

489 variables = set(variables) & reduce(set.union, symss, set()) 

490 

491 # Use internal multivariate solveset 

492 variables = tuple(variables) 

493 base_sets = [symsetmap[v] for v in variables] 

494 solnset = _solveset_multi(equations, variables, base_sets) 

495 if solnset is None: 

496 return None 

497 return fuzzy_not(solnset.is_empty) 

498 

499 @property 

500 def is_iterable(self): 

501 return all(s.is_iterable for s in self.base_sets) 

502 

503 def doit(self, **hints): 

504 from sympy.sets.setexpr import SetExpr 

505 f = self.lamda 

506 sig = f.signature 

507 if len(sig) == 1 and sig[0].is_symbol and isinstance(f.expr, Expr): 

508 base_set = self.base_sets[0] 

509 return SetExpr(base_set)._eval_func(f).set 

510 if all(s.is_FiniteSet for s in self.base_sets): 

511 return FiniteSet(*(f(*a) for a in product(*self.base_sets))) 

512 return self 

513 

514 def _kind(self): 

515 return SetKind(self.lamda.expr.kind) 

516 

517 

518class Range(Set): 

519 """ 

520 Represents a range of integers. Can be called as ``Range(stop)``, 

521 ``Range(start, stop)``, or ``Range(start, stop, step)``; when ``step`` is 

522 not given it defaults to 1. 

523 

524 ``Range(stop)`` is the same as ``Range(0, stop, 1)`` and the stop value 

525 (just as for Python ranges) is not included in the Range values. 

526 

527 >>> from sympy import Range 

528 >>> list(Range(3)) 

529 [0, 1, 2] 

530 

531 The step can also be negative: 

532 

533 >>> list(Range(10, 0, -2)) 

534 [10, 8, 6, 4, 2] 

535 

536 The stop value is made canonical so equivalent ranges always 

537 have the same args: 

538 

539 >>> Range(0, 10, 3) 

540 Range(0, 12, 3) 

541 

542 Infinite ranges are allowed. ``oo`` and ``-oo`` are never included in the 

543 set (``Range`` is always a subset of ``Integers``). If the starting point 

544 is infinite, then the final value is ``stop - step``. To iterate such a 

545 range, it needs to be reversed: 

546 

547 >>> from sympy import oo 

548 >>> r = Range(-oo, 1) 

549 >>> r[-1] 

550 0 

551 >>> next(iter(r)) 

552 Traceback (most recent call last): 

553 ... 

554 TypeError: Cannot iterate over Range with infinite start 

555 >>> next(iter(r.reversed)) 

556 0 

557 

558 Although ``Range`` is a :class:`Set` (and supports the normal set 

559 operations) it maintains the order of the elements and can 

560 be used in contexts where ``range`` would be used. 

561 

562 >>> from sympy import Interval 

563 >>> Range(0, 10, 2).intersect(Interval(3, 7)) 

564 Range(4, 8, 2) 

565 >>> list(_) 

566 [4, 6] 

567 

568 Although slicing of a Range will always return a Range -- possibly 

569 empty -- an empty set will be returned from any intersection that 

570 is empty: 

571 

572 >>> Range(3)[:0] 

573 Range(0, 0, 1) 

574 >>> Range(3).intersect(Interval(4, oo)) 

575 EmptySet 

576 >>> Range(3).intersect(Range(4, oo)) 

577 EmptySet 

578 

579 Range will accept symbolic arguments but has very limited support 

580 for doing anything other than displaying the Range: 

581 

582 >>> from sympy import Symbol, pprint 

583 >>> from sympy.abc import i, j, k 

584 >>> Range(i, j, k).start 

585 i 

586 >>> Range(i, j, k).inf 

587 Traceback (most recent call last): 

588 ... 

589 ValueError: invalid method for symbolic range 

590 

591 Better success will be had when using integer symbols: 

592 

593 >>> n = Symbol('n', integer=True) 

594 >>> r = Range(n, n + 20, 3) 

595 >>> r.inf 

596 n 

597 >>> pprint(r) 

598 {n, n + 3, ..., n + 18} 

599 """ 

600 

601 def __new__(cls, *args): 

602 if len(args) == 1: 

603 if isinstance(args[0], range): 

604 raise TypeError( 

605 'use sympify(%s) to convert range to Range' % args[0]) 

606 

607 # expand range 

608 slc = slice(*args) 

609 

610 if slc.step == 0: 

611 raise ValueError("step cannot be 0") 

612 

613 start, stop, step = slc.start or 0, slc.stop, slc.step or 1 

614 try: 

615 ok = [] 

616 for w in (start, stop, step): 

617 w = sympify(w) 

618 if w in [S.NegativeInfinity, S.Infinity] or ( 

619 w.has(Symbol) and w.is_integer != False): 

620 ok.append(w) 

621 elif not w.is_Integer: 

622 if w.is_infinite: 

623 raise ValueError('infinite symbols not allowed') 

624 raise ValueError 

625 else: 

626 ok.append(w) 

627 except ValueError: 

628 raise ValueError(filldedent(''' 

629 Finite arguments to Range must be integers; `imageset` can define 

630 other cases, e.g. use `imageset(i, i/10, Range(3))` to give 

631 [0, 1/10, 1/5].''')) 

632 start, stop, step = ok 

633 

634 null = False 

635 if any(i.has(Symbol) for i in (start, stop, step)): 

636 dif = stop - start 

637 n = dif/step 

638 if n.is_Rational: 

639 if dif == 0: 

640 null = True 

641 else: # (x, x + 5, 2) or (x, 3*x, x) 

642 n = floor(n) 

643 end = start + n*step 

644 if dif.is_Rational: # (x, x + 5, 2) 

645 if (end - stop).is_negative: 

646 end += step 

647 else: # (x, 3*x, x) 

648 if (end/stop - 1).is_negative: 

649 end += step 

650 elif n.is_extended_negative: 

651 null = True 

652 else: 

653 end = stop # other methods like sup and reversed must fail 

654 elif start.is_infinite: 

655 span = step*(stop - start) 

656 if span is S.NaN or span <= 0: 

657 null = True 

658 elif step.is_Integer and stop.is_infinite and abs(step) != 1: 

659 raise ValueError(filldedent(''' 

660 Step size must be %s in this case.''' % (1 if step > 0 else -1))) 

661 else: 

662 end = stop 

663 else: 

664 oostep = step.is_infinite 

665 if oostep: 

666 step = S.One if step > 0 else S.NegativeOne 

667 n = ceiling((stop - start)/step) 

668 if n <= 0: 

669 null = True 

670 elif oostep: 

671 step = S.One # make it canonical 

672 end = start + step 

673 else: 

674 end = start + n*step 

675 if null: 

676 start = end = S.Zero 

677 step = S.One 

678 return Basic.__new__(cls, start, end, step) 

679 

680 start = property(lambda self: self.args[0]) 

681 stop = property(lambda self: self.args[1]) 

682 step = property(lambda self: self.args[2]) 

683 

684 @property 

685 def reversed(self): 

686 """Return an equivalent Range in the opposite order. 

687 

688 Examples 

689 ======== 

690 

691 >>> from sympy import Range 

692 >>> Range(10).reversed 

693 Range(9, -1, -1) 

694 """ 

695 if self.has(Symbol): 

696 n = (self.stop - self.start)/self.step 

697 if not n.is_extended_positive or not all( 

698 i.is_integer or i.is_infinite for i in self.args): 

699 raise ValueError('invalid method for symbolic range') 

700 if self.start == self.stop: 

701 return self 

702 return self.func( 

703 self.stop - self.step, self.start - self.step, -self.step) 

704 

705 def _kind(self): 

706 return SetKind(NumberKind) 

707 

708 def _contains(self, other): 

709 if self.start == self.stop: 

710 return S.false 

711 if other.is_infinite: 

712 return S.false 

713 if not other.is_integer: 

714 return other.is_integer 

715 if self.has(Symbol): 

716 n = (self.stop - self.start)/self.step 

717 if not n.is_extended_positive or not all( 

718 i.is_integer or i.is_infinite for i in self.args): 

719 return 

720 else: 

721 n = self.size 

722 if self.start.is_finite: 

723 ref = self.start 

724 elif self.stop.is_finite: 

725 ref = self.stop 

726 else: # both infinite; step is +/- 1 (enforced by __new__) 

727 return S.true 

728 if n == 1: 

729 return Eq(other, self[0]) 

730 res = (ref - other) % self.step 

731 if res == S.Zero: 

732 if self.has(Symbol): 

733 d = Dummy('i') 

734 return self.as_relational(d).subs(d, other) 

735 return And(other >= self.inf, other <= self.sup) 

736 elif res.is_Integer: # off sequence 

737 return S.false 

738 else: # symbolic/unsimplified residue modulo step 

739 return None 

740 

741 def __iter__(self): 

742 n = self.size # validate 

743 if not (n.has(S.Infinity) or n.has(S.NegativeInfinity) or n.is_Integer): 

744 raise TypeError("Cannot iterate over symbolic Range") 

745 if self.start in [S.NegativeInfinity, S.Infinity]: 

746 raise TypeError("Cannot iterate over Range with infinite start") 

747 elif self.start != self.stop: 

748 i = self.start 

749 if n.is_infinite: 

750 while True: 

751 yield i 

752 i += self.step 

753 else: 

754 for _ in range(n): 

755 yield i 

756 i += self.step 

757 

758 @property 

759 def is_iterable(self): 

760 # Check that size can be determined, used by __iter__ 

761 dif = self.stop - self.start 

762 n = dif/self.step 

763 if not (n.has(S.Infinity) or n.has(S.NegativeInfinity) or n.is_Integer): 

764 return False 

765 if self.start in [S.NegativeInfinity, S.Infinity]: 

766 return False 

767 if not (n.is_extended_nonnegative and all(i.is_integer for i in self.args)): 

768 return False 

769 return True 

770 

771 def __len__(self): 

772 rv = self.size 

773 if rv is S.Infinity: 

774 raise ValueError('Use .size to get the length of an infinite Range') 

775 return int(rv) 

776 

777 @property 

778 def size(self): 

779 if self.start == self.stop: 

780 return S.Zero 

781 dif = self.stop - self.start 

782 n = dif/self.step 

783 if n.is_infinite: 

784 return S.Infinity 

785 if n.is_extended_nonnegative and all(i.is_integer for i in self.args): 

786 return abs(floor(n)) 

787 raise ValueError('Invalid method for symbolic Range') 

788 

789 @property 

790 def is_finite_set(self): 

791 if self.start.is_integer and self.stop.is_integer: 

792 return True 

793 return self.size.is_finite 

794 

795 @property 

796 def is_empty(self): 

797 try: 

798 return self.size.is_zero 

799 except ValueError: 

800 return None 

801 

802 def __bool__(self): 

803 # this only distinguishes between definite null range 

804 # and non-null/unknown null; getting True doesn't mean 

805 # that it actually is not null 

806 b = is_eq(self.start, self.stop) 

807 if b is None: 

808 raise ValueError('cannot tell if Range is null or not') 

809 return not bool(b) 

810 

811 def __getitem__(self, i): 

812 ooslice = "cannot slice from the end with an infinite value" 

813 zerostep = "slice step cannot be zero" 

814 infinite = "slicing not possible on range with infinite start" 

815 # if we had to take every other element in the following 

816 # oo, ..., 6, 4, 2, 0 

817 # we might get oo, ..., 4, 0 or oo, ..., 6, 2 

818 ambiguous = "cannot unambiguously re-stride from the end " + \ 

819 "with an infinite value" 

820 if isinstance(i, slice): 

821 if self.size.is_finite: # validates, too 

822 if self.start == self.stop: 

823 return Range(0) 

824 start, stop, step = i.indices(self.size) 

825 n = ceiling((stop - start)/step) 

826 if n <= 0: 

827 return Range(0) 

828 canonical_stop = start + n*step 

829 end = canonical_stop - step 

830 ss = step*self.step 

831 return Range(self[start], self[end] + ss, ss) 

832 else: # infinite Range 

833 start = i.start 

834 stop = i.stop 

835 if i.step == 0: 

836 raise ValueError(zerostep) 

837 step = i.step or 1 

838 ss = step*self.step 

839 #--------------------- 

840 # handle infinite Range 

841 # i.e. Range(-oo, oo) or Range(oo, -oo, -1) 

842 # -------------------- 

843 if self.start.is_infinite and self.stop.is_infinite: 

844 raise ValueError(infinite) 

845 #--------------------- 

846 # handle infinite on right 

847 # e.g. Range(0, oo) or Range(0, -oo, -1) 

848 # -------------------- 

849 if self.stop.is_infinite: 

850 # start and stop are not interdependent -- 

851 # they only depend on step --so we use the 

852 # equivalent reversed values 

853 return self.reversed[ 

854 stop if stop is None else -stop + 1: 

855 start if start is None else -start: 

856 step].reversed 

857 #--------------------- 

858 # handle infinite on the left 

859 # e.g. Range(oo, 0, -1) or Range(-oo, 0) 

860 # -------------------- 

861 # consider combinations of 

862 # start/stop {== None, < 0, == 0, > 0} and 

863 # step {< 0, > 0} 

864 if start is None: 

865 if stop is None: 

866 if step < 0: 

867 return Range(self[-1], self.start, ss) 

868 elif step > 1: 

869 raise ValueError(ambiguous) 

870 else: # == 1 

871 return self 

872 elif stop < 0: 

873 if step < 0: 

874 return Range(self[-1], self[stop], ss) 

875 else: # > 0 

876 return Range(self.start, self[stop], ss) 

877 elif stop == 0: 

878 if step > 0: 

879 return Range(0) 

880 else: # < 0 

881 raise ValueError(ooslice) 

882 elif stop == 1: 

883 if step > 0: 

884 raise ValueError(ooslice) # infinite singleton 

885 else: # < 0 

886 raise ValueError(ooslice) 

887 else: # > 1 

888 raise ValueError(ooslice) 

889 elif start < 0: 

890 if stop is None: 

891 if step < 0: 

892 return Range(self[start], self.start, ss) 

893 else: # > 0 

894 return Range(self[start], self.stop, ss) 

895 elif stop < 0: 

896 return Range(self[start], self[stop], ss) 

897 elif stop == 0: 

898 if step < 0: 

899 raise ValueError(ooslice) 

900 else: # > 0 

901 return Range(0) 

902 elif stop > 0: 

903 raise ValueError(ooslice) 

904 elif start == 0: 

905 if stop is None: 

906 if step < 0: 

907 raise ValueError(ooslice) # infinite singleton 

908 elif step > 1: 

909 raise ValueError(ambiguous) 

910 else: # == 1 

911 return self 

912 elif stop < 0: 

913 if step > 1: 

914 raise ValueError(ambiguous) 

915 elif step == 1: 

916 return Range(self.start, self[stop], ss) 

917 else: # < 0 

918 return Range(0) 

919 else: # >= 0 

920 raise ValueError(ooslice) 

921 elif start > 0: 

922 raise ValueError(ooslice) 

923 else: 

924 if self.start == self.stop: 

925 raise IndexError('Range index out of range') 

926 if not (all(i.is_integer or i.is_infinite 

927 for i in self.args) and ((self.stop - self.start)/ 

928 self.step).is_extended_positive): 

929 raise ValueError('Invalid method for symbolic Range') 

930 if i == 0: 

931 if self.start.is_infinite: 

932 raise ValueError(ooslice) 

933 return self.start 

934 if i == -1: 

935 if self.stop.is_infinite: 

936 raise ValueError(ooslice) 

937 return self.stop - self.step 

938 n = self.size # must be known for any other index 

939 rv = (self.stop if i < 0 else self.start) + i*self.step 

940 if rv.is_infinite: 

941 raise ValueError(ooslice) 

942 val = (rv - self.start)/self.step 

943 rel = fuzzy_or([val.is_infinite, 

944 fuzzy_and([val.is_nonnegative, (n-val).is_nonnegative])]) 

945 if rel: 

946 return rv 

947 if rel is None: 

948 raise ValueError('Invalid method for symbolic Range') 

949 raise IndexError("Range index out of range") 

950 

951 @property 

952 def _inf(self): 

953 if not self: 

954 return S.EmptySet.inf 

955 if self.has(Symbol): 

956 if all(i.is_integer or i.is_infinite for i in self.args): 

957 dif = self.stop - self.start 

958 if self.step.is_positive and dif.is_positive: 

959 return self.start 

960 elif self.step.is_negative and dif.is_negative: 

961 return self.stop - self.step 

962 raise ValueError('invalid method for symbolic range') 

963 if self.step > 0: 

964 return self.start 

965 else: 

966 return self.stop - self.step 

967 

968 @property 

969 def _sup(self): 

970 if not self: 

971 return S.EmptySet.sup 

972 if self.has(Symbol): 

973 if all(i.is_integer or i.is_infinite for i in self.args): 

974 dif = self.stop - self.start 

975 if self.step.is_positive and dif.is_positive: 

976 return self.stop - self.step 

977 elif self.step.is_negative and dif.is_negative: 

978 return self.start 

979 raise ValueError('invalid method for symbolic range') 

980 if self.step > 0: 

981 return self.stop - self.step 

982 else: 

983 return self.start 

984 

985 @property 

986 def _boundary(self): 

987 return self 

988 

989 def as_relational(self, x): 

990 """Rewrite a Range in terms of equalities and logic operators. """ 

991 if self.start.is_infinite: 

992 assert not self.stop.is_infinite # by instantiation 

993 a = self.reversed.start 

994 else: 

995 a = self.start 

996 step = self.step 

997 in_seq = Eq(Mod(x - a, step), 0) 

998 ints = And(Eq(Mod(a, 1), 0), Eq(Mod(step, 1), 0)) 

999 n = (self.stop - self.start)/self.step 

1000 if n == 0: 

1001 return S.EmptySet.as_relational(x) 

1002 if n == 1: 

1003 return And(Eq(x, a), ints) 

1004 try: 

1005 a, b = self.inf, self.sup 

1006 except ValueError: 

1007 a = None 

1008 if a is not None: 

1009 range_cond = And( 

1010 x > a if a.is_infinite else x >= a, 

1011 x < b if b.is_infinite else x <= b) 

1012 else: 

1013 a, b = self.start, self.stop - self.step 

1014 range_cond = Or( 

1015 And(self.step >= 1, x > a if a.is_infinite else x >= a, 

1016 x < b if b.is_infinite else x <= b), 

1017 And(self.step <= -1, x < a if a.is_infinite else x <= a, 

1018 x > b if b.is_infinite else x >= b)) 

1019 return And(in_seq, ints, range_cond) 

1020 

1021 

1022_sympy_converter[range] = lambda r: Range(r.start, r.stop, r.step) 

1023 

1024def normalize_theta_set(theta): 

1025 r""" 

1026 Normalize a Real Set `theta` in the interval `[0, 2\pi)`. It returns 

1027 a normalized value of theta in the Set. For Interval, a maximum of 

1028 one cycle $[0, 2\pi]$, is returned i.e. for theta equal to $[0, 10\pi]$, 

1029 returned normalized value would be $[0, 2\pi)$. As of now intervals 

1030 with end points as non-multiples of ``pi`` is not supported. 

1031 

1032 Raises 

1033 ====== 

1034 

1035 NotImplementedError 

1036 The algorithms for Normalizing theta Set are not yet 

1037 implemented. 

1038 ValueError 

1039 The input is not valid, i.e. the input is not a real set. 

1040 RuntimeError 

1041 It is a bug, please report to the github issue tracker. 

1042 

1043 Examples 

1044 ======== 

1045 

1046 >>> from sympy.sets.fancysets import normalize_theta_set 

1047 >>> from sympy import Interval, FiniteSet, pi 

1048 >>> normalize_theta_set(Interval(9*pi/2, 5*pi)) 

1049 Interval(pi/2, pi) 

1050 >>> normalize_theta_set(Interval(-3*pi/2, pi/2)) 

1051 Interval.Ropen(0, 2*pi) 

1052 >>> normalize_theta_set(Interval(-pi/2, pi/2)) 

1053 Union(Interval(0, pi/2), Interval.Ropen(3*pi/2, 2*pi)) 

1054 >>> normalize_theta_set(Interval(-4*pi, 3*pi)) 

1055 Interval.Ropen(0, 2*pi) 

1056 >>> normalize_theta_set(Interval(-3*pi/2, -pi/2)) 

1057 Interval(pi/2, 3*pi/2) 

1058 >>> normalize_theta_set(FiniteSet(0, pi, 3*pi)) 

1059 {0, pi} 

1060 

1061 """ 

1062 from sympy.functions.elementary.trigonometric import _pi_coeff 

1063 

1064 if theta.is_Interval: 

1065 interval_len = theta.measure 

1066 # one complete circle 

1067 if interval_len >= 2*S.Pi: 

1068 if interval_len == 2*S.Pi and theta.left_open and theta.right_open: 

1069 k = _pi_coeff(theta.start) 

1070 return Union(Interval(0, k*S.Pi, False, True), 

1071 Interval(k*S.Pi, 2*S.Pi, True, True)) 

1072 return Interval(0, 2*S.Pi, False, True) 

1073 

1074 k_start, k_end = _pi_coeff(theta.start), _pi_coeff(theta.end) 

1075 

1076 if k_start is None or k_end is None: 

1077 raise NotImplementedError("Normalizing theta without pi as coefficient is " 

1078 "not yet implemented") 

1079 new_start = k_start*S.Pi 

1080 new_end = k_end*S.Pi 

1081 

1082 if new_start > new_end: 

1083 return Union(Interval(S.Zero, new_end, False, theta.right_open), 

1084 Interval(new_start, 2*S.Pi, theta.left_open, True)) 

1085 else: 

1086 return Interval(new_start, new_end, theta.left_open, theta.right_open) 

1087 

1088 elif theta.is_FiniteSet: 

1089 new_theta = [] 

1090 for element in theta: 

1091 k = _pi_coeff(element) 

1092 if k is None: 

1093 raise NotImplementedError('Normalizing theta without pi as ' 

1094 'coefficient, is not Implemented.') 

1095 else: 

1096 new_theta.append(k*S.Pi) 

1097 return FiniteSet(*new_theta) 

1098 

1099 elif theta.is_Union: 

1100 return Union(*[normalize_theta_set(interval) for interval in theta.args]) 

1101 

1102 elif theta.is_subset(S.Reals): 

1103 raise NotImplementedError("Normalizing theta when, it is of type %s is not " 

1104 "implemented" % type(theta)) 

1105 else: 

1106 raise ValueError(" %s is not a real set" % (theta)) 

1107 

1108 

1109class ComplexRegion(Set): 

1110 r""" 

1111 Represents the Set of all Complex Numbers. It can represent a 

1112 region of Complex Plane in both the standard forms Polar and 

1113 Rectangular coordinates. 

1114 

1115 * Polar Form 

1116 Input is in the form of the ProductSet or Union of ProductSets 

1117 of the intervals of ``r`` and ``theta``, and use the flag ``polar=True``. 

1118 

1119 .. math:: Z = \{z \in \mathbb{C} \mid z = r\times (\cos(\theta) + I\sin(\theta)), r \in [\texttt{r}], \theta \in [\texttt{theta}]\} 

1120 

1121 * Rectangular Form 

1122 Input is in the form of the ProductSet or Union of ProductSets 

1123 of interval of x and y, the real and imaginary parts of the Complex numbers in a plane. 

1124 Default input type is in rectangular form. 

1125 

1126 .. math:: Z = \{z \in \mathbb{C} \mid z = x + Iy, x \in [\operatorname{re}(z)], y \in [\operatorname{im}(z)]\} 

1127 

1128 Examples 

1129 ======== 

1130 

1131 >>> from sympy import ComplexRegion, Interval, S, I, Union 

1132 >>> a = Interval(2, 3) 

1133 >>> b = Interval(4, 6) 

1134 >>> c1 = ComplexRegion(a*b) # Rectangular Form 

1135 >>> c1 

1136 CartesianComplexRegion(ProductSet(Interval(2, 3), Interval(4, 6))) 

1137 

1138 * c1 represents the rectangular region in complex plane 

1139 surrounded by the coordinates (2, 4), (3, 4), (3, 6) and 

1140 (2, 6), of the four vertices. 

1141 

1142 >>> c = Interval(1, 8) 

1143 >>> c2 = ComplexRegion(Union(a*b, b*c)) 

1144 >>> c2 

1145 CartesianComplexRegion(Union(ProductSet(Interval(2, 3), Interval(4, 6)), ProductSet(Interval(4, 6), Interval(1, 8)))) 

1146 

1147 * c2 represents the Union of two rectangular regions in complex 

1148 plane. One of them surrounded by the coordinates of c1 and 

1149 other surrounded by the coordinates (4, 1), (6, 1), (6, 8) and 

1150 (4, 8). 

1151 

1152 >>> 2.5 + 4.5*I in c1 

1153 True 

1154 >>> 2.5 + 6.5*I in c1 

1155 False 

1156 

1157 >>> r = Interval(0, 1) 

1158 >>> theta = Interval(0, 2*S.Pi) 

1159 >>> c2 = ComplexRegion(r*theta, polar=True) # Polar Form 

1160 >>> c2 # unit Disk 

1161 PolarComplexRegion(ProductSet(Interval(0, 1), Interval.Ropen(0, 2*pi))) 

1162 

1163 * c2 represents the region in complex plane inside the 

1164 Unit Disk centered at the origin. 

1165 

1166 >>> 0.5 + 0.5*I in c2 

1167 True 

1168 >>> 1 + 2*I in c2 

1169 False 

1170 

1171 >>> unit_disk = ComplexRegion(Interval(0, 1)*Interval(0, 2*S.Pi), polar=True) 

1172 >>> upper_half_unit_disk = ComplexRegion(Interval(0, 1)*Interval(0, S.Pi), polar=True) 

1173 >>> intersection = unit_disk.intersect(upper_half_unit_disk) 

1174 >>> intersection 

1175 PolarComplexRegion(ProductSet(Interval(0, 1), Interval(0, pi))) 

1176 >>> intersection == upper_half_unit_disk 

1177 True 

1178 

1179 See Also 

1180 ======== 

1181 

1182 CartesianComplexRegion 

1183 PolarComplexRegion 

1184 Complexes 

1185 

1186 """ 

1187 is_ComplexRegion = True 

1188 

1189 def __new__(cls, sets, polar=False): 

1190 if polar is False: 

1191 return CartesianComplexRegion(sets) 

1192 elif polar is True: 

1193 return PolarComplexRegion(sets) 

1194 else: 

1195 raise ValueError("polar should be either True or False") 

1196 

1197 @property 

1198 def sets(self): 

1199 """ 

1200 Return raw input sets to the self. 

1201 

1202 Examples 

1203 ======== 

1204 

1205 >>> from sympy import Interval, ComplexRegion, Union 

1206 >>> a = Interval(2, 3) 

1207 >>> b = Interval(4, 5) 

1208 >>> c = Interval(1, 7) 

1209 >>> C1 = ComplexRegion(a*b) 

1210 >>> C1.sets 

1211 ProductSet(Interval(2, 3), Interval(4, 5)) 

1212 >>> C2 = ComplexRegion(Union(a*b, b*c)) 

1213 >>> C2.sets 

1214 Union(ProductSet(Interval(2, 3), Interval(4, 5)), ProductSet(Interval(4, 5), Interval(1, 7))) 

1215 

1216 """ 

1217 return self.args[0] 

1218 

1219 @property 

1220 def psets(self): 

1221 """ 

1222 Return a tuple of sets (ProductSets) input of the self. 

1223 

1224 Examples 

1225 ======== 

1226 

1227 >>> from sympy import Interval, ComplexRegion, Union 

1228 >>> a = Interval(2, 3) 

1229 >>> b = Interval(4, 5) 

1230 >>> c = Interval(1, 7) 

1231 >>> C1 = ComplexRegion(a*b) 

1232 >>> C1.psets 

1233 (ProductSet(Interval(2, 3), Interval(4, 5)),) 

1234 >>> C2 = ComplexRegion(Union(a*b, b*c)) 

1235 >>> C2.psets 

1236 (ProductSet(Interval(2, 3), Interval(4, 5)), ProductSet(Interval(4, 5), Interval(1, 7))) 

1237 

1238 """ 

1239 if self.sets.is_ProductSet: 

1240 psets = () 

1241 psets = psets + (self.sets, ) 

1242 else: 

1243 psets = self.sets.args 

1244 return psets 

1245 

1246 @property 

1247 def a_interval(self): 

1248 """ 

1249 Return the union of intervals of `x` when, self is in 

1250 rectangular form, or the union of intervals of `r` when 

1251 self is in polar form. 

1252 

1253 Examples 

1254 ======== 

1255 

1256 >>> from sympy import Interval, ComplexRegion, Union 

1257 >>> a = Interval(2, 3) 

1258 >>> b = Interval(4, 5) 

1259 >>> c = Interval(1, 7) 

1260 >>> C1 = ComplexRegion(a*b) 

1261 >>> C1.a_interval 

1262 Interval(2, 3) 

1263 >>> C2 = ComplexRegion(Union(a*b, b*c)) 

1264 >>> C2.a_interval 

1265 Union(Interval(2, 3), Interval(4, 5)) 

1266 

1267 """ 

1268 a_interval = [] 

1269 for element in self.psets: 

1270 a_interval.append(element.args[0]) 

1271 

1272 a_interval = Union(*a_interval) 

1273 return a_interval 

1274 

1275 @property 

1276 def b_interval(self): 

1277 """ 

1278 Return the union of intervals of `y` when, self is in 

1279 rectangular form, or the union of intervals of `theta` 

1280 when self is in polar form. 

1281 

1282 Examples 

1283 ======== 

1284 

1285 >>> from sympy import Interval, ComplexRegion, Union 

1286 >>> a = Interval(2, 3) 

1287 >>> b = Interval(4, 5) 

1288 >>> c = Interval(1, 7) 

1289 >>> C1 = ComplexRegion(a*b) 

1290 >>> C1.b_interval 

1291 Interval(4, 5) 

1292 >>> C2 = ComplexRegion(Union(a*b, b*c)) 

1293 >>> C2.b_interval 

1294 Interval(1, 7) 

1295 

1296 """ 

1297 b_interval = [] 

1298 for element in self.psets: 

1299 b_interval.append(element.args[1]) 

1300 

1301 b_interval = Union(*b_interval) 

1302 return b_interval 

1303 

1304 @property 

1305 def _measure(self): 

1306 """ 

1307 The measure of self.sets. 

1308 

1309 Examples 

1310 ======== 

1311 

1312 >>> from sympy import Interval, ComplexRegion, S 

1313 >>> a, b = Interval(2, 5), Interval(4, 8) 

1314 >>> c = Interval(0, 2*S.Pi) 

1315 >>> c1 = ComplexRegion(a*b) 

1316 >>> c1.measure 

1317 12 

1318 >>> c2 = ComplexRegion(a*c, polar=True) 

1319 >>> c2.measure 

1320 6*pi 

1321 

1322 """ 

1323 return self.sets._measure 

1324 

1325 def _kind(self): 

1326 return self.args[0].kind 

1327 

1328 @classmethod 

1329 def from_real(cls, sets): 

1330 """ 

1331 Converts given subset of real numbers to a complex region. 

1332 

1333 Examples 

1334 ======== 

1335 

1336 >>> from sympy import Interval, ComplexRegion 

1337 >>> unit = Interval(0,1) 

1338 >>> ComplexRegion.from_real(unit) 

1339 CartesianComplexRegion(ProductSet(Interval(0, 1), {0})) 

1340 

1341 """ 

1342 if not sets.is_subset(S.Reals): 

1343 raise ValueError("sets must be a subset of the real line") 

1344 

1345 return CartesianComplexRegion(sets * FiniteSet(0)) 

1346 

1347 def _contains(self, other): 

1348 from sympy.functions import arg, Abs 

1349 other = sympify(other) 

1350 isTuple = isinstance(other, Tuple) 

1351 if isTuple and len(other) != 2: 

1352 raise ValueError('expecting Tuple of length 2') 

1353 

1354 # If the other is not an Expression, and neither a Tuple 

1355 if not isinstance(other, (Expr, Tuple)): 

1356 return S.false 

1357 # self in rectangular form 

1358 if not self.polar: 

1359 re, im = other if isTuple else other.as_real_imag() 

1360 return fuzzy_or(fuzzy_and([ 

1361 pset.args[0]._contains(re), 

1362 pset.args[1]._contains(im)]) 

1363 for pset in self.psets) 

1364 

1365 # self in polar form 

1366 elif self.polar: 

1367 if other.is_zero: 

1368 # ignore undefined complex argument 

1369 return fuzzy_or(pset.args[0]._contains(S.Zero) 

1370 for pset in self.psets) 

1371 if isTuple: 

1372 r, theta = other 

1373 else: 

1374 r, theta = Abs(other), arg(other) 

1375 if theta.is_real and theta.is_number: 

1376 # angles in psets are normalized to [0, 2pi) 

1377 theta %= 2*S.Pi 

1378 return fuzzy_or(fuzzy_and([ 

1379 pset.args[0]._contains(r), 

1380 pset.args[1]._contains(theta)]) 

1381 for pset in self.psets) 

1382 

1383 

1384class CartesianComplexRegion(ComplexRegion): 

1385 r""" 

1386 Set representing a square region of the complex plane. 

1387 

1388 .. math:: Z = \{z \in \mathbb{C} \mid z = x + Iy, x \in [\operatorname{re}(z)], y \in [\operatorname{im}(z)]\} 

1389 

1390 Examples 

1391 ======== 

1392 

1393 >>> from sympy import ComplexRegion, I, Interval 

1394 >>> region = ComplexRegion(Interval(1, 3) * Interval(4, 6)) 

1395 >>> 2 + 5*I in region 

1396 True 

1397 >>> 5*I in region 

1398 False 

1399 

1400 See also 

1401 ======== 

1402 

1403 ComplexRegion 

1404 PolarComplexRegion 

1405 Complexes 

1406 """ 

1407 

1408 polar = False 

1409 variables = symbols('x, y', cls=Dummy) 

1410 

1411 def __new__(cls, sets): 

1412 

1413 if sets == S.Reals*S.Reals: 

1414 return S.Complexes 

1415 

1416 if all(_a.is_FiniteSet for _a in sets.args) and (len(sets.args) == 2): 

1417 

1418 # ** ProductSet of FiniteSets in the Complex Plane. ** 

1419 # For Cases like ComplexRegion({2, 4}*{3}), It 

1420 # would return {2 + 3*I, 4 + 3*I} 

1421 

1422 # FIXME: This should probably be handled with something like: 

1423 # return ImageSet(Lambda((x, y), x+I*y), sets).rewrite(FiniteSet) 

1424 complex_num = [] 

1425 for x in sets.args[0]: 

1426 for y in sets.args[1]: 

1427 complex_num.append(x + S.ImaginaryUnit*y) 

1428 return FiniteSet(*complex_num) 

1429 else: 

1430 return Set.__new__(cls, sets) 

1431 

1432 @property 

1433 def expr(self): 

1434 x, y = self.variables 

1435 return x + S.ImaginaryUnit*y 

1436 

1437 

1438class PolarComplexRegion(ComplexRegion): 

1439 r""" 

1440 Set representing a polar region of the complex plane. 

1441 

1442 .. math:: Z = \{z \in \mathbb{C} \mid z = r\times (\cos(\theta) + I\sin(\theta)), r \in [\texttt{r}], \theta \in [\texttt{theta}]\} 

1443 

1444 Examples 

1445 ======== 

1446 

1447 >>> from sympy import ComplexRegion, Interval, oo, pi, I 

1448 >>> rset = Interval(0, oo) 

1449 >>> thetaset = Interval(0, pi) 

1450 >>> upper_half_plane = ComplexRegion(rset * thetaset, polar=True) 

1451 >>> 1 + I in upper_half_plane 

1452 True 

1453 >>> 1 - I in upper_half_plane 

1454 False 

1455 

1456 See also 

1457 ======== 

1458 

1459 ComplexRegion 

1460 CartesianComplexRegion 

1461 Complexes 

1462 

1463 """ 

1464 

1465 polar = True 

1466 variables = symbols('r, theta', cls=Dummy) 

1467 

1468 def __new__(cls, sets): 

1469 

1470 new_sets = [] 

1471 # sets is Union of ProductSets 

1472 if not sets.is_ProductSet: 

1473 for k in sets.args: 

1474 new_sets.append(k) 

1475 # sets is ProductSets 

1476 else: 

1477 new_sets.append(sets) 

1478 # Normalize input theta 

1479 for k, v in enumerate(new_sets): 

1480 new_sets[k] = ProductSet(v.args[0], 

1481 normalize_theta_set(v.args[1])) 

1482 sets = Union(*new_sets) 

1483 return Set.__new__(cls, sets) 

1484 

1485 @property 

1486 def expr(self): 

1487 r, theta = self.variables 

1488 return r*(cos(theta) + S.ImaginaryUnit*sin(theta)) 

1489 

1490 

1491class Complexes(CartesianComplexRegion, metaclass=Singleton): 

1492 """ 

1493 The :class:`Set` of all complex numbers 

1494 

1495 Examples 

1496 ======== 

1497 

1498 >>> from sympy import S, I 

1499 >>> S.Complexes 

1500 Complexes 

1501 >>> 1 + I in S.Complexes 

1502 True 

1503 

1504 See also 

1505 ======== 

1506 

1507 Reals 

1508 ComplexRegion 

1509 

1510 """ 

1511 

1512 is_empty = False 

1513 is_finite_set = False 

1514 

1515 # Override property from superclass since Complexes has no args 

1516 @property 

1517 def sets(self): 

1518 return ProductSet(S.Reals, S.Reals) 

1519 

1520 def __new__(cls): 

1521 return Set.__new__(cls)