o
    ohj                     @   s  d Z ddlmZ ddlmZ ddlmZ ddlmZ ddl	m
Z
mZmZmZ ddlmZmZ ddlmZ dd	lmZmZmZmZmZmZmZ d
d Zdd Zd)ddZdd Zd*ddZd+ddZ dd Z!dd Z"dd Z#dd  Z$d!d" Z%d#d$ Z&d,d%d&Z'd'd( Z(dS )-a  
Algorithms for solving the Risch differential equation.

Given a differential field K of characteristic 0 that is a simple
monomial extension of a base field k and f, g in K, the Risch
Differential Equation problem is to decide if there exist y in K such
that Dy + f*y == g and to find one if there are some.  If t is a
monomial over k and the coefficients of f and g are in k(t), then y is
in k(t), and the outline of the algorithm here is given as:

1. Compute the normal part n of the denominator of y.  The problem is
then reduced to finding y' in k<t>, where y == y'/n.
2. Compute the special part s of the denominator of y.   The problem is
then reduced to finding y'' in k[t], where y == y''/(n*s)
3. Bound the degree of y''.
4. Reduce the equation Dy + f*y == g to a similar equation with f, g in
k[t].
5. Find the solutions in k[t] of bounded degree of the reduced equation.

See Chapter 6 of "Symbolic Integration I: Transcendental Functions" by
Manuel Bronstein.  See also the docstring of risch.py.
    )mul)reduce)oo)Dummy)PolygcdZZcancel)imre)sqrt)gcdex_diophantinefrac_in
derivationsplitfactorNonElementaryIntegralExceptionDecrementLevelrecognize_log_derivativec                 C   s   | j rtS |t||kr| | d d S g }|}| |}d}|j r<|||f || }|d9 }| |}|j s%d}td|}t|dkri| }	||	d  }
| |
}|j rc||	d 7 }|
}t|dksI|S )aY  
    Computes the order of a at p, with respect to t.

    Explanation
    ===========

    For a, p in k[t], the order of a at p is defined as nu_p(a) = max({n
    in Z+ such that p**n|a}), where a != 0.  If a == 0, nu_p(a) = +oo.

    To compute the order at a rational function, a/b, use the fact that
    nu_p(a/b) == nu_p(a) - nu_p(b).
    r         )	is_zeror   r   as_polyETremappendlenpop)apt
power_listp1rtracks_powernproductfinalproductf r(   g/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/sympy/integrals/rde.pyorder_at)   s2   



r*   c                 C   s   | j rtS ||| | S )z
    Computes the order of a/d at oo (infinity), with respect to t.

    For f in k(t), the order or f at oo is defined as deg(d) - deg(a), where
    f == a/d.
    )r   r   degree)r   dr   r(   r(   r)   order_at_ooT   s   r-   Nc                    sF  |pt d}t| \}}t|| j}||}|t||t| j j j\}}	t| jt	    j
 j}
t|
|}
|
j|sgtd j|ffS dd |
 D }tt fdd|D td j}t	| }| ||  }|| }|j|dd\}}|||ffS )a  
    Weak normalization.

    Explanation
    ===========

    Given a derivation D on k[t] and f == a/d in k(t), return q in k[t]
    such that f - Dq/q is weakly normalized with respect to t.

    f in k(t) is said to be "weakly normalized" with respect to t if
    residue_p(f) is not a positive integer for any normal irreducible p
    in k[t] such that f is in R_p (Definition 6.1.1).  If f has an
    elementary integral, this is equivalent to no logarithm of
    integral(f) whose argument depends on t has a positive integer
    coefficient, where the arguments of the logarithms not in k(t) are
    in k[t].

    Returns (q, f - Dq/q)
    zr   c                 S   s    g | ]}|t v r|d kr|qS )r   )r   .0ir(   r(   r)   
<listcomp>   s     z#weak_normalizer.<locals>.<listcomp>c                    s,   g | ]}t t| jt   qS r(   )r   r   r   r   )r0   r$   DEr   d1r(   r)   r2      s   , Tinclude)r   r   r   diffr   quor   r   r   r   	resultantexprhas
real_rootsr   r   r	   )r   r,   r4   r.   dndsg
d_sqf_parta1br"   Nqdqsnsdr(   r3   r)   weak_normalizer`   s.   

