11@syms 𝑥
22@syms u[20 ]
33
4- mutable struct Transform
5- k:: Int
6- sub:: Dict
7- end
4+ transformer (eq) = transformer (ops (eq)... )
85
9- function next_variable! (f, eq)
10- μ = u[f. k]
11- f. k += 1
12- f. sub[μ] = eq
13- return μ
6+ function transformer (:: Mul , eq)
7+ return vcat ([transformer (t) for t in arguments (eq)]. .. )
148end
159
16- function transformer (eq:: SymbolicUtils.Add , f)
17- return sum (transformer (t, f) for t in arguments (eq); init = 0 )
18- end
19- function transformer (eq:: SymbolicUtils.Mul , f)
20- return prod (transformer (t, f) for t in arguments (eq); init = 1 )
21- end
22- function transformer (eq:: SymbolicUtils.Div , f)
23- return transformer (arguments (eq)[1 ], f) * transformer (arguments (eq)[2 ]^- 1 , f)
10+ function transformer (:: Div , eq)
11+ a = transformer (arguments (eq)[1 ])
12+ b = transformer (arguments (eq)[2 ])
13+ b = [(1 / q, k) for (q, k) in b]
14+ return [a; b]
2415end
2516
26- function transformer (eq :: SymbolicUtils. Pow , f )
17+ function transformer (:: Pow , eq )
2718 y, k = arguments (eq)
28-
29- if is_pos_int (k)
30- μ = next_variable! (f, y)
31- return μ ^ k
32- elseif is_neg_int (k)
33- μ = next_variable! (f, inv (y))
34- return μ ^- k
19+ if is_number (k)
20+ r = nice_parameter (k)
21+ if denominator (r) == 1
22+ return [(y, k)]
23+ else
24+ return [(y ^ ( 1 / denominator (r)), numerator (r))]
25+ end
3526 else
36- return next_variable! (f, y ^ k)
37- end
27+ return [(eq, 1 )]
28+ end
3829end
3930
40- function transformer (eq, f)
41- if isdependent (eq, 𝑥)
42- return next_variable! (f, eq)
43- else
44- return 1
45- end
31+ function transformer (:: Any , eq)
32+ return [(eq, 1 )]
4633end
4734
4835function transform (eq, x)
4936 eq = substitute (eq, Dict (x => 𝑥))
50- f = Transform (1 , Dict ())
51- q = transformer (eq, f)
52- if ! any (is_poly, values (f. sub))
53- q *= next_variable! (f, 1 )
54- end
55- return q, f. sub
37+ p = transformer (eq)
38+ p = p[isdependent .(first .(p), 𝑥)]
39+
40+ return p
41+ end
42+
43+ function rename_factors (p)
44+ n = length (p)
45+
46+ q = 1
47+ sub = Dict ()
48+ ks = Int[]
49+
50+ for (i,(y,k)) in enumerate (p)
51+ μ = u[i]
52+ q *= μ ^ k
53+ sub[μ] = y
54+ push! (ks, k)
55+ end
56+
57+ return q, sub, ks
5658end
5759
5860# #############################################################################
@@ -73,29 +75,34 @@ Symbolics.derivative(::typeof(Li), args::NTuple{1, Any}, ::Val{1}) = 1 / log(arg
7375
7476function substitute_x (eq, x, sub)
7577 eq = substitute (eq, sub)
76- substitute (eq, Dict (𝑥 => x))
78+ return substitute (eq, Dict (𝑥 => x))
7779end
7880
81+ guard_zero (x) = isequal (x, 0 ) ? one (x) : x
82+
7983function generate_homotopy (eq, x)
8084 eq = eq isa Num ? eq. val : eq
8185 x = x isa Num ? x. val : x
8286
83- q, sub = transform (eq, x)
87+ p = transform (eq, x)
88+ q, sub, ks = rename_factors (p)
8489 S = 0
8590
8691 for i in 1 : length (sub)
87- μ = u[i]
88- h₁, ∂h₁ = apply_partial_int_rules (sub[μ])
89- h₁ = substitute (h₁, Dict (si => Si, ci => Ci, ei => Ei, li => Li))
90- h₂ = expand_derivatives (Differential (μ)(q))
91-
92- h₁ = substitute_x (h₁, x, sub)
93- h₂ = substitute_x (h₂ * ∂h₁^- 1 , x, sub)
94-
95- S += expand ((1 + h₁) * (1 + h₂))
96- end
97-
98- unique ([one (x); [equivalent (t, x) for t in terms (S)]])
92+ μ = u[i]
93+ h₁, ∂h₁ = apply_partial_int_rules (sub[μ])
94+ h₁ = substitute (h₁, Dict (si => Si, ci => Ci, ei => Ei, li => Li))
95+ h₁ = substitute_x (h₁, x, sub)
96+
97+ for j = 1 : ks[i]
98+ h₂ = substitute_x ((q / μ^ j) / ∂h₁, x, sub)
99+ S += expand ((1 + h₁) * guard_zero (1 + h₂))
100+ end
101+ end
102+
103+ ζ = [x^ k for k= 1 : maximum (ks)+ 1 ]
104+
105+ unique ([one (x); ζ; [equivalent (t, x) for t in terms (S)]])
99106end
100107
101108# #############################################################################
@@ -105,6 +112,8 @@ function ∂(x)
105112 return isequal (d, 0 ) ? 1 : d
106113end
107114
115+ @syms 𝛷 (x)
116+
108117partial_int_rules = [
109118 # trigonometric functions
110119 @rule 𝛷 (sin (~ x)) => (cos (~ x) + si (~ x), ∂ (~ x))
@@ -121,19 +130,19 @@ partial_int_rules = [
121130 @rule 𝛷 (sech (~ x)) => (atan (sinh (~ x)), ∂ (~ x))
122131 @rule 𝛷 (coth (~ x)) => (log (sinh (~ x)), ∂ (~ x))
123132 # 1/trigonometric functions
124- @rule 𝛷 (^ ( sin (~ x), - 1 )) => (log (csc (~ x) + cot (~ x)), ∂ (~ x))
125- @rule 𝛷 (^ ( cos (~ x), - 1 )) => (log (sec (~ x) + tan (~ x)), ∂ (~ x))
126- @rule 𝛷 (^ ( tan (~ x), - 1 )) => (log (sin (~ x)), ∂ (~ x))
127- @rule 𝛷 (^ ( csc (~ x), - 1 )) => (cos (~ x), ∂ (~ x))
128- @rule 𝛷 (^ ( sec (~ x), - 1 )) => (sin (~ x), ∂ (~ x))
129- @rule 𝛷 (^ ( cot (~ x), - 1 )) => (log (cos (~ x)), ∂ (~ x))
133+ @rule 𝛷 (1 / sin (~ x)) => (log (csc (~ x) + cot ( ~ x)) + log ( sin (~ x)), ∂ (~ x))
134+ @rule 𝛷 (1 / cos (~ x)) => (log (sec (~ x) + tan ( ~ x)) + log ( cos (~ x)), ∂ (~ x))
135+ @rule 𝛷 (1 / tan (~ x)) => (log (sin ( ~ x)) + log ( tan (~ x)), ∂ (~ x))
136+ @rule 𝛷 (1 / csc (~ x)) => (cos (~ x) + log ( csc ( ~ x) ), ∂ (~ x))
137+ @rule 𝛷 (1 / sec (~ x)) => (sin (~ x) + log ( sec ( ~ x) ), ∂ (~ x))
138+ @rule 𝛷 (1 / cot (~ x)) => (log (cos ( ~ x)) + log ( cot (~ x)), ∂ (~ x))
130139 # 1/hyperbolic functions
131- @rule 𝛷 (^ ( sinh (~ x), - 1 )) => (log (tanh (~ x / 2 )), ∂ (~ x))
132- @rule 𝛷 (^ ( cosh (~ x), - 1 )) => (atan (sinh (~ x)), ∂ (~ x))
133- @rule 𝛷 (^ ( tanh (~ x), - 1 )) => (log (sinh (~ x)), ∂ (~ x))
134- @rule 𝛷 (^ ( csch (~ x), - 1 )) => (cosh (~ x), ∂ (~ x))
135- @rule 𝛷 (^ ( sech (~ x), - 1 )) => (sinh (~ x), ∂ (~ x))
136- @rule 𝛷 (^ ( coth (~ x), - 1 )) => (log (cosh (~ x)), ∂ (~ x))
140+ @rule 𝛷 (1 / sinh (~ x)) => (log (tanh (~ x / 2 )) + log ( sinh ( ~ x )), ∂ (~ x))
141+ @rule 𝛷 (1 / cosh (~ x)) => (atan (sinh ( ~ x)) + log ( cosh (~ x)), ∂ (~ x))
142+ @rule 𝛷 (1 / tanh (~ x)) => (log (sinh ( ~ x)) + log ( tanh (~ x)), ∂ (~ x))
143+ @rule 𝛷 (1 / csch (~ x)) => (cosh (~ x) + log ( csch ( ~ x) ), ∂ (~ x))
144+ @rule 𝛷 (1 / sech (~ x)) => (sinh (~ x) + log ( sech ( ~ x) ), ∂ (~ x))
145+ @rule 𝛷 (1 / coth (~ x)) => (log (cosh ( ~ x)) + log ( coth (~ x)), ∂ (~ x))
137146 # inverse trigonometric functions
138147 @rule 𝛷 (asin (~ x)) => (~ x * asin (~ x) + sqrt (1 - ~ x * ~ x), ∂ (~ x))
139148 @rule 𝛷 (acos (~ x)) => (~ x * acos (~ x) + sqrt (1 - ~ x * ~ x), ∂ (~ x))
@@ -152,23 +161,24 @@ partial_int_rules = [
152161 @rule 𝛷 (log (~ x)) => (~ x + ~ x * log (~ x) +
153162 sum (candidate_pow_minus (~ x, - 1 ); init = one (~ x)),
154163 ∂ (~ x))
155- @rule 𝛷 (^ ( log (~ x), - 1 )) => (log (log (~ x)) + li (~ x), ∂ (~ x))
164+ @rule 𝛷 (1 / log (~ x)) => (log (log (~ x)) + li (~ x), ∂ (~ x))
156165 @rule 𝛷 (exp (~ x)) => (exp (~ x) + ei (~ x), ∂ (~ x))
157166 @rule 𝛷 (^ (exp (~ x), ~ k:: is_neg )) => (^ (exp (- ~ x), - ~ k), ∂ (~ x))
158167 # square-root functions
159168 @rule 𝛷 (^ (~ x, ~ k:: is_abs_half )) => (sum (candidate_sqrt (~ x, ~ k);
160169 init = one (~ x)), 1 );
161- @rule 𝛷 (sqrt (~ x)) => (sum (candidate_sqrt (~ x, 0.5 ); init = one (~ x)), 1 );
162- @rule 𝛷 (^ ( sqrt (~ x), - 1 )) => 𝛷 ( ^ ( ~ x, - 0.5 ))
170+ @rule 𝛷 (sqrt (~ x)) => (sum (candidate_sqrt (~ x, 0.5 ); init = one (~ x)), ∂ ( ~ x) );
171+ @rule 𝛷 (1 / sqrt (~ x)) => ( sum ( candidate_sqrt ( ~ x, - 0.5 ); init = one ( ~ x)), ∂ ( ~ x));
163172 # rational functions
164- @rule 𝛷 (^ (~ x:: is_poly , ~ k:: is_neg )) => (sum (candidate_pow_minus (~ x,
165- ~ k);
173+ @rule 𝛷 (1 / ^ (~ x:: is_poly , ~ k:: is_pos_int )) => (sum (candidate_pow_minus (~ x, - ~ k);
174+ init = one (~ x)), 1 )
175+ @rule 𝛷 (1 / ~ x:: is_poly ) => (sum (candidate_pow_minus (~ x, - 1 );
166176 init = one (~ x)), 1 )
167177 @rule 𝛷 (^ (~ x, - 1 )) => (log (~ x), ∂ (~ x))
168178 @rule 𝛷 (^ (~ x, ~ k:: is_neg_int )) => (sum (^ (~ x, i) for i in (~ k + 1 ): - 1 ),
169179 ∂ (~ x))
170- @rule 𝛷 (1 / ~ x) => 𝛷 ( ^ (~ x, - 1 ))
171- @rule 𝛷 (^ (~ x, ~ k)) => (^ (~ x, ~ k + 1 ), ∂ (~ x))
180+ @rule 𝛷 (1 / ~ x) => ( log (~ x), ∂ ( ~ x ))
181+ @rule 𝛷 (^ (~ x, ~ k:: is_pos_int )) => (sum ( ^ (~ x, i + 1 ) for i = 1 : ~ k + 1 ), ∂ (~ x))
172182 @rule 𝛷 (1 ) => (𝑥, 1 )
173183 @rule 𝛷 (~ x) => ((~ x + ^ (~ x, 2 )), ∂ (~ x))]
174184
0 commit comments