sqrtdenest.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. from sympy.core import Add, Expr, Mul, S, sympify
  2. from sympy.core.function import _mexpand, count_ops, expand_mul
  3. from sympy.core.sorting import default_sort_key
  4. from sympy.core.symbol import Dummy
  5. from sympy.functions import root, sign, sqrt
  6. from sympy.polys import Poly, PolynomialError
  7. def is_sqrt(expr):
  8. """Return True if expr is a sqrt, otherwise False."""
  9. return expr.is_Pow and expr.exp.is_Rational and abs(expr.exp) is S.Half
  10. def sqrt_depth(p):
  11. """Return the maximum depth of any square root argument of p.
  12. >>> from sympy.functions.elementary.miscellaneous import sqrt
  13. >>> from sympy.simplify.sqrtdenest import sqrt_depth
  14. Neither of these square roots contains any other square roots
  15. so the depth is 1:
  16. >>> sqrt_depth(1 + sqrt(2)*(1 + sqrt(3)))
  17. 1
  18. The sqrt(3) is contained within a square root so the depth is
  19. 2:
  20. >>> sqrt_depth(1 + sqrt(2)*sqrt(1 + sqrt(3)))
  21. 2
  22. """
  23. if p is S.ImaginaryUnit:
  24. return 1
  25. if p.is_Atom:
  26. return 0
  27. elif p.is_Add or p.is_Mul:
  28. return max([sqrt_depth(x) for x in p.args], key=default_sort_key)
  29. elif is_sqrt(p):
  30. return sqrt_depth(p.base) + 1
  31. else:
  32. return 0
  33. def is_algebraic(p):
  34. """Return True if p is comprised of only Rationals or square roots
  35. of Rationals and algebraic operations.
  36. Examples
  37. ========
  38. >>> from sympy.functions.elementary.miscellaneous import sqrt
  39. >>> from sympy.simplify.sqrtdenest import is_algebraic
  40. >>> from sympy import cos
  41. >>> is_algebraic(sqrt(2)*(3/(sqrt(7) + sqrt(5)*sqrt(2))))
  42. True
  43. >>> is_algebraic(sqrt(2)*(3/(sqrt(7) + sqrt(5)*cos(2))))
  44. False
  45. """
  46. if p.is_Rational:
  47. return True
  48. elif p.is_Atom:
  49. return False
  50. elif is_sqrt(p) or p.is_Pow and p.exp.is_Integer:
  51. return is_algebraic(p.base)
  52. elif p.is_Add or p.is_Mul:
  53. return all(is_algebraic(x) for x in p.args)
  54. else:
  55. return False
  56. def _subsets(n):
  57. """
  58. Returns all possible subsets of the set (0, 1, ..., n-1) except the
  59. empty set, listed in reversed lexicographical order according to binary
  60. representation, so that the case of the fourth root is treated last.
  61. Examples
  62. ========
  63. >>> from sympy.simplify.sqrtdenest import _subsets
  64. >>> _subsets(2)
  65. [[1, 0], [0, 1], [1, 1]]
  66. """
  67. if n == 1:
  68. a = [[1]]
  69. elif n == 2:
  70. a = [[1, 0], [0, 1], [1, 1]]
  71. elif n == 3:
  72. a = [[1, 0, 0], [0, 1, 0], [1, 1, 0],
  73. [0, 0, 1], [1, 0, 1], [0, 1, 1], [1, 1, 1]]
  74. else:
  75. b = _subsets(n - 1)
  76. a0 = [x + [0] for x in b]
  77. a1 = [x + [1] for x in b]
  78. a = a0 + [[0]*(n - 1) + [1]] + a1
  79. return a
  80. def sqrtdenest(expr, max_iter=3):
  81. """Denests sqrts in an expression that contain other square roots
  82. if possible, otherwise returns the expr unchanged. This is based on the
  83. algorithms of [1].
  84. Examples
  85. ========
  86. >>> from sympy.simplify.sqrtdenest import sqrtdenest
  87. >>> from sympy import sqrt
  88. >>> sqrtdenest(sqrt(5 + 2 * sqrt(6)))
  89. sqrt(2) + sqrt(3)
  90. See Also
  91. ========
  92. sympy.solvers.solvers.unrad
  93. References
  94. ==========
  95. .. [1] http://researcher.watson.ibm.com/researcher/files/us-fagin/symb85.pdf
  96. .. [2] D. J. Jeffrey and A. D. Rich, 'Symplifying Square Roots of Square Roots
  97. by Denesting' (available at http://www.cybertester.com/data/denest.pdf)
  98. """
  99. expr = expand_mul(sympify(expr))
  100. for i in range(max_iter):
  101. z = _sqrtdenest0(expr)
  102. if expr == z:
  103. return expr
  104. expr = z
  105. return expr
  106. def _sqrt_match(p):
  107. """Return [a, b, r] for p.match(a + b*sqrt(r)) where, in addition to
  108. matching, sqrt(r) also has then maximal sqrt_depth among addends of p.
  109. Examples
  110. ========
  111. >>> from sympy.functions.elementary.miscellaneous import sqrt
  112. >>> from sympy.simplify.sqrtdenest import _sqrt_match
  113. >>> _sqrt_match(1 + sqrt(2) + sqrt(2)*sqrt(3) + 2*sqrt(1+sqrt(5)))
  114. [1 + sqrt(2) + sqrt(6), 2, 1 + sqrt(5)]
  115. """
  116. from sympy.simplify.radsimp import split_surds
  117. p = _mexpand(p)
  118. if p.is_Number:
  119. res = (p, S.Zero, S.Zero)
  120. elif p.is_Add:
  121. pargs = sorted(p.args, key=default_sort_key)
  122. sqargs = [x**2 for x in pargs]
  123. if all(sq.is_Rational and sq.is_positive for sq in sqargs):
  124. r, b, a = split_surds(p)
  125. res = a, b, r
  126. return list(res)
  127. # to make the process canonical, the argument is included in the tuple
  128. # so when the max is selected, it will be the largest arg having a
  129. # given depth
  130. v = [(sqrt_depth(x), x, i) for i, x in enumerate(pargs)]
  131. nmax = max(v, key=default_sort_key)
  132. if nmax[0] == 0:
  133. res = []
  134. else:
  135. # select r
  136. depth, _, i = nmax
  137. r = pargs.pop(i)
  138. v.pop(i)
  139. b = S.One
  140. if r.is_Mul:
  141. bv = []
  142. rv = []
  143. for x in r.args:
  144. if sqrt_depth(x) < depth:
  145. bv.append(x)
  146. else:
  147. rv.append(x)
  148. b = Mul._from_args(bv)
  149. r = Mul._from_args(rv)
  150. # collect terms comtaining r
  151. a1 = []
  152. b1 = [b]
  153. for x in v:
  154. if x[0] < depth:
  155. a1.append(x[1])
  156. else:
  157. x1 = x[1]
  158. if x1 == r:
  159. b1.append(1)
  160. else:
  161. if x1.is_Mul:
  162. x1args = list(x1.args)
  163. if r in x1args:
  164. x1args.remove(r)
  165. b1.append(Mul(*x1args))
  166. else:
  167. a1.append(x[1])
  168. else:
  169. a1.append(x[1])
  170. a = Add(*a1)
  171. b = Add(*b1)
  172. res = (a, b, r**2)
  173. else:
  174. b, r = p.as_coeff_Mul()
  175. if is_sqrt(r):
  176. res = (S.Zero, b, r**2)
  177. else:
  178. res = []
  179. return list(res)
  180. class SqrtdenestStopIteration(StopIteration):
  181. pass
  182. def _sqrtdenest0(expr):
  183. """Returns expr after denesting its arguments."""
  184. if is_sqrt(expr):
  185. n, d = expr.as_numer_denom()
  186. if d is S.One: # n is a square root
  187. if n.base.is_Add:
  188. args = sorted(n.base.args, key=default_sort_key)
  189. if len(args) > 2 and all((x**2).is_Integer for x in args):
  190. try:
  191. return _sqrtdenest_rec(n)
  192. except SqrtdenestStopIteration:
  193. pass
  194. expr = sqrt(_mexpand(Add(*[_sqrtdenest0(x) for x in args])))
  195. return _sqrtdenest1(expr)
  196. else:
  197. n, d = [_sqrtdenest0(i) for i in (n, d)]
  198. return n/d
  199. if isinstance(expr, Add):
  200. cs = []
  201. args = []
  202. for arg in expr.args:
  203. c, a = arg.as_coeff_Mul()
  204. cs.append(c)
  205. args.append(a)
  206. if all(c.is_Rational for c in cs) and all(is_sqrt(arg) for arg in args):
  207. return _sqrt_ratcomb(cs, args)
  208. if isinstance(expr, Expr):
  209. args = expr.args
  210. if args:
  211. return expr.func(*[_sqrtdenest0(a) for a in args])
  212. return expr
  213. def _sqrtdenest_rec(expr):
  214. """Helper that denests the square root of three or more surds.
  215. Explanation
  216. ===========
  217. It returns the denested expression; if it cannot be denested it
  218. throws SqrtdenestStopIteration
  219. Algorithm: expr.base is in the extension Q_m = Q(sqrt(r_1),..,sqrt(r_k));
  220. split expr.base = a + b*sqrt(r_k), where `a` and `b` are on
  221. Q_(m-1) = Q(sqrt(r_1),..,sqrt(r_(k-1))); then a**2 - b**2*r_k is
  222. on Q_(m-1); denest sqrt(a**2 - b**2*r_k) and so on.
  223. See [1], section 6.
  224. Examples
  225. ========
  226. >>> from sympy import sqrt
  227. >>> from sympy.simplify.sqrtdenest import _sqrtdenest_rec
  228. >>> _sqrtdenest_rec(sqrt(-72*sqrt(2) + 158*sqrt(5) + 498))
  229. -sqrt(10) + sqrt(2) + 9 + 9*sqrt(5)
  230. >>> w=-6*sqrt(55)-6*sqrt(35)-2*sqrt(22)-2*sqrt(14)+2*sqrt(77)+6*sqrt(10)+65
  231. >>> _sqrtdenest_rec(sqrt(w))
  232. -sqrt(11) - sqrt(7) + sqrt(2) + 3*sqrt(5)
  233. """
  234. from sympy.simplify.radsimp import radsimp, rad_rationalize, split_surds
  235. if not expr.is_Pow:
  236. return sqrtdenest(expr)
  237. if expr.base < 0:
  238. return sqrt(-1)*_sqrtdenest_rec(sqrt(-expr.base))
  239. g, a, b = split_surds(expr.base)
  240. a = a*sqrt(g)
  241. if a < b:
  242. a, b = b, a
  243. c2 = _mexpand(a**2 - b**2)
  244. if len(c2.args) > 2:
  245. g, a1, b1 = split_surds(c2)
  246. a1 = a1*sqrt(g)
  247. if a1 < b1:
  248. a1, b1 = b1, a1
  249. c2_1 = _mexpand(a1**2 - b1**2)
  250. c_1 = _sqrtdenest_rec(sqrt(c2_1))
  251. d_1 = _sqrtdenest_rec(sqrt(a1 + c_1))
  252. num, den = rad_rationalize(b1, d_1)
  253. c = _mexpand(d_1/sqrt(2) + num/(den*sqrt(2)))
  254. else:
  255. c = _sqrtdenest1(sqrt(c2))
  256. if sqrt_depth(c) > 1:
  257. raise SqrtdenestStopIteration
  258. ac = a + c
  259. if len(ac.args) >= len(expr.args):
  260. if count_ops(ac) >= count_ops(expr.base):
  261. raise SqrtdenestStopIteration
  262. d = sqrtdenest(sqrt(ac))
  263. if sqrt_depth(d) > 1:
  264. raise SqrtdenestStopIteration
  265. num, den = rad_rationalize(b, d)
  266. r = d/sqrt(2) + num/(den*sqrt(2))
  267. r = radsimp(r)
  268. return _mexpand(r)
  269. def _sqrtdenest1(expr, denester=True):
  270. """Return denested expr after denesting with simpler methods or, that
  271. failing, using the denester."""
  272. from sympy.simplify.simplify import radsimp
  273. if not is_sqrt(expr):
  274. return expr
  275. a = expr.base
  276. if a.is_Atom:
  277. return expr
  278. val = _sqrt_match(a)
  279. if not val:
  280. return expr
  281. a, b, r = val
  282. # try a quick numeric denesting
  283. d2 = _mexpand(a**2 - b**2*r)
  284. if d2.is_Rational:
  285. if d2.is_positive:
  286. z = _sqrt_numeric_denest(a, b, r, d2)
  287. if z is not None:
  288. return z
  289. else:
  290. # fourth root case
  291. # sqrtdenest(sqrt(3 + 2*sqrt(3))) =
  292. # sqrt(2)*3**(1/4)/2 + sqrt(2)*3**(3/4)/2
  293. dr2 = _mexpand(-d2*r)
  294. dr = sqrt(dr2)
  295. if dr.is_Rational:
  296. z = _sqrt_numeric_denest(_mexpand(b*r), a, r, dr2)
  297. if z is not None:
  298. return z/root(r, 4)
  299. else:
  300. z = _sqrt_symbolic_denest(a, b, r)
  301. if z is not None:
  302. return z
  303. if not denester or not is_algebraic(expr):
  304. return expr
  305. res = sqrt_biquadratic_denest(expr, a, b, r, d2)
  306. if res:
  307. return res
  308. # now call to the denester
  309. av0 = [a, b, r, d2]
  310. z = _denester([radsimp(expr**2)], av0, 0, sqrt_depth(expr))[0]
  311. if av0[1] is None:
  312. return expr
  313. if z is not None:
  314. if sqrt_depth(z) == sqrt_depth(expr) and count_ops(z) > count_ops(expr):
  315. return expr
  316. return z
  317. return expr
  318. def _sqrt_symbolic_denest(a, b, r):
  319. """Given an expression, sqrt(a + b*sqrt(b)), return the denested
  320. expression or None.
  321. Explanation
  322. ===========
  323. If r = ra + rb*sqrt(rr), try replacing sqrt(rr) in ``a`` with
  324. (y**2 - ra)/rb, and if the result is a quadratic, ca*y**2 + cb*y + cc, and
  325. (cb + b)**2 - 4*ca*cc is 0, then sqrt(a + b*sqrt(r)) can be rewritten as
  326. sqrt(ca*(sqrt(r) + (cb + b)/(2*ca))**2).
  327. Examples
  328. ========
  329. >>> from sympy.simplify.sqrtdenest import _sqrt_symbolic_denest, sqrtdenest
  330. >>> from sympy import sqrt, Symbol
  331. >>> from sympy.abc import x
  332. >>> a, b, r = 16 - 2*sqrt(29), 2, -10*sqrt(29) + 55
  333. >>> _sqrt_symbolic_denest(a, b, r)
  334. sqrt(11 - 2*sqrt(29)) + sqrt(5)
  335. If the expression is numeric, it will be simplified:
  336. >>> w = sqrt(sqrt(sqrt(3) + 1) + 1) + 1 + sqrt(2)
  337. >>> sqrtdenest(sqrt((w**2).expand()))
  338. 1 + sqrt(2) + sqrt(1 + sqrt(1 + sqrt(3)))
  339. Otherwise, it will only be simplified if assumptions allow:
  340. >>> w = w.subs(sqrt(3), sqrt(x + 3))
  341. >>> sqrtdenest(sqrt((w**2).expand()))
  342. sqrt((sqrt(sqrt(sqrt(x + 3) + 1) + 1) + 1 + sqrt(2))**2)
  343. Notice that the argument of the sqrt is a square. If x is made positive
  344. then the sqrt of the square is resolved:
  345. >>> _.subs(x, Symbol('x', positive=True))
  346. sqrt(sqrt(sqrt(x + 3) + 1) + 1) + 1 + sqrt(2)
  347. """
  348. a, b, r = map(sympify, (a, b, r))
  349. rval = _sqrt_match(r)
  350. if not rval:
  351. return None
  352. ra, rb, rr = rval
  353. if rb:
  354. y = Dummy('y', positive=True)
  355. try:
  356. newa = Poly(a.subs(sqrt(rr), (y**2 - ra)/rb), y)
  357. except PolynomialError:
  358. return None
  359. if newa.degree() == 2:
  360. ca, cb, cc = newa.all_coeffs()
  361. cb += b
  362. if _mexpand(cb**2 - 4*ca*cc).equals(0):
  363. z = sqrt(ca*(sqrt(r) + cb/(2*ca))**2)
  364. if z.is_number:
  365. z = _mexpand(Mul._from_args(z.as_content_primitive()))
  366. return z
  367. def _sqrt_numeric_denest(a, b, r, d2):
  368. r"""Helper that denest
  369. $\sqrt{a + b \sqrt{r}}, d^2 = a^2 - b^2 r > 0$
  370. If it cannot be denested, it returns ``None``.
  371. """
  372. d = sqrt(d2)
  373. s = a + d
  374. # sqrt_depth(res) <= sqrt_depth(s) + 1
  375. # sqrt_depth(expr) = sqrt_depth(r) + 2
  376. # there is denesting if sqrt_depth(s) + 1 < sqrt_depth(r) + 2
  377. # if s**2 is Number there is a fourth root
  378. if sqrt_depth(s) < sqrt_depth(r) + 1 or (s**2).is_Rational:
  379. s1, s2 = sign(s), sign(b)
  380. if s1 == s2 == -1:
  381. s1 = s2 = 1
  382. res = (s1 * sqrt(a + d) + s2 * sqrt(a - d)) * sqrt(2) / 2
  383. return res.expand()
  384. def sqrt_biquadratic_denest(expr, a, b, r, d2):
  385. """denest expr = sqrt(a + b*sqrt(r))
  386. where a, b, r are linear combinations of square roots of
  387. positive rationals on the rationals (SQRR) and r > 0, b != 0,
  388. d2 = a**2 - b**2*r > 0
  389. If it cannot denest it returns None.
  390. Explanation
  391. ===========
  392. Search for a solution A of type SQRR of the biquadratic equation
  393. 4*A**4 - 4*a*A**2 + b**2*r = 0 (1)
  394. sqd = sqrt(a**2 - b**2*r)
  395. Choosing the sqrt to be positive, the possible solutions are
  396. A = sqrt(a/2 +/- sqd/2)
  397. Since a, b, r are SQRR, then a**2 - b**2*r is a SQRR,
  398. so if sqd can be denested, it is done by
  399. _sqrtdenest_rec, and the result is a SQRR.
  400. Similarly for A.
  401. Examples of solutions (in both cases a and sqd are positive):
  402. Example of expr with solution sqrt(a/2 + sqd/2) but not
  403. solution sqrt(a/2 - sqd/2):
  404. expr = sqrt(-sqrt(15) - sqrt(2)*sqrt(-sqrt(5) + 5) - sqrt(3) + 8)
  405. a = -sqrt(15) - sqrt(3) + 8; sqd = -2*sqrt(5) - 2 + 4*sqrt(3)
  406. Example of expr with solution sqrt(a/2 - sqd/2) but not
  407. solution sqrt(a/2 + sqd/2):
  408. w = 2 + r2 + r3 + (1 + r3)*sqrt(2 + r2 + 5*r3)
  409. expr = sqrt((w**2).expand())
  410. a = 4*sqrt(6) + 8*sqrt(2) + 47 + 28*sqrt(3)
  411. sqd = 29 + 20*sqrt(3)
  412. Define B = b/2*A; eq.(1) implies a = A**2 + B**2*r; then
  413. expr**2 = a + b*sqrt(r) = (A + B*sqrt(r))**2
  414. Examples
  415. ========
  416. >>> from sympy import sqrt
  417. >>> from sympy.simplify.sqrtdenest import _sqrt_match, sqrt_biquadratic_denest
  418. >>> z = sqrt((2*sqrt(2) + 4)*sqrt(2 + sqrt(2)) + 5*sqrt(2) + 8)
  419. >>> a, b, r = _sqrt_match(z**2)
  420. >>> d2 = a**2 - b**2*r
  421. >>> sqrt_biquadratic_denest(z, a, b, r, d2)
  422. sqrt(2) + sqrt(sqrt(2) + 2) + 2
  423. """
  424. from sympy.simplify.radsimp import radsimp, rad_rationalize
  425. if r <= 0 or d2 < 0 or not b or sqrt_depth(expr.base) < 2:
  426. return None
  427. for x in (a, b, r):
  428. for y in x.args:
  429. y2 = y**2
  430. if not y2.is_Integer or not y2.is_positive:
  431. return None
  432. sqd = _mexpand(sqrtdenest(sqrt(radsimp(d2))))
  433. if sqrt_depth(sqd) > 1:
  434. return None
  435. x1, x2 = [a/2 + sqd/2, a/2 - sqd/2]
  436. # look for a solution A with depth 1
  437. for x in (x1, x2):
  438. A = sqrtdenest(sqrt(x))
  439. if sqrt_depth(A) > 1:
  440. continue
  441. Bn, Bd = rad_rationalize(b, _mexpand(2*A))
  442. B = Bn/Bd
  443. z = A + B*sqrt(r)
  444. if z < 0:
  445. z = -z
  446. return _mexpand(z)
  447. return None
  448. def _denester(nested, av0, h, max_depth_level):
  449. """Denests a list of expressions that contain nested square roots.
  450. Explanation
  451. ===========
  452. Algorithm based on <http://www.almaden.ibm.com/cs/people/fagin/symb85.pdf>.
  453. It is assumed that all of the elements of 'nested' share the same
  454. bottom-level radicand. (This is stated in the paper, on page 177, in
  455. the paragraph immediately preceding the algorithm.)
  456. When evaluating all of the arguments in parallel, the bottom-level
  457. radicand only needs to be denested once. This means that calling
  458. _denester with x arguments results in a recursive invocation with x+1
  459. arguments; hence _denester has polynomial complexity.
  460. However, if the arguments were evaluated separately, each call would
  461. result in two recursive invocations, and the algorithm would have
  462. exponential complexity.
  463. This is discussed in the paper in the middle paragraph of page 179.
  464. """
  465. from sympy.simplify.simplify import radsimp
  466. if h > max_depth_level:
  467. return None, None
  468. if av0[1] is None:
  469. return None, None
  470. if (av0[0] is None and
  471. all(n.is_Number for n in nested)): # no arguments are nested
  472. for f in _subsets(len(nested)): # test subset 'f' of nested
  473. p = _mexpand(Mul(*[nested[i] for i in range(len(f)) if f[i]]))
  474. if f.count(1) > 1 and f[-1]:
  475. p = -p
  476. sqp = sqrt(p)
  477. if sqp.is_Rational:
  478. return sqp, f # got a perfect square so return its square root.
  479. # Otherwise, return the radicand from the previous invocation.
  480. return sqrt(nested[-1]), [0]*len(nested)
  481. else:
  482. R = None
  483. if av0[0] is not None:
  484. values = [av0[:2]]
  485. R = av0[2]
  486. nested2 = [av0[3], R]
  487. av0[0] = None
  488. else:
  489. values = list(filter(None, [_sqrt_match(expr) for expr in nested]))
  490. for v in values:
  491. if v[2]: # Since if b=0, r is not defined
  492. if R is not None:
  493. if R != v[2]:
  494. av0[1] = None
  495. return None, None
  496. else:
  497. R = v[2]
  498. if R is None:
  499. # return the radicand from the previous invocation
  500. return sqrt(nested[-1]), [0]*len(nested)
  501. nested2 = [_mexpand(v[0]**2) -
  502. _mexpand(R*v[1]**2) for v in values] + [R]
  503. d, f = _denester(nested2, av0, h + 1, max_depth_level)
  504. if not f:
  505. return None, None
  506. if not any(f[i] for i in range(len(nested))):
  507. v = values[-1]
  508. return sqrt(v[0] + _mexpand(v[1]*d)), f
  509. else:
  510. p = Mul(*[nested[i] for i in range(len(nested)) if f[i]])
  511. v = _sqrt_match(p)
  512. if 1 in f and f.index(1) < len(nested) - 1 and f[len(nested) - 1]:
  513. v[0] = -v[0]
  514. v[1] = -v[1]
  515. if not f[len(nested)]: # Solution denests with square roots
  516. vad = _mexpand(v[0] + d)
  517. if vad <= 0:
  518. # return the radicand from the previous invocation.
  519. return sqrt(nested[-1]), [0]*len(nested)
  520. if not(sqrt_depth(vad) <= sqrt_depth(R) + 1 or
  521. (vad**2).is_Number):
  522. av0[1] = None
  523. return None, None
  524. sqvad = _sqrtdenest1(sqrt(vad), denester=False)
  525. if not (sqrt_depth(sqvad) <= sqrt_depth(R) + 1):
  526. av0[1] = None
  527. return None, None
  528. sqvad1 = radsimp(1/sqvad)
  529. res = _mexpand(sqvad/sqrt(2) + (v[1]*sqrt(R)*sqvad1/sqrt(2)))
  530. return res, f
  531. # sign(v[1])*sqrt(_mexpand(v[1]**2*R*vad1/2))), f
  532. else: # Solution requires a fourth root
  533. s2 = _mexpand(v[1]*R) + d
  534. if s2 <= 0:
  535. return sqrt(nested[-1]), [0]*len(nested)
  536. FR, s = root(_mexpand(R), 4), sqrt(s2)
  537. return _mexpand(s/(sqrt(2)*FR) + v[0]*FR/(sqrt(2)*s)), f
  538. def _sqrt_ratcomb(cs, args):
  539. """Denest rational combinations of radicals.
  540. Based on section 5 of [1].
  541. Examples
  542. ========
  543. >>> from sympy import sqrt
  544. >>> from sympy.simplify.sqrtdenest import sqrtdenest
  545. >>> z = sqrt(1+sqrt(3)) + sqrt(3+3*sqrt(3)) - sqrt(10+6*sqrt(3))
  546. >>> sqrtdenest(z)
  547. 0
  548. """
  549. from sympy.simplify.radsimp import radsimp
  550. # check if there exists a pair of sqrt that can be denested
  551. def find(a):
  552. n = len(a)
  553. for i in range(n - 1):
  554. for j in range(i + 1, n):
  555. s1 = a[i].base
  556. s2 = a[j].base
  557. p = _mexpand(s1 * s2)
  558. s = sqrtdenest(sqrt(p))
  559. if s != sqrt(p):
  560. return s, i, j
  561. indices = find(args)
  562. if indices is None:
  563. return Add(*[c * arg for c, arg in zip(cs, args)])
  564. s, i1, i2 = indices
  565. c2 = cs.pop(i2)
  566. args.pop(i2)
  567. a1 = args[i1]
  568. # replace a2 by s/a1
  569. cs[i1] += radsimp(c2 * s / a1.base)
  570. return _sqrt_ratcomb(cs, args)