"



rI   c                 C   s   t ||\}}t ||\}}||}	|||j|	|	|j}
||
 }||
 }||d r7t|| }|j|dd\}}||  |t|
| |  }|j|dd\}}|||f||f|
fS )a  
    Normal part of the denominator.

    Explanation
    ===========

    Given a derivation D on k[t] and f, g in k(t) with f weakly
    normalized with respect to t, either raise NonElementaryIntegralException,
    in which case the equation Dy + f*y == g has no solution in k(t), or the
    quadruplet (a, b, c, h) such that a, h in k[t], b, c in k<t>, and for any
    solution y in k(t) of Dy + f*y == g, q = y*h in k<t> satisfies
    a*Dq + b*q == c.

    This constitutes step 1 in the outline given in the rde.py docstring.
    r   Tr6   )	r   r   r8   r   r9   divr   r	   r   )fafdgagdr4   r>   r?   enesr   hr   ccacdbabdr(   r(   r)   normal_denom   s   
&rW   autoc                 C   sl  |dkr|j }|dkrt|j|j}n2|dkr#t|jd d |j}n"|dv r?| |}| |}	| ||	td|jfS td| t|||jt|||j }
t|||jt|||j }td|td|
 }|
svdd	lm	} |dkr|j
t|j|j}t|@ t|d |d | d |j\}}t||j\}}||||||}|d
ur|\}}}|dkrt||}W d
   n1 sw   Y  n|dkrv|j
t|jd d |j}t| tt|td |td | td |j\}}tt|td |td | td |j\}}t||j\}}ttd|j| ||rf||ttd|j | ||  || |||}|d
urf|\}}}|dkrft||}W d
   n	1 sqw   Y  td|
 || }|| }||  }| | }||| t||j|  t||| |  }|| | |}	|}|||	|fS )a  
    Special part of the denominator.

    Explanation
    ===========

    case is one of {'exp', 'tan', 'primitive'} for the hyperexponential,
    hypertangent, and primitive cases, respectively.  For the
    hyperexponential (resp. hypertangent) case, given a derivation D on
    k[t] and a in k[t], b, c, in k<t> with Dt/t in k (resp. Dt/(t**2 + 1) in
    k, sqrt(-1) not in k), a != 0, and gcd(a, t) == 1 (resp.
    gcd(a, t**2 + 1) == 1), return the quadruplet (A, B, C, 1/h) such that
    A, B, C, h in k[t] and for any solution q in k<t> of a*Dq + b*q == c,
    r = qh in k[t] satisfies A*Dr + B*r == C.

    For ``case == 'primitive'``, k<t> == k[t], so it returns (a, b, c, 1) in
    this case.

    This constitutes step 2 of the outline given in the rde.py docstring.
    rX   exptanr   r   )	primitivebasez@case must be one of {'exp', 'tan', 'primitive', 'base'}, not %s.r   parametric_log_derivN)caser   r   to_fieldr9   
