sqrtdenest.py 21 KB

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