text:
using Rubin
using Tests
using Elliptic
using HypergeometricFunctions
using Polylogarithms
using SpecialFunctions

@test integrate(x^5*(a+b*csch(c+d*x^2)), x) == :(1//6*a*x^6+b*d^-3*Polylogarithms.polylog(3,-1*exp(c+d*x^2))+-1*b*d^-3*Polylogarithms.polylog(3,exp(c+d*x^2))+b*d^-2*x^2*Polylogarithms.polylog(2,exp(c+d*x^2))+-1*b*d^-1*x^4*arctanh(exp(c+d*x^2))+-1*b*d^-2*x^2*Polylogarithms.polylog(2,-1*exp(c+d*x^2)))
@test integrate(x^3*(a+b*csch(c+d*x^2)), x) == :(1//4*a*x^4+(1/2)*b*d^-2*Polylogarithms.polylog(2,exp(c+d*x^2))+-1//2*b*d^-2*Polylogarithms.polylog(2,-1*exp(c+d*x^2))+-1*b*d^-1*x^2*arctanh(exp(c+d*x^2)))
@test integrate(x*(a+b*csch(c+d*x^2)), x) == :((1/2)*a*x^2+-1//2*b*d^-1*arctanh(cosh(c+d*x^2)))
@test integrate(x^5*(a+b*csch(c+d*x^2))^2, x) == :(1//6*a^2*x^6+(1/2)*b^2*d^-3*Polylogarithms.polylog(2,exp(2c+2*d*x^2))+-1//2*b^2*d^-1*x^4+b^2*d^-2*x^2*log(1+-1*exp(2c+2*d*x^2))+-2*a*b*d^-3*Polylogarithms.polylog(3,exp(c+d*x^2))+2*a*b*d^-3*Polylogarithms.polylog(3,-1*exp(c+d*x^2))+-1//2*b^2*d^-1*x^4*coth(c+d*x^2)+-2*a*b*d^-1*x^4*arctanh(exp(c+d*x^2))+-2*a*b*d^-2*x^2*Polylogarithms.polylog(2,-1*exp(c+d*x^2))+2*a*b*d^-2*x^2*Polylogarithms.polylog(2,exp(c+d*x^2)))
@test integrate(x^3*(a+b*csch(c+d*x^2))^2, x) == :(1//4*a^2*x^4+(1/2)*b^2*d^-2*log(sinh(c+d*x^2))+a*b*d^-2*Polylogarithms.polylog(2,exp(c+d*x^2))+-1*a*b*d^-2*Polylogarithms.polylog(2,-1*exp(c+d*x^2))+-1//2*b^2*d^-1*x^2*coth(c+d*x^2)+-2*a*b*d^-1*x^2*arctanh(exp(c+d*x^2)))
@test integrate(x*(a+b*csch(c+d*x^2))^2, x) == :((1/2)*a^2*x^2+-1//2*b^2*d^-1*coth(c+d*x^2)+-1*a*b*d^-1*arctanh(cosh(c+d*x^2)))
@test integrate(x*csch(a+b*x^2)^7, x) == :(5//32*b^-1*arctanh(cosh(a+b*x^2))+-5//32*b^-1*coth(a+b*x^2)*csch(a+b*x^2)+-1//12*b^-1*csch(a+b*x^2)^5*coth(a+b*x^2)+5//48*b^-1*csch(a+b*x^2)^3*coth(a+b*x^2))
@test integrate(x^5*(a+b*csch(c+d*x^2))^-1, x) == :(1//6*a^-1*x^6+b*a^-1*d^-3*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+-1*b*a^-1*d^-3*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+b*a^-1*d^-2*x^2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+(1/2)*b*a^-1*d^-1*x^4*(a^2+b^2)^-1//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+-1*b*a^-1*d^-2*x^2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+-1//2*b*a^-1*d^-1*x^4*(a^2+b^2)^-1//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^2)))
@test integrate(x^3*(a+b*csch(c+d*x^2))^-1, x) == :(1//4*a^-1*x^4+(1/2)*b*a^-1*d^-2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+-1//2*b*a^-1*d^-2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+(1/2)*b*a^-1*d^-1*x^2*(a^2+b^2)^-1//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+-1//2*b*a^-1*d^-1*x^2*(a^2+b^2)^-1//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^2)))
@test integrate(x*(a+b*csch(c+d*x^2))^-1, x) == :((1/2)*a^-1*x^2+b*a^-1*d^-1*(a^2+b^2)^-1//2*arctanh((a^2+b^2)^-1//2*(a+-1*b*tanh((1/2)*c+(1/2)*d*x^2))))
@test integrate(x^5*(a+b*csch(c+d*x^2))^-2, x) == :(1//6*a^-2*x^6+a^-2*b^2*d^-3*(a^2+b^2)^-1*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+a^-2*b^2*d^-3*(a^2+b^2)^-1*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+a^-2*b^3*d^-3*(a^2+b^2)^-3//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+-1*a^-2*b^3*d^-3*(a^2+b^2)^-3//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+-2*b*a^-2*d^-3*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+2*b*a^-2*d^-3*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+-1//2*a^-2*b^2*d^-1*x^4*(a^2+b^2)^-1+b*a^-2*d^-1*x^4*(a^2+b^2)^-1//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+a^-2*b^2*d^-2*x^2*(a^2+b^2)^-1*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+a^-2*b^2*d^-2*x^2*(a^2+b^2)^-1*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+a^-2*b^3*d^-2*x^2*(a^2+b^2)^-3//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+(1/2)*a^-2*b^3*d^-1*x^4*(a^2+b^2)^-3//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+-1*b*a^-2*d^-1*x^4*(a^2+b^2)^-1//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+-1*a^-2*b^3*d^-2*x^2*(a^2+b^2)^-3//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+-2*b*a^-2*d^-2*x^2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+2*b*a^-2*d^-2*x^2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+-1//2*a^-2*b^3*d^-1*x^4*(a^2+b^2)^-3//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+-1//2*a^-1*b^2*d^-1*x^4*(b+a*sinh(c+d*x^2))^-1*(a^2+b^2)^-1*cosh(c+d*x^2))
@test integrate(x^3*(a+b*csch(c+d*x^2))^-2, x) == :(1//4*a^-2*x^4+b*a^-2*d^-2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+(1/2)*a^-2*b^2*d^-2*(a^2+b^2)^-1*log(b+a*sinh(c+d*x^2))+(1/2)*a^-2*b^3*d^-2*(a^2+b^2)^-3//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+-1*b*a^-2*d^-2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+-1//2*a^-2*b^3*d^-2*(a^2+b^2)^-3//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+b*a^-2*d^-1*x^2*(a^2+b^2)^-1//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+(1/2)*a^-2*b^3*d^-1*x^2*(a^2+b^2)^-3//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+-1*b*a^-2*d^-1*x^2*(a^2+b^2)^-1//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+-1//2*a^-2*b^3*d^-1*x^2*(a^2+b^2)^-3//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^2))+-1//2*a^-1*b^2*d^-1*x^2*(b+a*sinh(c+d*x^2))^-1*(a^2+b^2)^-1*cosh(c+d*x^2))
@test integrate(x*(a+b*csch(c+d*x^2))^-2, x) == :((1/2)*a^-2*x^2+b*a^-2*d^-1*(a^2+b^2)^-3//2*(b^2+2*a^2)*arctanh((a^2+b^2)^-1//2*(a+-1*b*tanh((1/2)*c+(1/2)*d*x^2)))+-1//2*a^-1*b^2*d^-1*(a+b*csch(c+d*x^2))^-1*(a^2+b^2)^-1*coth(c+d*x^2))
@test integrate(x^3*(a+b*csch(c+d*x^(1/2))), x) == :(1//4*a*x^4+-10080*b*d^-8*Polylogarithms.polylog(8,-1*exp(c+d*x^(1/2)))+10080*b*d^-8*Polylogarithms.polylog(8,exp(c+d*x^(1/2)))+-10080*b*d^-7*x^(1/2)*Polylogarithms.polylog(7,exp(c+d*x^(1/2)))+-5040*b*x*d^-6*Polylogarithms.polylog(6,-1*exp(c+d*x^(1/2)))+-1680*b*d^-5*x^3//2*Polylogarithms.polylog(5,exp(c+d*x^(1/2)))+-420*b*d^-4*x^2*Polylogarithms.polylog(4,-1*exp(c+d*x^(1/2)))+-84*b*d^-3*x^5//2*Polylogarithms.polylog(3,exp(c+d*x^(1/2)))+-14*b*d^-2*x^3*Polylogarithms.polylog(2,-1*exp(c+d*x^(1/2)))+-4*b*d^-1*x^7//2*arctanh(exp(c+d*x^(1/2)))+14*b*d^-2*x^3*Polylogarithms.polylog(2,exp(c+d*x^(1/2)))+84*b*d^-3*x^5//2*Polylogarithms.polylog(3,-1*exp(c+d*x^(1/2)))+420*b*d^-4*x^2*Polylogarithms.polylog(4,exp(c+d*x^(1/2)))+1680*b*d^-5*x^3//2*Polylogarithms.polylog(5,-1*exp(c+d*x^(1/2)))+5040*b*x*d^-6*Polylogarithms.polylog(6,exp(c+d*x^(1/2)))+10080*b*d^-7*x^(1/2)*Polylogarithms.polylog(7,-1*exp(c+d*x^(1/2))))
@test integrate(x^2*(a+b*csch(c+d*x^(1/2))), x) == :(1//3*a*x^3+-240*b*d^-6*Polylogarithms.polylog(6,-1*exp(c+d*x^(1/2)))+240*b*d^-6*Polylogarithms.polylog(6,exp(c+d*x^(1/2)))+-240*b*d^-5*x^(1/2)*Polylogarithms.polylog(5,exp(c+d*x^(1/2)))+-120*b*x*d^-4*Polylogarithms.polylog(4,-1*exp(c+d*x^(1/2)))+-40*b*d^-3*x^3//2*Polylogarithms.polylog(3,exp(c+d*x^(1/2)))+-10*b*d^-2*x^2*Polylogarithms.polylog(2,-1*exp(c+d*x^(1/2)))+-4*b*d^-1*x^5//2*arctanh(exp(c+d*x^(1/2)))+10*b*d^-2*x^2*Polylogarithms.polylog(2,exp(c+d*x^(1/2)))+40*b*d^-3*x^3//2*Polylogarithms.polylog(3,-1*exp(c+d*x^(1/2)))+120*b*x*d^-4*Polylogarithms.polylog(4,exp(c+d*x^(1/2)))+240*b*d^-5*x^(1/2)*Polylogarithms.polylog(5,-1*exp(c+d*x^(1/2))))
@test integrate(x*(a+b*csch(c+d*x^(1/2))), x) == :((1/2)*a*x^2+-12*b*d^-4*Polylogarithms.polylog(4,-1*exp(c+d*x^(1/2)))+12*b*d^-4*Polylogarithms.polylog(4,exp(c+d*x^(1/2)))+-12*b*d^-3*x^(1/2)*Polylogarithms.polylog(3,exp(c+d*x^(1/2)))+-6*b*x*d^-2*Polylogarithms.polylog(2,-1*exp(c+d*x^(1/2)))+-4*b*d^-1*x^3//2*arctanh(exp(c+d*x^(1/2)))+6*b*x*d^-2*Polylogarithms.polylog(2,exp(c+d*x^(1/2)))+12*b*d^-3*x^(1/2)*Polylogarithms.polylog(3,-1*exp(c+d*x^(1/2))))
@test integrate(x^3*(a+b*csch(c+d*x^(1/2)))^2, x) == :(1//4*a^2*x^4+-2*b^2*d^-1*x^7//2+-315//2*b^2*d^-8*Polylogarithms.polylog(7,exp(2c+2*d*x^(1/2)))+-20160*a*b*d^-8*Polylogarithms.polylog(8,-1*exp(c+d*x^(1/2)))+-315*x*b^2*d^-6*Polylogarithms.polylog(5,exp(2c+2*d*x^(1/2)))+-105*b^2*d^-4*x^2*Polylogarithms.polylog(3,exp(2c+2*d*x^(1/2)))+-2*b^2*d^-1*x^7//2*coth(c+d*x^(1/2))+14*b^2*d^-2*x^3*log(1+-1*exp(2c+2*d*x^(1/2)))+42*b^2*d^-3*x^5//2*Polylogarithms.polylog(2,exp(2c+2*d*x^(1/2)))+210*b^2*d^-5*x^3//2*Polylogarithms.polylog(4,exp(2c+2*d*x^(1/2)))+315*b^2*d^-7*x^(1/2)*Polylogarithms.polylog(6,exp(2c+2*d*x^(1/2)))+20160*a*b*d^-8*Polylogarithms.polylog(8,exp(c+d*x^(1/2)))+-20160*a*b*d^-7*x^(1/2)*Polylogarithms.polylog(7,exp(c+d*x^(1/2)))+-10080*a*b*x*d^-6*Polylogarithms.polylog(6,-1*exp(c+d*x^(1/2)))+-3360*a*b*d^-5*x^3//2*Polylogarithms.polylog(5,exp(c+d*x^(1/2)))+-840*a*b*d^-4*x^2*Polylogarithms.polylog(4,-1*exp(c+d*x^(1/2)))+-168*a*b*d^-3*x^5//2*Polylogarithms.polylog(3,exp(c+d*x^(1/2)))+-28*a*b*d^-2*x^3*Polylogarithms.polylog(2,-1*exp(c+d*x^(1/2)))+-8*a*b*d^-1*x^7//2*arctanh(exp(c+d*x^(1/2)))+28*a*b*d^-2*x^3*Polylogarithms.polylog(2,exp(c+d*x^(1/2)))+168*a*b*d^-3*x^5//2*Polylogarithms.polylog(3,-1*exp(c+d*x^(1/2)))+840*a*b*d^-4*x^2*Polylogarithms.polylog(4,exp(c+d*x^(1/2)))+3360*a*b*d^-5*x^3//2*Polylogarithms.polylog(5,-1*exp(c+d*x^(1/2)))+10080*a*b*x*d^-6*Polylogarithms.polylog(6,exp(c+d*x^(1/2)))+20160*a*b*d^-7*x^(1/2)*Polylogarithms.polylog(7,-1*exp(c+d*x^(1/2))))
@test integrate(x^2*(a+b*csch(c+d*x^(1/2)))^2, x) == :(1//3*a^2*x^3+-15*b^2*d^-6*Polylogarithms.polylog(5,exp(2c+2*d*x^(1/2)))+-2*b^2*d^-1*x^5//2+-480*a*b*d^-6*Polylogarithms.polylog(6,-1*exp(c+d*x^(1/2)))+-30*x*b^2*d^-4*Polylogarithms.polylog(3,exp(2c+2*d*x^(1/2)))+-2*b^2*d^-1*x^5//2*coth(c+d*x^(1/2))+10*b^2*d^-2*x^2*log(1+-1*exp(2c+2*d*x^(1/2)))+20*b^2*d^-3*x^3//2*Polylogarithms.polylog(2,exp(2c+2*d*x^(1/2)))+30*b^2*d^-5*x^(1/2)*Polylogarithms.polylog(4,exp(2c+2*d*x^(1/2)))+480*a*b*d^-6*Polylogarithms.polylog(6,exp(c+d*x^(1/2)))+-480*a*b*d^-5*x^(1/2)*Polylogarithms.polylog(5,exp(c+d*x^(1/2)))+-240*a*b*x*d^-4*Polylogarithms.polylog(4,-1*exp(c+d*x^(1/2)))+-80*a*b*d^-3*x^3//2*Polylogarithms.polylog(3,exp(c+d*x^(1/2)))+-20*a*b*d^-2*x^2*Polylogarithms.polylog(2,-1*exp(c+d*x^(1/2)))+-8*a*b*d^-1*x^5//2*arctanh(exp(c+d*x^(1/2)))+20*a*b*d^-2*x^2*Polylogarithms.polylog(2,exp(c+d*x^(1/2)))+80*a*b*d^-3*x^3//2*Polylogarithms.polylog(3,-1*exp(c+d*x^(1/2)))+240*a*b*x*d^-4*Polylogarithms.polylog(4,exp(c+d*x^(1/2)))+480*a*b*d^-5*x^(1/2)*Polylogarithms.polylog(5,-1*exp(c+d*x^(1/2))))
@test integrate(x*(a+b*csch(c+d*x^(1/2)))^2, x) == :((1/2)*a^2*x^2+-3*b^2*d^-4*Polylogarithms.polylog(3,exp(2c+2*d*x^(1/2)))+-2*b^2*d^-1*x^3//2+-24*a*b*d^-4*Polylogarithms.polylog(4,-1*exp(c+d*x^(1/2)))+-2*b^2*d^-1*x^3//2*coth(c+d*x^(1/2))+6*x*b^2*d^-2*log(1+-1*exp(2c+2*d*x^(1/2)))+6*b^2*d^-3*x^(1/2)*Polylogarithms.polylog(2,exp(2c+2*d*x^(1/2)))+24*a*b*d^-4*Polylogarithms.polylog(4,exp(c+d*x^(1/2)))+-24*a*b*d^-3*x^(1/2)*Polylogarithms.polylog(3,exp(c+d*x^(1/2)))+-12*a*b*x*d^-2*Polylogarithms.polylog(2,-1*exp(c+d*x^(1/2)))+-8*a*b*d^-1*x^3//2*arctanh(exp(c+d*x^(1/2)))+12*a*b*x*d^-2*Polylogarithms.polylog(2,exp(c+d*x^(1/2)))+24*a*b*d^-3*x^(1/2)*Polylogarithms.polylog(3,-1*exp(c+d*x^(1/2))))
@test integrate(x^3*(a+b*csch(c+d*x^(1/2)))^-1, x) == :(1//4*a^-1*x^4+-10080*b*a^-1*d^-8*(a^2+b^2)^-1//2*Polylogarithms.polylog(8,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+10080*b*a^-1*d^-8*(a^2+b^2)^-1//2*Polylogarithms.polylog(8,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-10080*b*a^-1*d^-7*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(7,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-5040*b*x*a^-1*d^-6*(a^2+b^2)^-1//2*Polylogarithms.polylog(6,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-1680*b*a^-1*d^-5*x^3//2*(a^2+b^2)^-1//2*Polylogarithms.polylog(5,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-420*b*a^-1*d^-4*x^2*(a^2+b^2)^-1//2*Polylogarithms.polylog(4,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-84*b*a^-1*d^-3*x^5//2*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-14*b*a^-1*d^-2*x^3*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*b*a^-1*d^-1*x^7//2*(a^2+b^2)^-1//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+2*b*a^-1*d^-1*x^7//2*(a^2+b^2)^-1//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+14*b*a^-1*d^-2*x^3*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+84*b*a^-1*d^-3*x^5//2*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+420*b*a^-1*d^-4*x^2*(a^2+b^2)^-1//2*Polylogarithms.polylog(4,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+1680*b*a^-1*d^-5*x^3//2*(a^2+b^2)^-1//2*Polylogarithms.polylog(5,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+5040*b*x*a^-1*d^-6*(a^2+b^2)^-1//2*Polylogarithms.polylog(6,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+10080*b*a^-1*d^-7*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(7,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2))))
@test integrate(x^2*(a+b*csch(c+d*x^(1/2)))^-1, x) == :(1//3*a^-1*x^3+-240*b*a^-1*d^-6*(a^2+b^2)^-1//2*Polylogarithms.polylog(6,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+240*b*a^-1*d^-6*(a^2+b^2)^-1//2*Polylogarithms.polylog(6,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-240*b*a^-1*d^-5*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(5,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-120*b*x*a^-1*d^-4*(a^2+b^2)^-1//2*Polylogarithms.polylog(4,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-40*b*a^-1*d^-3*x^3//2*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-10*b*a^-1*d^-2*x^2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*b*a^-1*d^-1*x^5//2*(a^2+b^2)^-1//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+2*b*a^-1*d^-1*x^5//2*(a^2+b^2)^-1//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+10*b*a^-1*d^-2*x^2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+40*b*a^-1*d^-3*x^3//2*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+120*b*x*a^-1*d^-4*(a^2+b^2)^-1//2*Polylogarithms.polylog(4,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+240*b*a^-1*d^-5*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(5,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2))))
@test integrate(x*(a+b*csch(c+d*x^(1/2)))^-1, x) == :((1/2)*a^-1*x^2+-12*b*a^-1*d^-4*(a^2+b^2)^-1//2*Polylogarithms.polylog(4,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+12*b*a^-1*d^-4*(a^2+b^2)^-1//2*Polylogarithms.polylog(4,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-12*b*a^-1*d^-3*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-6*b*x*a^-1*d^-2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*b*a^-1*d^-1*x^3//2*(a^2+b^2)^-1//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+2*b*a^-1*d^-1*x^3//2*(a^2+b^2)^-1//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+6*b*x*a^-1*d^-2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+12*b*a^-1*d^-3*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2))))
@test integrate(x^3*(a+b*csch(c+d*x^(1/2)))^-2, x) == :(1//4*a^-2*x^4+-20160*b*a^-2*d^-8*(a^2+b^2)^-1//2*Polylogarithms.polylog(8,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-10080*a^-2*b^2*d^-8*(a^2+b^2)^-1*Polylogarithms.polylog(7,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-10080*a^-2*b^2*d^-8*(a^2+b^2)^-1*Polylogarithms.polylog(7,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-10080*a^-2*b^3*d^-8*(a^2+b^2)^-3//2*Polylogarithms.polylog(8,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*a^-2*b^2*d^-1*x^7//2*(a^2+b^2)^-1+10080*a^-2*b^3*d^-8*(a^2+b^2)^-3//2*Polylogarithms.polylog(8,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+20160*b*a^-2*d^-8*(a^2+b^2)^-1//2*Polylogarithms.polylog(8,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-20160*b*a^-2*d^-7*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(7,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-10080*b*x*a^-2*d^-6*(a^2+b^2)^-1//2*Polylogarithms.polylog(6,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-10080*a^-2*b^3*d^-7*x^(1/2)*(a^2+b^2)^-3//2*Polylogarithms.polylog(7,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-5040*x*a^-2*b^2*d^-6*(a^2+b^2)^-1*Polylogarithms.polylog(5,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-5040*x*a^-2*b^2*d^-6*(a^2+b^2)^-1*Polylogarithms.polylog(5,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-5040*x*a^-2*b^3*d^-6*(a^2+b^2)^-3//2*Polylogarithms.polylog(6,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-3360*b*a^-2*d^-5*x^3//2*(a^2+b^2)^-1//2*Polylogarithms.polylog(5,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-1680*a^-2*b^3*d^-5*x^3//2*(a^2+b^2)^-3//2*Polylogarithms.polylog(5,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-840*b*a^-2*d^-4*x^2*(a^2+b^2)^-1//2*Polylogarithms.polylog(4,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-420*a^-2*b^2*d^-4*x^2*(a^2+b^2)^-1*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-420*a^-2*b^2*d^-4*x^2*(a^2+b^2)^-1*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-420*a^-2*b^3*d^-4*x^2*(a^2+b^2)^-3//2*Polylogarithms.polylog(4,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-168*b*a^-2*d^-3*x^5//2*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-84*a^-2*b^3*d^-3*x^5//2*(a^2+b^2)^-3//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-28*b*a^-2*d^-2*x^3*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-14*a^-2*b^3*d^-2*x^3*(a^2+b^2)^-3//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-4*b*a^-2*d^-1*x^7//2*(a^2+b^2)^-1//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*a^-2*b^3*d^-1*x^7//2*(a^2+b^2)^-3//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+2*a^-2*b^3*d^-1*x^7//2*(a^2+b^2)^-3//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+4*b*a^-2*d^-1*x^7//2*(a^2+b^2)^-1//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+14*a^-2*b^2*d^-2*x^3*(a^2+b^2)^-1*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+14*a^-2*b^2*d^-2*x^3*(a^2+b^2)^-1*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+14*a^-2*b^3*d^-2*x^3*(a^2+b^2)^-3//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+28*b*a^-2*d^-2*x^3*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+84*a^-2*b^2*d^-3*x^5//2*(a^2+b^2)^-1*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+84*a^-2*b^2*d^-3*x^5//2*(a^2+b^2)^-1*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+84*a^-2*b^3*d^-3*x^5//2*(a^2+b^2)^-3//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+168*b*a^-2*d^-3*x^5//2*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+420*a^-2*b^3*d^-4*x^2*(a^2+b^2)^-3//2*Polylogarithms.polylog(4,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+840*b*a^-2*d^-4*x^2*(a^2+b^2)^-1//2*Polylogarithms.polylog(4,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+1680*a^-2*b^2*d^-5*x^3//2*(a^2+b^2)^-1*Polylogarithms.polylog(4,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+1680*a^-2*b^2*d^-5*x^3//2*(a^2+b^2)^-1*Polylogarithms.polylog(4,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+1680*a^-2*b^3*d^-5*x^3//2*(a^2+b^2)^-3//2*Polylogarithms.polylog(5,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+3360*b*a^-2*d^-5*x^3//2*(a^2+b^2)^-1//2*Polylogarithms.polylog(5,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+5040*x*a^-2*b^3*d^-6*(a^2+b^2)^-3//2*Polylogarithms.polylog(6,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+10080*b*x*a^-2*d^-6*(a^2+b^2)^-1//2*Polylogarithms.polylog(6,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+10080*a^-2*b^2*d^-7*x^(1/2)*(a^2+b^2)^-1*Polylogarithms.polylog(6,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+10080*a^-2*b^2*d^-7*x^(1/2)*(a^2+b^2)^-1*Polylogarithms.polylog(6,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+10080*a^-2*b^3*d^-7*x^(1/2)*(a^2+b^2)^-3//2*Polylogarithms.polylog(7,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+20160*b*a^-2*d^-7*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(7,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*a^-1*b^2*d^-1*x^7//2*(b+a*sinh(c+d*x^(1/2)))^-1*(a^2+b^2)^-1*cosh(c+d*x^(1/2)))
@test integrate(x^2*(a+b*csch(c+d*x^(1/2)))^-2, x) == :(1//3*a^-2*x^3+-480*b*a^-2*d^-6*(a^2+b^2)^-1//2*Polylogarithms.polylog(6,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-240*a^-2*b^2*d^-6*(a^2+b^2)^-1*Polylogarithms.polylog(5,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-240*a^-2*b^2*d^-6*(a^2+b^2)^-1*Polylogarithms.polylog(5,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-240*a^-2*b^3*d^-6*(a^2+b^2)^-3//2*Polylogarithms.polylog(6,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*a^-2*b^2*d^-1*x^5//2*(a^2+b^2)^-1+240*a^-2*b^3*d^-6*(a^2+b^2)^-3//2*Polylogarithms.polylog(6,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+480*b*a^-2*d^-6*(a^2+b^2)^-1//2*Polylogarithms.polylog(6,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-480*b*a^-2*d^-5*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(5,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-240*b*x*a^-2*d^-4*(a^2+b^2)^-1//2*Polylogarithms.polylog(4,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-240*a^-2*b^3*d^-5*x^(1/2)*(a^2+b^2)^-3//2*Polylogarithms.polylog(5,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-120*x*a^-2*b^2*d^-4*(a^2+b^2)^-1*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-120*x*a^-2*b^2*d^-4*(a^2+b^2)^-1*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-120*x*a^-2*b^3*d^-4*(a^2+b^2)^-3//2*Polylogarithms.polylog(4,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-80*b*a^-2*d^-3*x^3//2*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-40*a^-2*b^3*d^-3*x^3//2*(a^2+b^2)^-3//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-20*b*a^-2*d^-2*x^2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-10*a^-2*b^3*d^-2*x^2*(a^2+b^2)^-3//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-4*b*a^-2*d^-1*x^5//2*(a^2+b^2)^-1//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*a^-2*b^3*d^-1*x^5//2*(a^2+b^2)^-3//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+2*a^-2*b^3*d^-1*x^5//2*(a^2+b^2)^-3//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+4*b*a^-2*d^-1*x^5//2*(a^2+b^2)^-1//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+10*a^-2*b^2*d^-2*x^2*(a^2+b^2)^-1*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+10*a^-2*b^2*d^-2*x^2*(a^2+b^2)^-1*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+10*a^-2*b^3*d^-2*x^2*(a^2+b^2)^-3//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+20*b*a^-2*d^-2*x^2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+40*a^-2*b^2*d^-3*x^3//2*(a^2+b^2)^-1*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+40*a^-2*b^2*d^-3*x^3//2*(a^2+b^2)^-1*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+40*a^-2*b^3*d^-3*x^3//2*(a^2+b^2)^-3//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+80*b*a^-2*d^-3*x^3//2*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+120*x*a^-2*b^3*d^-4*(a^2+b^2)^-3//2*Polylogarithms.polylog(4,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+240*b*x*a^-2*d^-4*(a^2+b^2)^-1//2*Polylogarithms.polylog(4,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+240*a^-2*b^2*d^-5*x^(1/2)*(a^2+b^2)^-1*Polylogarithms.polylog(4,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+240*a^-2*b^2*d^-5*x^(1/2)*(a^2+b^2)^-1*Polylogarithms.polylog(4,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+240*a^-2*b^3*d^-5*x^(1/2)*(a^2+b^2)^-3//2*Polylogarithms.polylog(5,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+480*b*a^-2*d^-5*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(5,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*a^-1*b^2*d^-1*x^5//2*(b+a*sinh(c+d*x^(1/2)))^-1*(a^2+b^2)^-1*cosh(c+d*x^(1/2)))
@test integrate(x*(a+b*csch(c+d*x^(1/2)))^-2, x) == :((1/2)*a^-2*x^2+-24*b*a^-2*d^-4*(a^2+b^2)^-1//2*Polylogarithms.polylog(4,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-12*a^-2*b^2*d^-4*(a^2+b^2)^-1*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-12*a^-2*b^2*d^-4*(a^2+b^2)^-1*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-12*a^-2*b^3*d^-4*(a^2+b^2)^-3//2*Polylogarithms.polylog(4,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*a^-2*b^2*d^-1*x^3//2*(a^2+b^2)^-1+12*a^-2*b^3*d^-4*(a^2+b^2)^-3//2*Polylogarithms.polylog(4,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+24*b*a^-2*d^-4*(a^2+b^2)^-1//2*Polylogarithms.polylog(4,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-24*b*a^-2*d^-3*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-12*b*x*a^-2*d^-2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-12*a^-2*b^3*d^-3*x^(1/2)*(a^2+b^2)^-3//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-6*x*a^-2*b^3*d^-2*(a^2+b^2)^-3//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-4*b*a^-2*d^-1*x^3//2*(a^2+b^2)^-1//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*a^-2*b^3*d^-1*x^3//2*(a^2+b^2)^-3//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+2*a^-2*b^3*d^-1*x^3//2*(a^2+b^2)^-3//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+4*b*a^-2*d^-1*x^3//2*(a^2+b^2)^-1//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+6*x*a^-2*b^2*d^-2*(a^2+b^2)^-1*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+6*x*a^-2*b^2*d^-2*(a^2+b^2)^-1*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+6*x*a^-2*b^3*d^-2*(a^2+b^2)^-3//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+12*b*x*a^-2*d^-2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+12*a^-2*b^2*d^-3*x^(1/2)*(a^2+b^2)^-1*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+12*a^-2*b^2*d^-3*x^(1/2)*(a^2+b^2)^-1*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+12*a^-2*b^3*d^-3*x^(1/2)*(a^2+b^2)^-3//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+24*b*a^-2*d^-3*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*a^-1*b^2*d^-1*x^3//2*(b+a*sinh(c+d*x^(1/2)))^-1*(a^2+b^2)^-1*cosh(c+d*x^(1/2)))
@test integrate(x^3//2*(a+b*csch(c+d*x^(1/2))), x) == :(2//5*a*x^5//2+-48*b*d^-5*Polylogarithms.polylog(5,exp(c+d*x^(1/2)))+48*b*d^-5*Polylogarithms.polylog(5,-1*exp(c+d*x^(1/2)))+-48*b*d^-4*x^(1/2)*Polylogarithms.polylog(4,-1*exp(c+d*x^(1/2)))+-24*b*x*d^-3*Polylogarithms.polylog(3,exp(c+d*x^(1/2)))+-8*b*d^-2*x^3//2*Polylogarithms.polylog(2,-1*exp(c+d*x^(1/2)))+-4*b*d^-1*x^2*arctanh(exp(c+d*x^(1/2)))+8*b*d^-2*x^3//2*Polylogarithms.polylog(2,exp(c+d*x^(1/2)))+24*b*x*d^-3*Polylogarithms.polylog(3,-1*exp(c+d*x^(1/2)))+48*b*d^-4*x^(1/2)*Polylogarithms.polylog(4,exp(c+d*x^(1/2))))
@test integrate(x^(1/2)*(a+b*csch(c+d*x^(1/2))), x) == :(2//3*a*x^3//2+-4*b*d^-3*Polylogarithms.polylog(3,exp(c+d*x^(1/2)))+4*b*d^-3*Polylogarithms.polylog(3,-1*exp(c+d*x^(1/2)))+-4*b*x*d^-1*arctanh(exp(c+d*x^(1/2)))+-4*b*d^-2*x^(1/2)*Polylogarithms.polylog(2,-1*exp(c+d*x^(1/2)))+4*b*d^-2*x^(1/2)*Polylogarithms.polylog(2,exp(c+d*x^(1/2))))
@test integrate(x^-1//2*(a+b*csch(c+d*x^(1/2))), x) == :(2*a*x^(1/2)+-2*b*d^-1*arctanh(cosh(c+d*x^(1/2))))
@test integrate(x^3//2*(a+b*csch(c+d*x^(1/2)))^2, x) == :(2//5*a^2*x^5//2+-2*b^2*d^-1*x^2+6*b^2*d^-5*Polylogarithms.polylog(4,exp(2c+2*d*x^(1/2)))+-96*a*b*d^-5*Polylogarithms.polylog(5,exp(c+d*x^(1/2)))+-12*b^2*d^-4*x^(1/2)*Polylogarithms.polylog(3,exp(2c+2*d*x^(1/2)))+-2*b^2*d^-1*x^2*coth(c+d*x^(1/2))+8*b^2*d^-2*x^3//2*log(1+-1*exp(2c+2*d*x^(1/2)))+12*x*b^2*d^-3*Polylogarithms.polylog(2,exp(2c+2*d*x^(1/2)))+96*a*b*d^-5*Polylogarithms.polylog(5,-1*exp(c+d*x^(1/2)))+-96*a*b*d^-4*x^(1/2)*Polylogarithms.polylog(4,-1*exp(c+d*x^(1/2)))+-48*a*b*x*d^-3*Polylogarithms.polylog(3,exp(c+d*x^(1/2)))+-16*a*b*d^-2*x^3//2*Polylogarithms.polylog(2,-1*exp(c+d*x^(1/2)))+-8*a*b*d^-1*x^2*arctanh(exp(c+d*x^(1/2)))+16*a*b*d^-2*x^3//2*Polylogarithms.polylog(2,exp(c+d*x^(1/2)))+48*a*b*x*d^-3*Polylogarithms.polylog(3,-1*exp(c+d*x^(1/2)))+96*a*b*d^-4*x^(1/2)*Polylogarithms.polylog(4,exp(c+d*x^(1/2))))
@test integrate(x^(1/2)*(a+b*csch(c+d*x^(1/2)))^2, x) == :(2//3*a^2*x^3//2+-2*x*b^2*d^-1+2*b^2*d^-3*Polylogarithms.polylog(2,exp(2c+2*d*x^(1/2)))+-8*a*b*d^-3*Polylogarithms.polylog(3,exp(c+d*x^(1/2)))+-2*x*b^2*d^-1*coth(c+d*x^(1/2))+4*b^2*d^-2*x^(1/2)*log(1+-1*exp(2c+2*d*x^(1/2)))+8*a*b*d^-3*Polylogarithms.polylog(3,-1*exp(c+d*x^(1/2)))+-8*a*b*x*d^-1*arctanh(exp(c+d*x^(1/2)))+-8*a*b*d^-2*x^(1/2)*Polylogarithms.polylog(2,-1*exp(c+d*x^(1/2)))+8*a*b*d^-2*x^(1/2)*Polylogarithms.polylog(2,exp(c+d*x^(1/2))))
@test integrate(x^-1//2*(a+b*csch(c+d*x^(1/2)))^2, x) == :(2*a^2*x^(1/2)+-2*b^2*d^-1*coth(c+d*x^(1/2))+-4*a*b*d^-1*arctanh(cosh(c+d*x^(1/2))))
@test integrate(x^3//2*(a+b*csch(c+d*x^(1/2)))^-1, x) == :(2//5*a^-1*x^5//2+-48*b*a^-1*d^-5*(a^2+b^2)^-1//2*Polylogarithms.polylog(5,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+48*b*a^-1*d^-5*(a^2+b^2)^-1//2*Polylogarithms.polylog(5,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-48*b*a^-1*d^-4*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(4,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-24*b*x*a^-1*d^-3*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-8*b*a^-1*d^-2*x^3//2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*b*a^-1*d^-1*x^2*(a^2+b^2)^-1//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+2*b*a^-1*d^-1*x^2*(a^2+b^2)^-1//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+8*b*a^-1*d^-2*x^3//2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+24*b*x*a^-1*d^-3*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+48*b*a^-1*d^-4*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(4,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2))))
@test integrate(x^(1/2)*(a+b*csch(c+d*x^(1/2)))^-1, x) == :(2//3*a^-1*x^3//2+-4*b*a^-1*d^-3*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+4*b*a^-1*d^-3*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-4*b*a^-1*d^-2*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*b*x*a^-1*d^-1*(a^2+b^2)^-1//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+2*b*x*a^-1*d^-1*(a^2+b^2)^-1//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+4*b*a^-1*d^-2*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2))))
@test integrate(x^-1//2*(a+b*csch(c+d*x^(1/2)))^-1, x) == :(2*a^-1*x^(1/2)+4*b*a^-1*d^-1*(a^2+b^2)^-1//2*arctanh((a^2+b^2)^-1//2*(a+-1*b*tanh((1/2)*c+(1/2)*d*x^(1/2)))))
@test integrate(x^3//2*(a+b*csch(c+d*x^(1/2)))^-2, x) == :(2//5*a^-2*x^5//2+-96*b*a^-2*d^-5*(a^2+b^2)^-1//2*Polylogarithms.polylog(5,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-48*a^-2*b^3*d^-5*(a^2+b^2)^-3//2*Polylogarithms.polylog(5,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*a^-2*b^2*d^-1*x^2*(a^2+b^2)^-1+48*a^-2*b^2*d^-5*(a^2+b^2)^-1*Polylogarithms.polylog(4,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+48*a^-2*b^2*d^-5*(a^2+b^2)^-1*Polylogarithms.polylog(4,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+48*a^-2*b^3*d^-5*(a^2+b^2)^-3//2*Polylogarithms.polylog(5,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+96*b*a^-2*d^-5*(a^2+b^2)^-1//2*Polylogarithms.polylog(5,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-96*b*a^-2*d^-4*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(4,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-48*b*x*a^-2*d^-3*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-48*a^-2*b^2*d^-4*x^(1/2)*(a^2+b^2)^-1*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-48*a^-2*b^2*d^-4*x^(1/2)*(a^2+b^2)^-1*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-48*a^-2*b^3*d^-4*x^(1/2)*(a^2+b^2)^-3//2*Polylogarithms.polylog(4,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-24*x*a^-2*b^3*d^-3*(a^2+b^2)^-3//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-16*b*a^-2*d^-2*x^3//2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-8*a^-2*b^3*d^-2*x^3//2*(a^2+b^2)^-3//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-4*b*a^-2*d^-1*x^2*(a^2+b^2)^-1//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*a^-2*b^3*d^-1*x^2*(a^2+b^2)^-3//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+2*a^-2*b^3*d^-1*x^2*(a^2+b^2)^-3//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+4*b*a^-2*d^-1*x^2*(a^2+b^2)^-1//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+8*a^-2*b^2*d^-2*x^3//2*(a^2+b^2)^-1*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+8*a^-2*b^2*d^-2*x^3//2*(a^2+b^2)^-1*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+8*a^-2*b^3*d^-2*x^3//2*(a^2+b^2)^-3//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+16*b*a^-2*d^-2*x^3//2*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+24*x*a^-2*b^2*d^-3*(a^2+b^2)^-1*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+24*x*a^-2*b^2*d^-3*(a^2+b^2)^-1*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+24*x*a^-2*b^3*d^-3*(a^2+b^2)^-3//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+48*b*x*a^-2*d^-3*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+48*a^-2*b^3*d^-4*x^(1/2)*(a^2+b^2)^-3//2*Polylogarithms.polylog(4,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+96*b*a^-2*d^-4*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(4,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*a^-1*b^2*d^-1*x^2*(b+a*sinh(c+d*x^(1/2)))^-1*(a^2+b^2)^-1*cosh(c+d*x^(1/2)))
@test integrate(x^(1/2)*(a+b*csch(c+d*x^(1/2)))^-2, x) == :(2//3*a^-2*x^3//2+-8*b*a^-2*d^-3*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-4*a^-2*b^3*d^-3*(a^2+b^2)^-3//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*x*a^-2*b^2*d^-1*(a^2+b^2)^-1+4*a^-2*b^2*d^-3*(a^2+b^2)^-1*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+4*a^-2*b^2*d^-3*(a^2+b^2)^-1*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+4*a^-2*b^3*d^-3*(a^2+b^2)^-3//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+8*b*a^-2*d^-3*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-8*b*a^-2*d^-2*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-4*b*x*a^-2*d^-1*(a^2+b^2)^-1//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-4*a^-2*b^3*d^-2*x^(1/2)*(a^2+b^2)^-3//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*x*a^-2*b^3*d^-1*(a^2+b^2)^-3//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+2*x*a^-2*b^3*d^-1*(a^2+b^2)^-3//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+4*b*x*a^-2*d^-1*(a^2+b^2)^-1//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+4*a^-2*b^2*d^-2*x^(1/2)*(a^2+b^2)^-1*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+4*a^-2*b^2*d^-2*x^(1/2)*(a^2+b^2)^-1*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+4*a^-2*b^3*d^-2*x^(1/2)*(a^2+b^2)^-3//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+8*b*a^-2*d^-2*x^(1/2)*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^(1/2)))+-2*x*a^-1*b^2*d^-1*(b+a*sinh(c+d*x^(1/2)))^-1*(a^2+b^2)^-1*cosh(c+d*x^(1/2)))
@test integrate(x^-1//2*(a+b*csch(c+d*x^(1/2)))^-2, x) == :(2*a^-2*x^(1/2)+-2*a^-1*b^2*d^-1*(a+b*csch(c+d*x^(1/2)))^-1*(a^2+b^2)^-1*coth(c+d*x^(1/2))+4*b*a^-2*d^-1*(a^2+b^2)^-3//2*(b^2+2*a^2)*arctanh((a^2+b^2)^-1//2*(a+-1*b*tanh((1/2)*c+(1/2)*d*x^(1/2)))))
@test integrate((e*x)^(-1+n)*(a+b*csch(c+d*x^n)), x) == :(a*e^-1*n^-1*(e*x)^n+-1*b*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^n*arctanh(cosh(c+d*x^n)))
@test integrate((e*x)^(-1+2n)*(a+b*csch(c+d*x^n)), x) == :((1/2)*a*e^-1*n^-1*(e*x)^(2n)+b*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(2n)*Polylogarithms.polylog(2,exp(c+d*x^n))+-1*b*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(2n)*Polylogarithms.polylog(2,-1*exp(c+d*x^n))+-2*b*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(2n)*arctanh(exp(c+d*x^n)))
@test integrate((e*x)^(-1+3n)*(a+b*csch(c+d*x^n)), x) == :(1//3*a*e^-1*n^-1*(e*x)^(3n)+-2*b*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(3n)*arctanh(exp(c+d*x^n))+-2*b*d^-3*e^-1*n^-1*x^(-3n)*(e*x)^(3n)*Polylogarithms.polylog(3,exp(c+d*x^n))+-2*b*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(3n)*Polylogarithms.polylog(2,-1*exp(c+d*x^n))+2*b*d^-3*e^-1*n^-1*x^(-3n)*(e*x)^(3n)*Polylogarithms.polylog(3,-1*exp(c+d*x^n))+2*b*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(3n)*Polylogarithms.polylog(2,exp(c+d*x^n)))
@test integrate((e*x)^(-1+n)*(a+b*csch(c+d*x^n))^2, x) == :(a^2*e^-1*n^-1*(e*x)^n+-1*b^2*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^n*coth(c+d*x^n)+-2*a*b*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^n*arctanh(cosh(c+d*x^n)))
@test integrate((e*x)^(-1+2n)*(a+b*csch(c+d*x^n))^2, x) == :((1/2)*a^2*e^-1*n^-1*(e*x)^(2n)+b^2*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(2n)*log(sinh(c+d*x^n))+-1*b^2*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(2n)*coth(c+d*x^n)+-4*a*b*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(2n)*arctanh(exp(c+d*x^n))+-2*a*b*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(2n)*Polylogarithms.polylog(2,-1*exp(c+d*x^n))+2*a*b*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(2n)*Polylogarithms.polylog(2,exp(c+d*x^n)))
@test integrate((e*x)^(-1+3n)*(a+b*csch(c+d*x^n))^2, x) == :(1//3*a^2*e^-1*n^-1*(e*x)^(3n)+-1*b^2*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(3n)+b^2*d^-3*e^-1*n^-1*x^(-3n)*(e*x)^(3n)*Polylogarithms.polylog(2,exp(2c+2*d*x^n))+-1*b^2*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(3n)*coth(c+d*x^n)+2*b^2*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(3n)*log(1+-1*exp(2c+2*d*x^n))+-4*a*b*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(3n)*arctanh(exp(c+d*x^n))+-4*a*b*d^-3*e^-1*n^-1*x^(-3n)*(e*x)^(3n)*Polylogarithms.polylog(3,exp(c+d*x^n))+-4*a*b*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(3n)*Polylogarithms.polylog(2,-1*exp(c+d*x^n))+4*a*b*d^-3*e^-1*n^-1*x^(-3n)*(e*x)^(3n)*Polylogarithms.polylog(3,-1*exp(c+d*x^n))+4*a*b*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(3n)*Polylogarithms.polylog(2,exp(c+d*x^n)))
@test integrate((e*x)^(-1+n)*(a+b*csch(c+d*x^n))^-1, x) == :(a^-1*e^-1*n^-1*(e*x)^n+2*b*a^-1*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^n*(a^2+b^2)^-1//2*arctanh((a^2+b^2)^-1//2*(a+-1*b*tanh((1/2)*c+(1/2)*d*x^n))))
@test integrate((e*x)^(-1+2n)*(a+b*csch(c+d*x^n))^-1, x) == :((1/2)*a^-1*e^-1*n^-1*(e*x)^(2n)+b*a^-1*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(2n)*(a^2+b^2)^-1//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+b*a^-1*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(2n)*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+-1*b*a^-1*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(2n)*(a^2+b^2)^-1//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+-1*b*a^-1*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(2n)*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^n)))
@test integrate((e*x)^(-1+3n)*(a+b*csch(c+d*x^n))^-1, x) == :(1//3*a^-1*e^-1*n^-1*(e*x)^(3n)+b*a^-1*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(3n)*(a^2+b^2)^-1//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+-1*b*a^-1*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(3n)*(a^2+b^2)^-1//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+-2*b*a^-1*d^-3*e^-1*n^-1*x^(-3n)*(e*x)^(3n)*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+-2*b*a^-1*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(3n)*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+2*b*a^-1*d^-3*e^-1*n^-1*x^(-3n)*(e*x)^(3n)*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+2*b*a^-1*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(3n)*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^n)))
@test integrate((e*x)^(-1+n)*(a+b*csch(c+d*x^n))^-2, x) == :(a^-2*e^-1*n^-1*(e*x)^n+-1*a^-1*b^2*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^n*(a+b*csch(c+d*x^n))^-1*(a^2+b^2)^-1*coth(c+d*x^n)+2*b*a^-2*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^n*(a^2+b^2)^-3//2*(b^2+2*a^2)*arctanh((a^2+b^2)^-1//2*(a+-1*b*tanh((1/2)*c+(1/2)*d*x^n))))
@test integrate((e*x)^(-1+2n)*(a+b*csch(c+d*x^n))^-2, x) == :((1/2)*a^-2*e^-1*n^-1*(e*x)^(2n)+a^-2*b^2*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(2n)*(a^2+b^2)^-1*log(b+a*sinh(c+d*x^n))+a^-2*b^3*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(2n)*(a^2+b^2)^-3//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+a^-2*b^3*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(2n)*(a^2+b^2)^-3//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+-1*a^-2*b^3*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(2n)*(a^2+b^2)^-3//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+-1*a^-2*b^3*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(2n)*(a^2+b^2)^-3//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+-2*b*a^-2*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(2n)*(a^2+b^2)^-1//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+-2*b*a^-2*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(2n)*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+2*b*a^-2*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(2n)*(a^2+b^2)^-1//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+2*b*a^-2*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(2n)*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+-1*a^-1*b^2*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(2n)*(b+a*sinh(c+d*x^n))^-1*(a^2+b^2)^-1*cosh(c+d*x^n))
@test integrate((e*x)^(-1+3n)*(a+b*csch(c+d*x^n))^-2, x) == :(1//3*a^-2*e^-1*n^-1*(e*x)^(3n)+-1*a^-2*b^2*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(3n)*(a^2+b^2)^-1+a^-2*b^3*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(3n)*(a^2+b^2)^-3//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+-1*a^-2*b^3*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(3n)*(a^2+b^2)^-3//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+-4*b*a^-2*d^-3*e^-1*n^-1*x^(-3n)*(e*x)^(3n)*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+-4*b*a^-2*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(3n)*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+-2*b*a^-2*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(3n)*(a^2+b^2)^-1//2*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+-2*a^-2*b^3*d^-3*e^-1*n^-1*x^(-3n)*(e*x)^(3n)*(a^2+b^2)^-3//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+-2*a^-2*b^3*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(3n)*(a^2+b^2)^-3//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+2*b*a^-2*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(3n)*(a^2+b^2)^-1//2*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+2*a^-2*b^2*d^-3*e^-1*n^-1*x^(-3n)*(e*x)^(3n)*(a^2+b^2)^-1*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+2*a^-2*b^2*d^-3*e^-1*n^-1*x^(-3n)*(e*x)^(3n)*(a^2+b^2)^-1*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+2*a^-2*b^2*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(3n)*(a^2+b^2)^-1*log(1+a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+2*a^-2*b^2*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(3n)*(a^2+b^2)^-1*log(1+a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+2*a^-2*b^3*d^-3*e^-1*n^-1*x^(-3n)*(e*x)^(3n)*(a^2+b^2)^-3//2*Polylogarithms.polylog(3,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+2*a^-2*b^3*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(3n)*(a^2+b^2)^-3//2*Polylogarithms.polylog(2,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+4*b*a^-2*d^-3*e^-1*n^-1*x^(-3n)*(e*x)^(3n)*(a^2+b^2)^-1//2*Polylogarithms.polylog(3,-1*a*(b+-1*(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+4*b*a^-2*d^-2*e^-1*n^-1*x^(-2n)*(e*x)^(3n)*(a^2+b^2)^-1//2*Polylogarithms.polylog(2,-1*a*(b+(a^2+b^2)^(1/2))^-1*exp(c+d*x^n))+-1*a^-1*b^2*d^-1*e^-1*n^-1*x^(-1n)*(e*x)^(3n)*(b+a*sinh(c+d*x^n))^-1*(a^2+b^2)^-1*cosh(c+d*x^n))

max_stars_repo_path: test/6 Hyperbolic functions/6.6 Hyperbolic cosecant/6.6.2 (e x)^m (a+b csch(c+d x^n))^p.jl


text:
using FirstPassageTools
using Test
using CSV
using DataFrames
using Distributions
using StaticArrays

T = [-1 1.0; 1 -2]
A = [0 1.0]
p0 = [1.0, 0]

@testset "Testing setup" begin
    Ttest, Atest = setup("goodtest.csv")
    @test isapprox(Ttest, [-3.0 0; 3 -3])
    @test isapprox(Atest, [0 3.0])
    @test_throws AssertionError setup("badtest.csv")
end

@testset "Tests of rescale!()" begin
    # Test with T and A matrices
    Tcopy = deepcopy(T)
    Acopy = deepcopy(A)
    Tcorr = [-2.0 2; 2 -4]
    Acorr = [0 2.0]
    Ttest = rescale!(Tcopy, 2.0)
    Atest = rescale!(Acopy, 2.0)
    @test isapprox(Tcorr, Ttest)
    @test isapprox(Acorr, Atest)

    # Test with full W-matrix
    Wtest = cat(Tcopy, Acopy, dims=1)
    Wtest = hcat(Wtest, zeros(size(Wtest, 1)))
    @test isapprox(3 * Wtest, rescale!(Wtest, 3))
end

@testset "Tests for building an fpdistribution" begin
    # Should pass:
    @test_nowarn fpdistribution(T, A, p0)

    # Should fail:
    Tbad = [-1 1.0; 1 -1]
    Abad = [0 1.1]
    p0bad = [1.0, 0.1]
    @test_throws AssertionError fpdistribution(Tbad, A, p0)
    @test_throws AssertionError fpdistribution(T, Abad, p0)
    @test_throws AssertionError fpdistribution(T, A, p0bad)
    @test_throws AssertionError fpdistribution(T, A, [1.0])
end

@testset "Erlang distribution tests" begin
    # goodtest system should be equivalent to an Erlang distribution with 2 transient
    # states and a scale parameter equal to 1/(total # states)
    erl = Erlang(2, 1/3)
    Terl, Aerl = setup("goodtest.csv")
    p0 = [1.0, 0]
    fperl = fpdistribution(Terl, Aerl, p0)
    times = Array(0.0:5:20)

    @test all(isapprox.(pdf.(erl, times), pdf.(fperl, times)))
    @test all(isapprox.(logpdf.(erl, times), logpdf.(fperl, times)))
    @test all(isapprox.(cdf.(erl, times), cdf.(fperl, times)))
    # Using a looser tolerance for this test because the quantile fn. for fpdistribution
    # relies on numerical root finding
    qtiles = Array(0:0.1:0.9)
    @test all(isapprox.(quantile.(erl, qtiles), quantile.(fperl, qtiles), atol=1e-6))
    @test isapprox(mean(erl), mean(fperl))
    @test isapprox(var(erl), var(fperl))
end

@testset "Multiple absorbing states" begin
    Tm, Am = setup("two_absorbing.csv")
    two_abs = fpdistribution(Tm, Am, [1.0, 0, 0])
    @test all(isapprox.([0.5, 0.5], splittingprobabilities(two_abs)))
    @test_nowarn pdf.(two_abs, [0.0, 5], 1)
    @test_nowarn pdf.(two_abs, [0.0, 5], [1, 2])
end

@testset "Test quasi-stationary distribution" begin
    # Should have a quasi-stationary distribution of [0.5, 0.5]
    T5050 = [-2.0 1; 1 -2]
    A5050 = [1.0 1.0]
    p5050 = [1.0, 0]  # irrelevant for quasi-stationary distribution, but needed to set up fp
    qs_fp = fpdistribution(T5050, A5050, p5050)
    @test isapprox(quasistationary(qs_fp), [0.5, 0.5])
end

@testset "Using static arrays" begin
    Ts = @SArray [-1 1.0; 1 -2]
    As = @SArray [0 1.0]
    p0s = @SVector [1.0, 0]
    @test_nowarn fpdistribution(Ts, As, p0s)
    @test isapprox(mean(fpdistribution(Ts, As, p0s)), mean(fpdistribution(T, A, p0)))
end

@testset "Difficult transition matrix" begin
    T = 6 * [-2.0 1 0 1 0; 1 -2 1 0 0; 0 1 -1 0 0; 1 0 0 -2 1; 0 0 0 1 -2]
    A = 6 * [0.0 0 0 0 1]
    p0 = [1.0, 0, 0, 0, 0]
    @test pdf(fpdistribution(T, A, p0), eps()) > 0.0
end

ext: jl


text:
using LinuxPerf
using Test

using LinuxPerf: make_bench, enable!, disable!, reset!, reasonable_defaults, counters, EventType, EventTypeExt, parse_groups

@testset "LinuxPerf" begin

@testset "simple benchmark" begin
    @test begin
        bench = make_bench(reasonable_defaults);
        @noinline function g(a)
            enable!(bench)
            c = 0
            for x in a
                if x > 0
                    c += 1
                end
            end
            disable!(bench)
            c
        end
        g(zeros(10000))

        counters(bench)

        true  # Succeeded without any exceptions...
    end
end

@testset "@measure" begin
    c1 = @measure 2 + 2
    v, b1 = @measured 2 + 2

    @test v === 4
    @test typeof(c1) == typeof(counters(b1))
end

@testset "Parser" begin
    cycles = EventType(:hw, :cycles)
    insns = EventType(:hw, :instructions)

    @test parse_groups("") == []
    @test parse_groups("cpu-cycles") == [[EventTypeExt(cycles, false, 0)]]
    @test parse_groups("(cpu-cycles)") == parse_groups("cpu-cycles")
    @test parse_groups("cpu-cycles,instructions") == [[EventTypeExt(cycles, false, 0)], [EventTypeExt(insns, false, 0)]]
    @test parse_groups("(cpu-cycles,instructions)") == [[EventTypeExt(cycles, false, 0), EventTypeExt(insns, false, 0)]]
    @test parse_groups("  cpu-cycles,  instructions  ") == parse_groups("cpu-cycles,instructions")
    @test parse_groups("  (  cpu-cycles,  instructions  )  ") == parse_groups("(cpu-cycles,instructions)")

    # exclude flags
    u = LinuxPerf.exclude_flags(true, false, false)
    k = LinuxPerf.exclude_flags(false, true, false)
    h = LinuxPerf.exclude_flags(false, false, true)
    uk = LinuxPerf.exclude_flags(true, true, false)
    ukh = LinuxPerf.exclude_flags(true, true, true)

    # event-level modifiers
    @test parse_groups("cpu-cycles:u") == [[EventTypeExt(cycles, true, u)]]
    @test parse_groups("cpu-cycles:k") == [[EventTypeExt(cycles, true, k)]]
    @test parse_groups("cpu-cycles:h") == [[EventTypeExt(cycles, true, h)]]
    @test parse_groups("cpu-cycles:uk") == [[EventTypeExt(cycles, true, uk)]]
    @test parse_groups("cpu-cycles:ukh") == [[EventTypeExt(cycles, true, ukh)]]
    @test parse_groups("cpu-cycles:ku") == parse_groups("cpu-cycles:uk")
    @test parse_groups("cpu-cycles:uu") == parse_groups("cpu-cycles:u")
    @test parse_groups("cpu-cycles  :  u  ") == parse_groups("cpu-cycles:u")

    # group-level modifiers
    @test parse_groups("(cpu-cycles,instructions):u") == parse_groups("(cpu-cycles:u,instructions:u)")
    @test parse_groups("(cpu-cycles,instructions):k") == parse_groups("(cpu-cycles:k,instructions:k)")
    @test parse_groups("(cpu-cycles,instructions):h") == parse_groups("(cpu-cycles:h,instructions:h)")
    @test parse_groups("(cpu-cycles,instructions):uk") == parse_groups("(cpu-cycles:uk,instructions:uk)")
    @test parse_groups("(cpu-cycles,instructions):ukh") == parse_groups("(cpu-cycles:ukh,instructions:ukh)")
    @test parse_groups("(cpu-cycles,instructions):ku") == parse_groups("(cpu-cycles,instructions):uk")
    @test parse_groups("(cpu-cycles,instructions):uu") == parse_groups("(cpu-cycles,instructions):u")
    @test parse_groups("(cpu-cycles:k,instructions):u") == parse_groups("(cpu-cycles:k,instructions:u)")
    @test parse_groups("(cpu-cycles,instructions)  :  u  ") == parse_groups("(cpu-cycles,instructions):u")
end

end


text:
function delete_duplicate!(db::SQLite.DB, base_id, graph::AbstractGraph, id, graph_path)
    println("Comparing $base_id and $id")
    other_graph = loadgraph(graph_path)
    if graph == other_graph
        println("ICI")
        query = "DELETE FROM decompositions WHERE id = $id"
        execute_query(db, query)
    end
end

function delete_duplicate_dfrow!(db::SQLite.DB, id, origin_name::AbstractString, origin_scenario, graph_path)
    println("Delete duplicate: ($origin_name $origin_scenario)")
    query = "SELECT id, graph_path FROM decompositions WHERE origin_name='$origin_name' AND origin_scenario=$origin_scenario AND id > $id"
    results = DBInterface.execute(db, query) |> DataFrame
    graph = loadgraph(graph_path)
    delete_duplicate_function!(row) = delete_duplicate!(db, id, graph, row[:id], row[:graph_path])
    delete_duplicate_function!.(eachrow(results[!, [:id, :graph_path]]))
end

function delete_duplicates!(db::SQLite.DB; subset=nothing)
    println("Deleting duplicates")
    println("subset\n$subset\nend subset")
    query = "SELECT id, origin_name, origin_scenario, graph_path FROM decompositions"
    if !isnothing(subset)
        query *= " WHERE origin_id IN ($(join(subset, ',')))"
    end
    println(query)
    results = DBInterface.execute(db, query) |> DataFrame
    delete_duplicate_function!(row) = delete_duplicate_dfrow!(db, row[:id], row[:origin_name], row[:origin_scenario], row[:graph_path])
    delete_duplicate_function!.(eachrow(results[!, [:id, :origin_name, :origin_scenario, :graph_path]]))
end

max_stars_repo_name: charlyalizadeh/PowerFlowNetworks

max_issues_repo_name: charlyalizadeh/PowerFlowNetworks

max_forks_repo_name: charlyalizadeh/PowerFlowNetworks


text:
# This file is a part of LegendDSP.jl, licensed under the MIT License (MIT).

import Test
Test.@testset "Package LegendDSP" begin

# test code goes here

end # testset


text:
function priceplot(df::DataFrame, yv::String, stock::String)

  df = copy(df)
  df["days"] = [1:nrow(df)]

  g  = render(plot(df, {:x => "days",
                        :y => yv}, Geom.line))

  filename = strcat(stock, ".svg")
  img = SVG(filename, 6inch, 4inch)
  draw(img, g)
  finish(img)
  run(`open -a safari $filename`)
end


text:
"""
Check that user-facing function arguments satisfy assumptions made in code:

* Per-group sample size is at least 2
* The deviation from the null is strictly positive
* The variance in each group is strictly positive
* The power is between 0 and 1
* The significance level is between 0 and 1
"""
function check_args(
    ns::Union{Real, Tuple},
    δ::Real,
    σs::Union{Real, Tuple},
    p::Real,
    α::Real,
)
    if isa(ns, Real)
        if !(2.0 <= ns < Inf)
            error("sample size must be in [2.0, Inf)")
        end
    else
        if !(2.0 <= min(ns...) < Inf)
            error("sample sizes must both be in [2.0, Inf)")
        end
    end

    if !(0.0 < δ < Inf)
        error("δ must be in (0.0, Inf)")
    end

    if isa(σs, Real)
        if !(0.0 < σs < Inf)
            error("σ must be in (0.0, Inf)")
        end
    else
        if !(0.0 < min(σs...) < Inf)
            error("σs must both be in (0.0, Inf)")
        end
    end

    if !(0.0 < p < 1.0)
        error("power must be in (0.0, 1.0)")
    end

    if !(0.0 < α < 1.0)
        error("α must be in (0.0, 1.0)")
    end
end


text:
"""
    $SIGNATURES

Return dict of all histories in a Bayes Tree.
"""
function getTreeCliqsSolverHistories(fg::G,
                                     tree::BayesTree)::Dict{Symbol, CSMHistory} where G <: AbstractDFG
  #
  fsy = getTreeAllFrontalSyms(fg, tree)
  histories = Dict{Symbol, CSMHistory}()
  for fs in fsy
    hist = getCliqSolveHistory(tree, fs)
    if length(hist) > 0
      histories[fs] = hist
    end
  end
  return histories
end

"""
    $SIGNATURES

Return clique state machine history from `tree` if it was solved with `recordcliqs`.

Notes
- Cliques are identified by front variable `::Symbol` which are always unique across the cliques.
"""
function getCliqSolveHistory(cliq::Graphs.ExVertex)
  getData(cliq).statehistory
end
function getCliqSolveHistory(tree::BayesTree, frntal::Symbol)
  cliq = whichCliq(tree, frntal)
  getCliqSolveHistory(cliq)
end

"""
    $SIGNATURES

Print a short summary of state machine history for a clique solve.

Related:

getTreeAllFrontalSyms, getCliqSolveHistory, animateCliqStateMachines
"""
function printCliqHistorySummary(fid, hist::Vector{Tuple{DateTime, Int, Function, CliqStateMachineContainer}})
  if length(hist) == 0
    @warn "printCliqHistorySummary -- No CSM history found."
  end
  for hi in hist
    first = (split(string(hi[1]), 'T')[end])*" "
    len = length(first)
    for i in len:13  first = first*" "; end
    first = first*string(hi[2])
    len = length(first)
    for i in len:17  first = first*" "; end
    first = first*string(getCliqStatus(hi[4].cliq))
    len = length(first)
    for i in len:30  first = first*" "; end
    nextfn = split(split(string(hi[3]),'.')[end], '_')[1]
    lenf = length(nextfn)
    nextfn = 20 < lenf ? nextfn[1:20]*"." : nextfn
    first = first*nextfn
    len = length(first)
    for i in len:52  first = first*" "; end
    first = first*string(hi[4].forceproceed)
    len = length(first)
    for i in len:58  first = first*" "; end
    if 0 < length(hi[4].parentCliq)
      first = first*string(getCliqStatus(hi[4].parentCliq[1]))
    else
      first = first*"----"
    end
    first = first*" | "
    if 0 < length(hi[4].childCliqs)
      for ch in hi[4].childCliqs
        first = first*string(getCliqStatus(ch))*" "
      end
    end
    println(fid, first)
  end
  nothing
end

function printCliqHistorySummary(hist::Vector{Tuple{DateTime, Int, Function, CliqStateMachineContainer}})
  printCliqHistorySummary(stdout, hist)
end

function printCliqHistorySummary(hists::Dict{Int,Vector{Tuple{DateTime, Int, Function, CliqStateMachineContainer}}}, tree::BayesTree, sym::Symbol)
  hist = hists[getCliq(tree, sym).index]
  printCliqHistorySummary(stdout, hist)
end

function printCliqHistorySummary(cliq::Graphs.ExVertex)
  hist = getCliqSolveHistory(cliq)
  printCliqHistorySummary(hist)
end

function printCliqHistorySummary(tree::BayesTree, frontal::Symbol)
  hist = getCliqSolveHistory(tree, frontal)
  printCliqHistorySummary(hist)
end

"""
  $SIGNATURES

Repeat a solver state machine step without changing history or primary values.

printCliqSummary, printCliqHistorySummary, getCliqSolveHistory, cliqHistFilterTransitions
"""
function sandboxCliqResolveStep(tree::BayesTree,
                                frontal::Symbol,
                                step::Int)
  #
  hist = getCliqSolveHistory(tree, frontal)
    # clear Condition states to allow step solve
    cond = getSolveCondition(hist[step][4].cliq)
    cond.waitq = Any[]
  return sandboxStateMachineStep(hist, step)
end

"""
    $SIGNATURES

Draw many images in '/tmp/?/csm_%d.png' representing time synchronized state machine
events for cliques `cliqsyms::Vector{Symbol}`.

Notes
- State history must have previously been recorded (stored in tree cliques).

Related

printCliqHistorySummary
"""
function animateCliqStateMachines(tree::BayesTree,
                                  cliqsyms::Vector{Symbol};
                                  frames::Int=100  )
  #
  startT = Dates.now()
  stopT = Dates.now()

  # get start and stop times across all cliques
  first = true
  for sym in cliqsyms
    hist = getCliqSolveHistory(tree, sym)
    if hist[1][1] < startT
      startT = hist[1][1]
    end
    if first
      stopT = hist[end][1]
      first = false
    end
    if stopT < hist[end][1]
      stopT= hist[end][1]
    end
  end

  # export all figures
  folders = String[]
  for sym in cliqsyms
    hist = getCliqSolveHistory(tree, sym)
    retval = animateStateMachineHistoryByTime(hist, frames=frames, folder="caesar/animatecsm/cliq$sym", title="$sym", startT=startT, stopT=stopT, rmfirst=false)
    push!(folders, "cliq$sym")
  end

  return folders
end

"""
    $SIGNATURES

Return state machine transition steps from history such that the `nextfnc::Function`.

Related:

getCliqSolveHistory, printCliqHistorySummary, filterHistAllToArray, sandboxCliqResolveStep
"""
function cliqHistFilterTransitions(hist::Vector{Tuple{DateTime, Int, Function, CliqStateMachineContainer}}, nextfnc::Function)
  ret = Vector{Tuple{DateTime, Int, Function, CliqStateMachineContainer}}()
  for hi in hist
    if hi[3] == nextfnc
      push!(ret, hi)
    end
  end
  return ret
end

"""
    $SIGNATURES

Return state machine transition steps from all cliq histories with transition `nextfnc::Function`.

Related:

getCliqSolveHistory, printCliqHistorySummary, cliqHistFilterTransitions, sandboxCliqResolveStep
"""
function filterHistAllToArray(tree::BayesTree, frontals::Vector{Symbol}, nextfnc::Function)
  ret = Vector{Tuple{DateTime, Int, Function, CliqStateMachineContainer}}()
  for sym in frontals
    hist = getCliqSolveHistory(tree, sym)
    fih = cliqHistFilterTransitions(hist, nextfnc)
    for fi in fih
      push!(ret, fi)
    end
   end
  return ret
end

"""
    $SIGNATURES

Standalone state machine solution for a single clique.

Related:

initInferTreeUp!
"""
function solveCliqWithStateMachine!(dfg::G,
                                    tree::BayesTree,
                                    frontal::Symbol;
                                    iters::Int=200,
                                    downsolve::Bool=true,
                                    recordhistory::Bool=false,
                                    verbose::Bool=false,
                                    nextfnc::Function=testCliqCanRecycled_StateMachine,
                                    prevcsmc::Union{Nothing,CliqStateMachineContainer}=nothing) where G <: AbstractDFG
  #
  cliq = whichCliq(tree, frontal)
  children = Graphs.ExVertex[]
  for ch in Graphs.out_neighbors(cliq, tree.bt)
    push!(children, ch)
  end
  prnt = getParent(tree, cliq)

  destType = (G <: InMemoryDFGTypes) ? G : InMemDFGType#GraphsDFG{SolverParams}

  csmc = isa(prevcsmc, Nothing) ? CliqStateMachineContainer(dfg, initfg(destType, params=getSolverParams(dfg)), tree, cliq, prnt, children, false, true, true, downsolve, false, getSolverParams(dfg)) : prevcsmc
  statemachine = StateMachine{CliqStateMachineContainer}(next=nextfnc)
  while statemachine(csmc, verbose=verbose, iterlimit=iters, recordhistory=recordhistory); end
  statemachine, csmc
end

"""
    $SIGNATURES

Animate multiple clique state machines on the same graphviz visualization.  Renders according to
linear time for all provided histories.

Example:
```julia
using Caesar

# build a factor graph
fg = initfg()
# addVariable!(...)
# addFactor!(...)
# ...

fsy = getTreeAllFrontalSyms(fg, tree) # for later use
# perform inference to find the factor graph marginal posterior estimates
tree, smt, hist = solveTree!(fg, recordcliqs=fsy)

# generate frames in standard location /tmp/caesar/csmCompound/
#  requires: sudo apt-get install graphviz
csmAnimate(fg, tree, fsy, frames=500)

# to render and show from default location (might require)
#  sudo apt-get install ffmpeg vlc

# .ogv [Totem Ubuntu default]
Base.rm("/tmp/caesar/csmCompound/out.ogv")
run(`ffmpeg -r 10 -i /tmp/caesar/csmCompound/csm_%d.png -c:v libtheora -vf fps=25 -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" -q 10 /tmp/caesar/csmCompound/out.ogv`)
run(`totem /tmp/caesar/csmCompound/out.ogv`)

# h.264 [VLC not default]
Base.rm("/tmp/caesar/csmCompound/out.mp4")
run(`ffmpeg -r 10 -i /tmp/caesar/csmCompound/csm_%d.png -c:v libx264 -vf fps=25 -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" /tmp/caesar/csmCompound/out.mp4`)
run(`vlc /tmp/caesar/csmCompound/out.mp4`)
```
"""
function csmAnimate(fg::G,
                    tree::BayesTree,
                    cliqsyms::Vector{Symbol};
                    frames::Int=100,
                    rmfirst::Bool=true  ) where G <: AbstractDFG
  #
  hists = getTreeCliqsSolverHistories(fg,tree)

  startT = Dates.now()
  stopT = Dates.now()

  # get start and stop times across all cliques
  first = true
  for (csym, hist) in hists
    # global startT, stopT
    @show csym
    if hist[1][1] < startT
      startT = hist[1][1]
    end
    if first
      stopT = hist[end][1]
      first = false
    end
    if stopT < hist[end][1]
      stopT = hist[end][1]
    end
  end

  # export all figures
  if rmfirst
    @warn "Removing /tmp/caesar/csmCompound/ in preparation for new frames."
    Base.rm("/tmp/caesar/csmCompound/", recursive=true, force=true)
  end
  animateStateMachineHistoryByTimeCompound(hists, startT, stopT, folder="caesar/csmCompound", frames=frames)
end

"""
    $SIGNATURES

Convenience function to assign and make video of CSM state machine for `cliqs`.

Notes
- Probably several teething issues still (lower priority).
- Use `assignhist` if solver params async was true, or errored.

Related

csmAnimate, printCliqHistorySummary
"""
function makeCsmMovie(fg::G,
                      tree::BayesTree,
                      cliqs=ls(fg);
                      assignhist=nothing,
                      show::Bool=true,
                      filename::AS="/tmp/caesar/csmCompound/out.ogv",
                      frames::Int=1000 )::String where {G <: AbstractDFG, AS <: AbstractString}
  #
  if assignhist != nothing
    assignTreeHistory!(tree, assignhist)
  end
  csmAnimate(fg, tree, cliqs, frames=frames)
  # Base.rm("/tmp/caesar/csmCompound/out.ogv")
  run(`ffmpeg -r 10 -i /tmp/caesar/csmCompound/csm_%d.png -c:v libtheora -vf fps=25 -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" -q 10 $filename`)
  if show
    @async run(`totem $filename`)
  end
  filename
end

"""
    $SIGNATURES

Return true if this clique's down init should be delayed on account of prioritization among sibling separators.

Notes
- process described in issue #344

Dev Notes
- not priorizing order yet (TODO), just avoiding unsolvables at this time.
- Very closely related to getCliqSiblingsPartialNeeds -- refactor likely (NOTE).
- should precompute `allinters`.
"""
function getSiblingsDelayOrder(tree::BayesTree, cliq::Graphs.ExVertex, prnt, dwinmsgs::Dict; logger=ConsoleLogger())
  # when is a cliq upsolved
  solvedstats = Symbol[:upsolved; :marginalized; :uprecycled]

  # safety net double check
  cliqst = getCliqStatus(cliq)
  if cliqst in solvedstats
    with_logger(logger) do
      @warn "getSiblingsDelayOrder -- clique status should not be here with a solved cliqst=$cliqst"
    end
    return false
  end

  # get siblings separators
  sibs = getCliqSiblings(tree, cliq, true)
  ids = map(s->s.index, sibs)
  len = length(sibs)
  sibidx = collect(1:len)[ids .== cliq.index][1]
  seps = getCliqSeparatorVarIds.(sibs)
  lielbls = setdiff(ids, cliq.index)
  # get intersect matrix of siblings (should be exactly the same across siblings' csm)
  allinters = Array{Int,2}(undef, len, len)
  dwninters = Vector{Int}(undef, len)
  dwnkeys = collect(keys(dwinmsgs))
  with_logger(logger) do
    @info "getSiblingsDelayOrder -- number siblings=$(len), sibidx=$sibidx"
  end

  # sum matrix with all "up solved" rows and columns eliminated
  fill!(allinters, 0)
  for i in 1:len
    for j in i:len
      if i != j
        allinters[i,j] = length(intersect(seps[i],seps[j]))
      end
    end
    dwninters[i] = length(intersect(seps[i], dwnkeys))
  end

  # sum "across/over" rows, then columns (i.e. visa versa "along" columns then rows)
  rows = sum(allinters, dims=1)
  cols = sum(allinters, dims=2)

  with_logger(logger) do
      @info "getSiblingsDelayOrder -- allinters=$(allinters)"
      @info "getSiblingsDelayOrder -- rows=$(rows)"
      @info "getSiblingsDelayOrder -- rows=$(cols)"
  end

  # is this clique a non-zero row -- i.e. sum across columns? if not, no further special care needed
  if cols[sibidx] == 0
    with_logger(logger) do
      @info "getSiblingsDelayOrder -- cols[sibidx=$(sibidx))] == 0, no special care needed"
    end
    return false
  end

  # now determine if initializing from below or needdownmsg
  if cliqst in Symbol[:needdownmsg;]
    # be super careful about delay (true) vs pass (false) at this point -- might be partial too TODO
    # return true if delay beneficial to initialization accuracy

    # find which siblings this cliq epends on
    symm = allinters + allinters'
    maskcol = symm[:,sibidx] .> 0
    # lenm = length(maskcol)
    stat = Vector{Symbol}(undef, len)
    stillbusymask = fill(false, len)

    flush(logger.stream)

    # get each sibling status (entering atomic computation segment -- until wait command)
    stat .= getCliqStatus.(sibs) #[maskcol]

    ## (long down chain case)
    # need different behaviour when all remaining siblings are blocking with :needdownmsg
    remainingmask = stat .== :needdownmsg
    if sum(remainingmask) == length(stat)
      with_logger(logger) do
        @info "getSiblingsDelayOrder -- all blocking: sum(remainingmask) == length(stat), stat=$stat"
      end
      # pick sibling with most overlap in down msgs from parent
       # list of similar length siblings
      candidates = dwninters .== maximum(dwninters)
      if candidates[sibidx]
        # must also pick minimized intersect with other remaing siblings
        maxcan = collect(1:len)[candidates]
        with_logger(logger) do
          @info "getSiblingsDelayOrder -- candidates=$candidates, maxcan=$maxcan, rows=$rows"
        end
        if rows[sibidx] == minimum(rows[maxcan])
          with_logger(logger) do
            @info "getSiblingsDelayOrder -- FORCE DOWN INIT SOLVE ON THIS CLIQUE: $(cliq.index), $(cliq.attributes["label"])"
          end
          return false
        end
      end
      with_logger(logger) do
        @info "getSiblingsDelayOrder -- not a max and should block"
      end
      return true
    end

    # still busy solving on branches, so potential to delay
    for i in 1:len
      stillbusymask[i] = maskcol[i] && !(stat[i] in solvedstats)
    end
    with_logger(logger) do
        @info "getSiblingsDelayOrder -- busy solving:"
        @info "maskcol=$maskcol"
        @info "stillbusy=$stillbusymask"
    end

    # Too blunt -- should already have returned false by this point perhaps
    if sum(stillbusymask) > 0
      # yes something to delay about
      with_logger(logger) do
        @info "getSiblingsDelayOrder -- yes delay,"
        @info "stat=$stat"
        @info "symm=$symm"
      end
      return true
    end
  end

  with_logger(logger) do
    @info "getSiblingsDelayOrder -- default will not delay"
  end
  flush(logger.stream)
  # carry over default from partial init process
  return false
end

"""
    $SIGNATURES

Return true if both, i.) this clique requires more downward information, ii.) more
downward message information could potentially become available.

Notes
- Delay initialization to the last possible moment.

Dev Notes:

Determine clique truely isn't able to proceed any further:
- should be as self reliant as possible (using clique's status as indicator)
- change status to :mustinitdown if have only partial beliefs so far:
  - combination of status, while partials belief siblings are not :mustinitdown
"""
function getCliqSiblingsPartialNeeds(tree::BayesTree, cliq::Graphs.ExVertex, prnt, dwinmsgs::Dict; logger=ConsoleLogger())
  # which incoming messages are partials
  hasPartials = Dict{Symbol, Int}()
  for (sym, tmsg) in dwinmsgs
    # assuming any down message per label that is not partial voids further partial consideration
    if sum(tmsg[2]) > 0
      if !haskey(hasPartials, sym)
        hasPartials[sym] = 0
      end
      hasPartials[sym] += 1
    end
  end
  partialKeys = collect(keys(hasPartials))

  ## determine who might be able to help init this cliq
  # check sibling separator sets against this clique's separator
  sibs = getCliqSiblings(tree, cliq)

  with_logger(logger) do
    @info "getCliqSiblingsPartialNeeds -- CHECK PARTIAL"
  end
  # identify which cliques might have useful information
  localsep = getCliqSeparatorVarIds(cliq)
  seps = Dict{Int, Vector{Symbol}}()
  for si in sibs
    # @show si.attributes["label"]
    mighthave = intersect(getCliqSeparatorVarIds(si), localsep)
    if length(mighthave) > 0
      seps[si.index] = mighthave
      if getCliqStatus(si) in [:initialized; :null; :needdownmsg]
        # partials treated special -- this is slightly hacky
        if length(intersect(localsep, partialKeys)) > 0 && length(mighthave) > 0
          # this sibling might have info to delay about
          setCliqDrawColor(cliq,"magenta")
          return true
        end
      end
    end
  end
  # determine if those cliques will / or will not be able to provide more info
  # when does clique change to :mustinitdown

  # default
  return false
end

"""
    $SIGNATURES

Bump a clique state machine solver condition in case a task might be waiting on it.
"""
notifyCSMCondition(tree::BayesTree, frsym::Symbol) = notify(getSolveCondition(whichCliq(tree, frsym)))

"""
    $SIGNATURES

Store/cache a clique's solvable dimensions.
"""
function updateCliqSolvableDims!(cliq::Graphs.ExVertex,
                                 sdims::Dict{Symbol, Float64},
                                 logger=ConsoleLogger() )::Nothing
  #
  cliqd = getData(cliq)
  if isready(cliqd.solvableDims)
    take!(cliqd.solvableDims)
    with_logger(logger) do
      @info "cliq $(cliq.index), updateCliqSolvableDims! -- cleared solvableDims"
    end
  end
  put!(cliqd.solvableDims, sdims)
  with_logger(logger) do
      @info "cliq $(cliq.index), updateCliqSolvableDims! -- updated"
  end
  nothing
end

"""
    $SIGNATURES

Retrieve a clique's cached solvable dimensions (since last update).
"""
function fetchCliqSolvableDims(cliq::Graphs.ExVertex)::Dict{Symbol,Float64}
  cliqd = getData(cliq)
  if isready(cliqd.solvableDims)
    return cliqd.solvableDims.data[1]
  end
  return fetch(cliqd.solvableDims)
  # if isready(cliqd.solvableDims)
  # end
end

"""
    $SIGNATURES

Return true there is no other sibling that will make progress.

Notes
- Relies on sibling priority order with only one "currently best" option that will force progress in global upward inference.
- Return false if one of the siblings is still busy
"""
function areSiblingsRemaingNeedDownOnly(tree::BayesTree,
                                        cliq::Graphs.ExVertex  )::Bool
  #
  stillbusylist = [:null; :initialized;]
  prnt = getParent(tree, cliq)
  if length(prnt) > 0
    for si in getChildren(tree, prnt[1])
      # are any of the other siblings still busy?
      if si.index != cliq.index && getCliqStatus(si) in stillbusylist
        return false
      end
    end
  end

  # nope, everybody is waiting for something to change -- proceed with forcing a cliq solve
  return true
end

"""
    $SIGNATURES

Calculate new and then set PPE estimates for variable from some distributed factor graph.

DevNotes
- TODO solve key might be needed if one only wants to update one
- TODO consider a more fiting name.
- guess it would make sense that :default=>variableNodeData, goes with :default=>MeanMaxPPE

Related

calcVariablePPE
"""
function setVariablePosteriorEstimates!(var::DFG.DFGVariable, solveKey::Symbol=:default)::DFG.DFGVariable

  vnd = solverData(var, solveKey)

  #TODO in the future one can perhaps populate other solver data types here by looking at the typeof estimateDict entries
  var.estimateDict[solveKey] = calcVariablePPE(var, method=MeanMaxPPE, solveKey=solveKey)

  return var
end

function setVariablePosteriorEstimates!(subfg::AbstractDFG,
                                        sym::Symbol )::DFG.DFGVariable
  var = setVariablePosteriorEstimates!(getVariable(subfg, sym))
  # JT - TODO if subfg is in the cloud or from another fg it has to be updated
  # it feels like a waste to update the whole vairable for one field.
  # currently i could find mergeUpdateVariableSolverData()
  # might be handy to use a setter such as updatePointParametricEst(dfg, variable, solverkey)
  # This might also not be the correct place, if it is uncomment:
  # if (subfg <: InMemoryDFGTypes)
  #   updateVariable!(subfg, var)
  # end
end

"""
    $SIGNATURES

Get the main factor graph stored in a history object from a particular step in CSM.

Related

getCliqSubgraphFromHistory, printCliqHistorySummary, printCliqSummary
"""
getGraphFromHistory(hist::Vector{<:Tuple}, step::Int) = hist[step][4].dfg

"""
    $SIGNATURES

Get the cliq sub graph fragment stored in a history object from a particular step in CSM.

Related

getGraphFromHistory, printCliqHistorySummary, printCliqSummary
"""
getCliqSubgraphFromHistory(hist::Vector{<:Tuple}, step::Int) = hist[step][4].cliqSubFg
getCliqSubgraphFromHistory(tree::BayesTree, frnt::Symbol, step::Int) = getCliqSubgraphFromHistory(getCliqSolveHistory(tree, frnt), step)

function printCliqSummary(dfg::G,
                          tree::BayesTree,
                          frs::Symbol,
                          logger=ConsoleLogger() ) where G <: AbstractDFG
  #
  printCliqSummary(dfg, getCliq(tree, frs), logger)
end

function updateSubFgFromDownMsgs!(sfg::G,
                                  dwnmsgs::Dict,
                                  seps::Vector{Symbol} ) where G <: AbstractDFG
  #
  # sanity check basic Bayes (Junction) tree property
  # length(setdiff(keys(dwnmsgs), seps)) == 0 ? nothing : error("updateSubFgFromDownMsgs! -- separators and dwnmsgs not consistent")

  # update specific variables in sfg from msgs
  for (key,beldim) in dwnmsgs
    if key in seps
      setValKDE!(sfg, key, beldim[1], false, beldim[2])
    end
  end

  nothing
end

"""
    $SIGNATURES

Find all factors that go `from` variable to any other complete variable set within `between`.

Notes
- Developed for downsolve in CSM, expanding the cliqSubFg to include all frontal factors.
"""
function findFactorsBetweenFrom(dfg::G,
                                between::Vector{Symbol},
                                from::Symbol ) where {G <: AbstractDFG}
  # get all associated factors
  allfcts = ls(dfg, from)

  # remove candidates with neighbors outside between with mask
  mask = ones(Bool, length(allfcts))
  i = 0
  for fct in allfcts
    i += 1
    # check if immediate neighbors are all in the `between` list
    immnei = ls(dfg, fct)
    if length(immnei) != length(intersect(immnei, between))
      mask[i] = false
    end
  end

  # return only masked factors
  return allfcts[mask]
end

"""
    $SIGNATURES

Special function to add a few variables and factors to the clique sub graph required for downward solve in CSM.

Dev Notes
- There is still some disparity on whether up and down solves of tree should use exactly the same subgraph...  'between for up and frontal connected for down'
"""
function addDownVariableFactors!(dfg::G1,
                                 subfg::G2,
                                 cliq::Graphs.ExVertex,
                                 logger=ConsoleLogger()  ) where {G1 <: AbstractDFG, G2 <: InMemoryDFGTypes}
  #
  # determine which variables and factors needs to be added
  currsyms = ls(subfg)
  allclsyms = getCliqVarsWithFrontalNeighbors(dfg, cliq)
  newsyms = setdiff(allclsyms, currsyms)
  with_logger(logger) do
    @info "addDownVariableFactors!, cliq=$(cliq.index), newsyms=$newsyms"
  end
  frtls = getCliqFrontalVarIds(cliq)
  with_logger(logger) do
    @info "addDownVariableFactors!, cliq=$(cliq.index), frtls=$frtls"
  end
  allnewfcts = union(map(x->findFactorsBetweenFrom(dfg,union(currsyms, newsyms),x), frtls)...)
  newfcts = setdiff(allnewfcts, lsf(subfg))
  with_logger(logger) do
    @info "addDownVariableFactors!, cliq=$(cliq.index), newfcts=$newfcts, allnewfcts=$allnewfcts"
  end

  # add the variables
  DFG.getSubgraph(dfg, newsyms, false, subfg)
  # add the factors
  DFG.getSubgraph(dfg, newfcts, false, subfg)

  return newsyms, newfcts
end

"""
    $SIGNATURES

Basic wrapper to take local product and then set the value of `sym` in `dfg`.
"""
function localProductAndUpdate!(dfg::G,
                                sym::Symbol,
                                setkde::Bool=true,
                                logger=ConsoleLogger() )::Tuple{BallTreeDensity, Float64, Vector{Symbol}} where {G <: AbstractDFG}
  #
  pp, dens, parts, lbl, infdim = localProduct(dfg, sym, N=getSolverParams(dfg).N, logger=logger)
  setkde ? setValKDE!(dfg, sym, pp, false, infdim) : nothing

  return pp, infdim, lbl
end

"""
    $SIGNATURES

Calculate new and then set the down messages for a clique in Bayes (Junction) tree.
"""
function getSetDownMessagesComplete!(subfg::G,
                                     cliq::Graphs.ExVertex,
                                     prntDwnMsgs::TempBeliefMsg,
                                     logger=ConsoleLogger()  )::Nothing where G <: AbstractDFG
  #
  allvars = getCliqVarIdsAll(cliq)
  allprntkeys = collect(keys(prntDwnMsgs))
  passkeys = intersect(allvars, setdiff(allprntkeys,ls(subfg)))
  remainkeys = setdiff(allvars, passkeys)
  newDwnMsgs = TempBeliefMsg()

  # some msgs are just pass through from parent
  for pk in passkeys
    newDwnMsgs[pk] = prntDwnMsgs[pk]
  end

  # other messages must be extracted from subfg
  for mk in remainkeys
    newDwnMsgs[mk] = (getKDE(subfg, mk), getVariableInferredDim(subfg,mk))
  end

  # set the downward keys
  with_logger(logger) do
    @info "cliq $(cliq.index), getSetDownMessagesComplete!, allkeys=$(allvars), passkeys=$(passkeys)"
  end
  setDwnMsg!(cliq, newDwnMsgs)

  return nothing
end

"""
    $SIGNATURES

Determine which variables to iterate or compute directly for downward tree pass of inference.

Related Functions from Upward Inference

directPriorMsgIDs, directFrtlMsgIDs, directAssignmentIDs, mcmcIterationIDs
"""
function determineCliqVariableDownSequence(subfg::G, cliq::Graphs.ExVertex) where G <: AbstractDFG
  frtl = getCliqFrontalVarIds(cliq)

  adj = DFG.getAdjacencyMatrix(subfg)
  mask = map(x->(x in frtl), adj[1,:])
  subAdj = adj[2:end,mask] .!= nothing
  newFrtlOrder = Symbol.(adj[1,mask])
  crossCheck = sum(Int.(subAdj), dims=2) .> 1
  iterVars = Symbol[]
  for i in 1:length(crossCheck)
    # must add associated variables to iterVars
    if crossCheck[i]
      # find which variables are associated
      varSym = newFrtlOrder[subAdj[i,:]]
      union!(iterVars, varSym)
    end
  end

  # return iteration list ordered by frtl
  return intersect(frtl, iterVars)
end

"""
    $SIGNATURES

Perform downward direction solves on a sub graph fragment.
Calculates belief on each of the frontal variables and iterate if required.

Notes
- uses all factors connected to the frontal variables.
- assumes `subfg` was properly prepared before calling.
- has multi-process option.

Dev Notes
- TODO incorporate variation possible due to cross frontal factors.
- cleanup and updates required, and @spawn jl 1.3
"""
function solveCliqDownFrontalProducts!(subfg::G,
                                       cliq::Graphs.ExVertex,
                                       opts::SolverParams,
                                       logger=ConsoleLogger();
                                       MCIters::Int=3 )::Nothing where G <: AbstractDFG
  #
  # get frontal variables for this clique
  frsyms = getCliqFrontalVarIds(cliq)

  # determine if cliq has cross frontal factors
  # iterdwn, directdwns, passmsgs?
  iterFrtls = determineCliqVariableDownSequence(subfg,cliq)

  # direct frontals
  directs = setdiff(frsyms, iterFrtls)

  # ignore limited fixed lag variables
  fixd = map(x->opts.limitfixeddown && isMarginalized(subfg,x), frsyms)
  skip = frsyms[fixd]
  iterFrtls = setdiff(iterFrtls, skip)
  directs = setdiff(directs, skip)
  with_logger(logger) do
    @info "cliq $(cliq.index), doCliqDownSolve_StateMachine, skipping marginalized keys=$(skip)"
  end

  # use new localproduct approach
  if opts.multiproc
    downresult = Dict{Symbol, Tuple{BallTreeDensity, Float64, Vector{Symbol}}}()
    @sync for i in 1:length(directs)
      @async begin
        downresult[directs[i]] = remotecall_fetch(localProductAndUpdate!, upp2(), subfg, directs[i], false)
      end
    end
    with_logger(logger) do
      @info "cliq $(cliq.index), doCliqDownSolve_StateMachine, multiproc keys=$(keys(downresult))"
    end
    for fr in directs
        with_logger(logger) do
            @info "cliq $(cliq.index), doCliqDownSolve_StateMachine, key=$(fr), infdim=$(downresult[fr][2]), lbls=$(downresult[fr][3])"
        end
      setValKDE!(subfg, fr, downresult[fr][1], false, downresult[fr][2])
    end
    for mc in 1:MCIters, fr in iterFrtls
      result = remotecall_fetch(localProductAndUpdate!, upp2(), subfg, fr, false)
      setValKDE!(subfg, fr, result[1], false, result[2])
      with_logger(logger) do
          @info "cliq $(cliq.index), doCliqDownSolve_StateMachine, iter key=$(fr), infdim=$(result[2]), lbls=$(result[3])"
      end
    end
  else
    # do directs first
    for fr in directs
      localProductAndUpdate!(subfg, fr, true, logger)
    end
    #do iters next
    for mc in 1:MCIters, fr in iterFrtls
      localProductAndUpdate!(subfg, fr, true, logger)
    end
  end

  return nothing
end

#


text:
#!/usr/bin/env julia

include("../src/MsgPackRpcClient.jl")
include("dataset.jl")
include("const.jl")
using MsgPackRpcClient
using Base.Test

function test_data(data, number = 1)
  results = {}
  expects = {}
  for d in data
    future = MsgPackRpcClient.call(session, d["method"], d["arg"]; sync = false)
    push!(results, get(future) )
    if haskey(d, "expect")
      push!(expects, d["expect"])
    else
      push!(expects, d["arg"])
    end
  end

  for d in data
    println("$(number): $d ")
    try
      @test first(results[number]) == expects[number]
      println("  => OK")
    catch
      println("Error on d[\"arg\"] = ", d["arg"])
    end
    number += 1
  end
end

session = MsgPackRpcClientSession.create()

test_data(get_dataset())

session.destroy()

max_stars_repo_name: keithseahus/msgpack-rpc-julia

max_issues_repo_name: keithseahus/msgpack-rpc-julia

max_forks_repo_name: keithseahus/msgpack-rpc-julia


text:
using LinearAlgebra

struct ValueOne; end
ValueOne()

# Compute X <- a X + b I.
function matfun_axpby!(X,a,b,Y::UniformScaling)
    m,n=size(X)
    if ~(a isa ValueOne)
        rmul!(X,a)
    end
    @inbounds for i=1:n
        X[i,i]+=(b isa ValueOne) ? 1 : b
    end
end

@inline function denman_beavers_opt(A)
    return denman_beavers_opt!(copy(A))
end

@inline function denman_beavers_opt!(A)
    T=promote_type(eltype(A),Float64) # Make it work for many 'bigger' types (matrices and scalars)
    max_memslots=7
    memslots=Vector{Matrix{T}}(undef,max_memslots)
    n=size(A,1)
    for j=1:max_memslots
        memslots[j]=Matrix{T}(undef,n,n)
    end
    # The first slots are precomputed nodes [:A]
    memslots[1]=A # overwrite A
    # Uniform scaling is exploited.
    # No matrix I explicitly allocated.
    value_one=ValueOne()
    # Computation order: Bb2 Ba2 B2 Ba3 Bb3 B3 Ba4 Bb4 B4 Ba5 Bb5 B5 T2k7
    # Computing Bb2 = x*I+x*A
    coeff1=1.0
    coeff2=-0.011141376535527443
    memslots[2] .= coeff2.*memslots[1]
    mul!(memslots[2],true,I*coeff1,true,true)
    # Computing Ba2 = x*I+x*A
    coeff1=1.0
    coeff2=0.7610413081657074
    memslots[3] .= coeff2.*memslots[1]
    mul!(memslots[3],true,I*coeff1,true,true)
    # Computing B2 with operation: ldiv
    memslots[4]=memslots[3]\memslots[2]
    # Deallocating Ba2 in slot 3
    # Deallocating Bb2 in slot 2
    # Computing Ba3 = x*I+x*A+x*B2
    coeff1=1.0
    coeff2=-0.07127247848266706
    coeff3=0.9541397430184381
    memslots[2] .= coeff2.*memslots[1] .+ coeff3.*memslots[4]
    mul!(memslots[2],true,I*coeff1,true,true)
    # Computing Bb3 = x*I+x*A+x*B2
    coeff1=1.0
    coeff2=-0.02575361014723645
    coeff3=-0.004282806676350282
    memslots[3] .= coeff2.*memslots[1] .+ coeff3.*memslots[4]
    mul!(memslots[3],true,I*coeff1,true,true)
    # Computing B3 with operation: ldiv
    memslots[5]=memslots[2]\memslots[3]
    # Deallocating Ba3 in slot 2
    # Deallocating Bb3 in slot 3
    # Computing Ba4 = x*I+x*A+x*B2+x*B3
    coeff1=1.0
    coeff2=0.5152503668289159
    coeff3=-0.10150239642416546
    coeff4=0.016950835467818528
    memslots[2] .= coeff2.*memslots[1] .+ coeff3.*memslots[4] .+ coeff4.*memslots[5]
    mul!(memslots[2],true,I*coeff1,true,true)
    # Computing Bb4 = x*I+x*A+x*B2+x*B3
    coeff1=1.0
    coeff2=0.03845623901890617
    coeff3=0.026744368550352622
    coeff4=-0.029043605652931636
    memslots[3] .= coeff2.*memslots[1] .+ coeff3.*memslots[4] .+ coeff4.*memslots[5]
    mul!(memslots[3],true,I*coeff1,true,true)
    # Computing B4 with operation: ldiv
    memslots[6]=memslots[2]\memslots[3]
    # Deallocating Ba4 in slot 2
    # Deallocating Bb4 in slot 3
    # Computing Ba5 = x*I+x*A+x*B2+x*B3+x*B4
    coeff1=0.49421282325538585
    coeff2=0.05943417585870563
    coeff3=0.5017024742690791
    coeff4=0.5276435956563207
    coeff5=1.0
    memslots[2] .= coeff2.*memslots[1] .+ coeff3.*memslots[4] .+ coeff4.*memslots[5] .+ coeff5.*memslots[6]
    mul!(memslots[2],true,I*coeff1,true,true)
    # Computing Bb5 = x*I+x*A+x*B2+x*B3+x*B4
    coeff1=1.0
    coeff2=0.12762852235945304
    coeff3=-0.0015101375211018255
    coeff4=-0.14486471812413823
    coeff5=0.01583234295751802
    memslots[3] .= coeff2.*memslots[1] .+ coeff3.*memslots[4] .+ coeff4.*memslots[5] .+ coeff5.*memslots[6]
    mul!(memslots[3],true,I*coeff1,true,true)
    # Computing B5 with operation: ldiv
    memslots[7]=memslots[2]\memslots[3]
    # Deallocating Ba5 in slot 2
    # Deallocating Bb5 in slot 3
    # Computing T2k7 = x*I+x*A+x*B2+x*B3+x*B4+x*B5
    coeff1=0.28457285753903816
    coeff2=0.11495283295141033
    coeff3=-0.0344930890633602
    coeff4=0.34606871085737384
    coeff5=-0.006442438999085179
    coeff6=1.4670072325444539
    # Smart lincomb recycle A
    memslots[1] .= coeff2.*memslots[1] .+ coeff3.*memslots[4] .+ coeff4.*memslots[5] .+ coeff5.*memslots[6] .+ coeff6.*memslots[7]
    mul!(memslots[1],true,I*coeff1,true,true)
    # Deallocating B2 in slot 4
    # Deallocating B3 in slot 5
    # Deallocating B4 in slot 6
    # Deallocating B5 in slot 7
    return memslots[1] # Returning T2k7
end

max_stars_repo_name: matrixfunctions/GraphMatFunData

max_issues_repo_name: matrixfunctions/GraphMatFunData

max_forks_repo_name: matrixfunctions/GraphMatFunData


text:
module Fields

export
    Face, Cell,
    AbstractField, Field, CellField, XFaceField, YFaceField, ZFaceField,
    interior, interiorparent,
    xnode, ynode, znode, location,
    set!,
    VelocityFields, TracerFields, tracernames, PressureFields, TendencyFields

using Oceananigans: Cell, Face
using Oceananigans.Grids
using Oceananigans.BoundaryConditions

include("field.jl")
include("set!.jl")
include("field_tuples.jl")
include("show_fields.jl")
include("boundary_function.jl")

end


text:
"""
Text align, e.g. :
"""
to_textalign(b, x) = x

# @default function legend(scene, kw_args)
#     backgroundcolor = to_color(backgroundcolor)
#     strokecolor = to_color(strokecolor)
#     strokewidth = to_float(strokewidth)
#     position = to_position(position)
#     gap = to_float(gap)
#     textgap = to_float(textgap)
#     labelwidth = to_float(labelwidth)
#     padding = to_float(padding)
#     align = to_textalign(align)
#     rotation = to_rotation(rotation)
#     textcolor = to_color(textcolor)
#     textsize = to_float(textsize)
#     markersize = to_markersize2d(markersize)
#     linepattern = to_positions(linepattern)
#     scatterpattern = to_positions(scatterpattern)
# end
@default function legend(scene, kw_args)
    backgroundcolor = to_color(backgroundcolor)
    strokecolor = to_color(strokecolor)
    strokewidth = to_float(strokewidth)
    position = to_position(position)
    gap = to_float(gap)
    textgap = to_float(textgap)
    labelwidth = to_float(labelwidth)
    padding = to_float(padding)
    outerpadding = to_markersize2d(outerpadding)
    align = to_textalign(align)
    rotation = to_rotation(rotation)
    textcolor = to_color(textcolor)
    textsize = to_float(textsize)
    markersize = to_markersize2d(markersize)
    linepattern = to_positions(linepattern)
    scatterpattern = to_positions(scatterpattern)
end

function make_label(p, plot, labeltext, i, attributes)
    w, gap, msize, tsize, lpattern, mpattern, padding = getindex.(attributes, (
        :labelwidth, :gap, :markersize, :textsize,
        :linepattern, :scatterpattern, :padding
    ))

    scale(x, w, pad, g, t) = Point2f0(
        pad + (x[1]w),
        pad + floor(t/2) + x[2]w + ((i - 1) * g)
    )

    return if plot.name in (:lines, :linesegment)
        linesegment(
            p, scale.(lpattern, w, padding, gap, tsize),
            color = plot[:color], linestyle = plot[:linestyle], show = false,
            camera = :pixel
        )
    else
        scatter(
            p, scale.(mpattern, w, padding, gap, tsize),
            markersize = msize, color = get(plot, :color, :black), show = false,
            camera = :pixel
        )
    end
end

function legend(scene::Scene, legends::AbstractVector{<:Scene}, labels::AbstractVector{<:String}, attributes)
    isempty(legends) && return
    N = length(legends)

    attributes = legend_defaults(scene, attributes)

    position, color, stroke, strokecolor, padding, opad = getindex.(attributes, (
        :position, :backgroundcolor, :strokewidth, :strokecolor, :padding,
        :outerpadding
    ))

    textbuffer = TextBuffer(Point2f0(0))

    args = getindex.(attributes, (
        :labelwidth, :gap, :textgap, :padding,
        :textsize, :textcolor, :rotation, :align
    ))

    legend = make_label.(scene, legends, labels, 1:N, attributes)

    lift_node(to_node(labels), args...) do labels, w, gap, tgap, padding, font...
        empty!(textbuffer)
        for i = 1:length(labels)
            yposition = (i - 1) * gap
            tsize = floor(font[1] / 2) # textsize at position one, half of it since we used centered align
            xy = Point2f0(w + padding + tgap, yposition + tsize + padding)
            append!(textbuffer, xy, labels[i], font...)
        end
        return
    end

    bblist = (native_visual.(legend)..., textbuffer.robj)
    screen = getscreen(scene)

    legendarea = lift_node(position, to_node(screen.area), opad, args[4:5]..., args[1:3]...) do xy, area, opad, padding, unused...
        bb = mapreduce(x-> value(x.boundingbox), union, bblist)
        mini = minimum(bb)
        wx, wy, _ = widths(bb) .+ mini
        xy = (xy .* widths(area))
        w, h = if isfinite(wx) && isfinite(wy)
            round.(Int, (wx, wy)) .+ padding
        else
            (0, 0)
        end
        # TODO check for overlaps, eliminate them!!
        dont_touch(area, IRect(xy[1], xy[2], w, h), opad)
    end
    legend_scene = Scene(
        scene, legendarea,
        color = to_value(color),
        stroke = (to_value(stroke), to_value(strokecolor))
    )
    # Nasty, but Scene doesn't accept signals... Guess at some point we will just fold
    # GLWindow into makie anyways (or the gl backend package)
    lscreen = legend_scene[:screen]
    lift_node(x-> (lscreen.color = x), color)
    lift_node((x...)-> (lscreen.stroke = x), stroke, strokecolor)
    show!.(legend_scene, legend)
    GLVisualize._view(textbuffer.robj, lscreen, camera = :fixed_pixel)
    Scene(attributes)
end

@default function color_legend(scene, kw_args)
    width = to_markersize2d(width)
    backgroundcolor = to_color(backgroundcolor)
    strokecolor = to_color(strokecolor)
    strokewidth = to_float(strokewidth)
    position = to_position(position)
    textgap = to_float(textgap)
    padding = to_markersize2d(padding)
    outerpadding = to_markersize2d(outerpadding)
    align = to_textalign(align)
    rotation = to_rotation(rotation)
    textcolor = to_color(textcolor)
    textsize = to_float(textsize)
end

function legend(scene::Scene, colormap::AbstractVector{<: Colorant}, range, attributes)
    attributes = color_legend_defaults(scene, attributes)
    attributes[:offset] = to_node(Vec3f0(0))
    attributes[:camera] = :pixel
    lscene = Scene(scene, attributes)

    padding, textsize, textcolor, align, textgap, width, position, opad = getindex.(attributes, (
        :padding, :textsize, :textcolor, :align, :textgap, :width, :position, :outerpadding
    ))

    vertices = Point3f0[(0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0)]
    mesh = GLNormalUVMesh(
        vertices = copy(vertices),
        faces = GLTriangle[(1, 2, 3), (3, 4, 1)],
        texturecoordinates = UV{Float32}[(0, 0), (0, 1), (0, 1), (0, 0)]
    )

    cmap_node = lift_node(to_node(colormap)) do cmap
        reshape(cmap, (length(cmap), 1))
    end
    tio = TextBuffer(Point2f0(0))
    area = to_node(scene[:screen].area)
    rect = lift_node(
                to_node(range), textsize, textcolor, align,
                textgap, width, padding, opad, position, area
            ) do r, ts, tc, a, tg, w, pad, opad, position, area

        empty!(tio)
        N = length(r)
        for i = 1:N
            o1 = (i-1) / (N - 1) # 0 to 1
            pos = Point2f0(w[1] + tg, (ts/2) + o1 * w[2]) .+ pad
            label = string(r[i])
            append!(tio, pos, label, ts, tc, Vec4f0(0, 0, 0, 1), a)
        end
        bbw, bbh, _ = widths(value(boundingbox(tio.robj)))
        rect = FRect(
            0, 0,
            w[1] + 2pad[1] + bbw + tg,
            2pad[2] + bbh + (ts/2)
        )
        p = (position .* widths(area))
        r2 = FRect(p, rect.w, rect.h)
        p = p .+ move_from_touch(FRect(area), r2, opad)
        lscene[:offset] = Vec3f0(p[1], p[2], 0)
        rect
    end
    meshnode = lift_node(width, padding, textsize) do w, pad, ts
        mesh.vertices .= broadcast(vertices) do v
            Point3f0(((Point2f0(v[1], v[2]) .* w) .+ Point2f0(0, ts/2) .+ pad)..., 0.0)
        end
        mesh
    end
    lvis = Makie.lines(
        lscene,
        rect,
        linewidth = attributes[:strokewidth],
        color = attributes[:strokecolor]
    )
    tio.robj[:model] = lvis.visual[:model]

    GLVisualize._view(tio.robj, getscreen(scene), camera = :fixed_pixel)
    Makie.mesh(lscene, meshnode, color = cmap_node, shading = false)
    lscene
end