ValueErrorr*   minprder^   r,   r   r   evalr
   r   r   r   maxr   )r   rU   rV   rS   rT   r4   r`   r   BCnbncr$   r^   dcoeffalphaaalphadetaaetadAQmr.   betaabetadrD   pNpnrQ   r(   r(   r)   special_denom   sj   
,




<<0




2rw   Fc              	      s  |dkr j }|  j}| j}|r!t fdd|D }n| j}t| j   |  j   }	|dkratd|t||d  }
||d kr_|	jr_td|	|| }
|
S |dkr||krrtd|| }
n	td|| d }
t	 j
 j jd  \}} j}t  t	|	 j\}}||d krddlm} z|||||fg \\}}}W n	 ty   Y nw t|dkrtd	t|
|d }
n||krQdd
lm} ||| }|duri|\}}|dkrq| t| | |||    | |    }t	| j\}}ddlm} z|||||fg \\}}}W n
 ty4   Y nEw t|dkr@td	t|
|d  }
W d   |
S W d   |
S W d   |
S W d   |
S W d   |
S W d   |
S W d   |
S 1 sw   Y  |
S |dkrddlm} td|t|| }
||krt	 j
t j j j jd  \}}t = t	|	 j\}}||||| }|dur|\} }}| dkrt|
|}
W d   |
S W d   |
S W d   |
S 1 sw   Y  |
S |dv rD j
 j} j
 }t|	| }	td|t|| d | }
||| d krB|	jrBtd|	|| }
|
S td| )am  
    Bound on polynomial solutions.

    Explanation
    ===========

    Given a derivation D on k[t] and ``a``, ``b``, ``c`` in k[t] with ``a != 0``, return
    n in ZZ such that deg(q) <= n for any solution q in k[t] of
    a*Dq + b*q == c, when parametric=False, or deg(q) <= n for any solution
    c1, ..., cm in Const(k) and q in k[t] of a*Dq + b*q == Sum(ci*gi, (i, 1, m))
    when parametric=True.

    For ``parametric=False``, ``cQ`` is ``c``, a ``Poly``; for ``parametric=True``, ``cQ`` is Q ==
    [q1, ..., qm], a list of Polys.

    This constitutes step 3 of the outline given in the rde.py docstring.
    rX   c                 3   s    | ]	}|  jV  qd S N)r+   r   r/   r4   r(   r)   	<genexpr>(  s    zbound_degree.<locals>.<genexpr>r\   r   r   r[   )limited_integratezLength of m should be 1!is_log_deriv_k_t_radical_in_fieldNrY   r]   )rZ   other_nonlinearzScase must be one of {'exp', 'tan', 'primitive', 'other_nonlinear', 'base'}, not %s.)r`   r+   r   rf   r	   r   LCas_expr
is_Integerr   r,   Tlevelr   rd   r{   r   r   rb   r}   r   r^   r9   r   )r   rC   cQr4   r`   
parametricdadbdcalphar$   rn   ro   t1rl   rm   r{   zazdrr   r}   rp   aar.   betars   rt   r^   deltalamr(   ry   r)   bound_degree  s   N






C
C
C
C
C
C
CC

,








r   c                 C   s  t d|j}t d|j}t d|j}	 |jr||d||fS |dk du r%t| |}||js2t| |||||} }}| |jdkr`| | }| | }|||||fS t	|| |\}	}
|t
| |7 }|
t
|	| }|| |j8 }|||	 7 }|| 9 }q)a  
    Rothstein's Special Polynomial Differential Equation algorithm.

    Explanation
    ===========

    Given a derivation D on k[t], an integer n and ``a``,``b``,``c`` in k[t] with
    ``a != 0``, either raise NonElementaryIntegralException, in which case the
    equation a*Dq + b*q == c has no solution of degree at most ``n`` in
    k[t], or return the tuple (B, C, m, alpha, beta) such that B, C,
    alpha, beta in k[t], m in ZZ, and any solution q in k[t] of degree
    at most n of a*Dq + b*q == c must be of the form
    q == alpha*h + beta, where h in k[t], deg(h) <= m, and Dh + B*h == C.

    This constitutes step 4 of the outline given in the rde.py docstring.
    r   r   T)r   r   r   r   r   r   r9   r+   ra   r   r   )r   rC   rR   r$   r4   zeror   r   r@   r"   r.   r(   r(   r)   spde  s.   
"r   c                 C   s   t d|j}|jsT||j| |j }d|  kr |ks#t tt ||j | |j  |j|  |jdd}|| }|d }|t|| | |  }|jr	|S )a  
    Poly Risch Differential Equation - No cancellation: deg(b) large enough.

    Explanation
    ===========

    Given a derivation D on k[t], ``n`` either an integer or +oo, and ``b``,``c``
    in k[t] with ``b != 0`` and either D == d/dt or
    deg(b) > max(0, deg(D) - 1), either raise NonElementaryIntegralException, in
    which case the equation ``Dq + b*q == c`` has no solution of degree at
    most n in k[t], or a solution q in k[t] of this equation with
    ``deg(q) < n``.
    r   Fexpandr   )r   r   r   r+   r   r   r   r   rC   rR   r$   r4   rE   rr   r   r(   r(   r)   no_cancel_b_large  s   .r   c                 C   sV  t d|j}|js|dkrd}n||j|j|j d }d|  kr*|ks-t t|dkrPt ||j ||j|j   |j|  |jdd}nC| |j||jkr^t| |jdkr}|| |j|j	d  ||j|j	d  fS t ||j | |j  |jdd}|| }|d }|t
|| | |  }|jr	|S )a  
    Poly Risch Differential Equation - No cancellation: deg(b) small enough.

    Explanation
    ===========

    Given a derivation D on k[t], ``n`` either an integer or +oo, and ``b``,``c``
    in k[t] with deg(b) < deg(D) - 1 and either D == d/dt or
    deg(D) >= 2, either raise NonElementaryIntegralException, in which case the
    equation Dq + b*q == c has no solution of degree at most n in k[t],
    or a solution q in k[t] of this equation with deg(q) <= n, or the
    tuple (h, b0, c0) such that h in k[t], b0, c0, in k, and for any
    solution q in k[t] of degree at most n of Dq + bq == c, y == q - h
    is a solution in k of Dy + b0*y == c0.
    r   r   Fr   )r   r   r   r+   r,   r   r   r   r   r   r   r   r(   r(   r)   no_cancel_b_small  s6   0$r   c           
      C   sp  t d|j}t| |j  |j|j  }|jr#|jr#|}nd}|jst	||
|j|j
|j d }d|  krE|ksHt tt||j|j  | |j  }|jre|||fS |dkrt ||j | |j|  |jdd}	n!|
|j|j
|jd krt||j | |j  }	||	 }|d }|t|	| | |	  }|jr(|S )a  
    Poly Risch Differential Equation - No cancellation: deg(b) == deg(D) - 1

    Explanation
    ===========

    Given a derivation D on k[t] with deg(D) >= 2, n either an integer
    or +oo, and b, c in k[t] with deg(b) == deg(D) - 1, either raise
    NonElementaryIntegralException, in which case the equation Dq + b*q == c has
    no solution of degree at most n in k[t], or a solution q in k[t] of
    this equation with deg(q) <= n, or the tuple (h, m, C) such that h
    in k[t], m in ZZ, and C in k[t], and for any solution q in k[t] of
    degree at most n of Dq + b*q == c, y == q - h is a solution in k[t]
    of degree at most m of Dy + b*y == C.
    r   r_   r   Fr   )r   r   r	   r   r   r,   r   is_positiver   rf   r+   r   r   )
rC   rR   r$   r4   rE   lcMrr   ur   r(   r(   r)   no_cancel_equal  s0   ($*
, r   c                 C   s^  ddl m} t|& t| |j\}}||||}|dur)|\}}|dkr)tdW d   n1 s3w   Y  |jr=|S |||jk rGtt	d|j}	|js||j}
||
k r\tt| t|
 |j\}}t|||||\}}W d   n1 sw   Y  t	| |  |j|
  |jdd}|	|7 }	|
d }|| | t|| 8 }|jrP|	S )a  
    Poly Risch Differential Equation - Cancellation: Primitive case.

    Explanation
    ===========

    Given a derivation D on k[t], n either an integer or +oo, ``b`` in k, and
    ``c`` in k[t] with Dt in k and ``b != 0``, either raise
    NonElementaryIntegralException, in which case the equation Dq + b*q == c
    has no solution of degree at most n in k[t], or a solution q in k[t] of
    this equation with deg(q) <= n.
    r   r|   Nz7is_deriv_in_field() is required to  solve this problem.r   Fr   )rd   r}   r   r   r   NotImplementedErrorr   r+   r   r   r   rischDEr   r   )rC   rR   r$   r4   r}   rU   rV   rp   r.   rE   rr   a2aa2dsarH   stmr(   r(   r)   cancel_primitive.  s:   

&r   c                 C   s  ddl m} |jt|j|j }t|1 t||j\}}t| |j\}}	|||	|||}
|
durA|
\}}}|dkrAt	dW d   n1 sKw   Y  |j
rU|S |||jk r_ttd|j}|j
s||j}||k rtt|  }t|6 t||j\}}|| || t||j  }|| }t| |j\}}t|||||\}}W d   n1 sw   Y  t| |  |j|  |jdd}||7 }|d }|| | t|| 8 }|j
rh|S )a  
    Poly Risch Differential Equation - Cancellation: Hyperexponential case.

    Explanation
    ===========

    Given a derivation D on k[t], n either an integer or +oo, ``b`` in k, and
    ``c`` in k[t] with Dt/t in k and ``b != 0``, either raise
    NonElementaryIntegralException, in which case the equation Dq + b*q == c
    has no solution of degree at most n in k[t], or a solution q in k[t] of
    this equation with deg(q) <= n.
    r   r]   Nz6is_deriv_in_field() is required to solve this problem.r   Fr   )rd   r^   r,   r9   r   r   r   r   r   r   r   r+   r   r   r   r   )rC   rR   r$   r4   r^   etarn   ro   rU   rV   rp   r   rr   r.   rE   rB   a1aa1dr   r   r   rH   r   r(   r(   r)   
cancel_exp`  sF   


&	r   c                 C   s  | j s0|jdks| |jtd|j|jd kr0|r)ddlm} || |||S t| |||S | j sB| |j|j|jd k r|jdksP|j|jdkr|r_ddlm	} || |||S t
| |||}t|trm|S |\}}	}
t|3 |	|j|
|j}	}
|	du rtd|
du rtd	t|	|
|||j}W d   || S 1 sw   Y  || S |j|jdkr| |j|j|jd kr|| |j  |j|j  kr| |j jstd
|rtdt| |||}t|tr|S |\}}}t| |||}|| S | j rtd|jdkr2|r+tdt| |||S |jdkrF|r?tdt| |||S td|j )a  
    Solve a Polynomial Risch Differential Equation with degree bound ``n``.

    This constitutes step 4 of the outline given in the rde.py docstring.

    For parametric=False, cQ is c, a Poly; for parametric=True, cQ is Q ==
    [q1, ..., qm], a list of Polys.
    r\   r   r   )prde_no_cancel_b_larger   )prde_no_cancel_b_smallNzb0 should be a non-Null valuezc0 should be a non-Null valuezResult should be a numberz0prde_no_cancel_b_equal() is not yet implemented.zWRemaining cases for Poly (P)RDE are not yet implemented (is_deriv_in_field() required).rY   zIParametric RDE cancellation hyperexponential case is not yet implemented.r[   zBParametric RDE cancellation primitive case is not yet implemented.zBOther Poly (P)RDE cancellation cases are not yet implemented (%s).)r   r`   r+   r   rf   r,   rd   r   r   r   r   
isinstancer   r   r   rb   solve_poly_rder   	is_number	TypeErrorr   r   r   r   )rC   r   r$   r4   r   r   r   RrQ   b0c0yrr   rh   r(   r(   r)   r     sf   
$$



4*
r   c                 C   s   t | ||\}\} }t| ||||\}\}}\}	}
}t||||	|
|\}}}}z	t||||}W n ty;   t}Y nw t|||||\}}}}}|jrO|}nt||||}|| | || fS )a  
    Solve a Risch Differential Equation: Dy + f*y == g.

    Explanation
    ===========

    See the outline in the docstring of rde.py for more information
    about the procedure used.  Either raise NonElementaryIntegralException, in
    which case there is no solution y in the given differential field,
    or return y in k(t) satisfying Dy + f*y == g, or raise
    NotImplementedError, in which case, the algorithms necessary to
    solve the given Risch Differential Equation have not yet been
    implemented.
    )	rI   rW   rw   r   r   r   r   r   r   )rK   rL   rM   rN   r4   _r   rU   rV   rS   rT   hnrp   rg   rh   hsr$   rr   r   r   r   r(   r(   r)   r     s    r   rx   )rX   )rX   F)F))__doc__operatorr   	functoolsr   
sympy.corer   sympy.core.symbolr   sympy.polysr   r   r   r	   $sympy.functions.elementary.complexesr
   r   (sympy.functions.elementary.miscellaneousr   sympy.integrals.rischr   r   r   r   r   r   r   r*   r-   rI   rW   rw   r   r   r   r   r   r   r   r   r   r(   r(   r(   r)   <module>   s.    $+
3
%
Tw///2
<]