On Thu, Jul 20, 2023 at 01:29:10PM +0000, '68th' via FriCAS - computer algebra system wrote: > ------- Original Message ------- > On Wednesday, July 19th, 2023 at 4:46 PM, Ralf Hemmecke <r...@hemmecke.org> > wrote: > > > Ah, you want to challenge me. ;-) No, honestly, I am grateful that you > > pose such questions. > > No, I don't want to challenge anybody. I just want to know how to get in > FriCAS what I want. I think it will be easier to achieve it with an example. > > > (323) -> eq := c^2 = a^2 + b^2 -(2ab)*cos(gamma) > > The reason why I enclosed 2ab in brackets is to visually separate it from > cosine. Otherwise one could think there are six variables: a, b, c, o, s, and > γ. That's not what I want FriCAS to distribute. > > > (324) -> map(x +-> subst(x,[a=(l+k)/2, b=(l-k)/2]), eq) >
Fixing syntax and naming results for easier reference: (5) -> eq1 := c^2 = a^2 + b^2 -(2*a*b)*cos(gamma) 2 2 2 (5) c = - 2 a b cos(gamma) + b + a Type: Equation(Expression(Integer)) (6) -> eq2 := map(x +-> subst(x,[a=(l+k)/2, b=(l-k)/2]), eq) 2 2 2 2 2 (- l + k )cos(gamma) + l + k (6) c = ------------------------------- 2 Type: Equation(Expression(Integer)) > > That's just a preliminary step. Now we get to the point. How to distribute > cos(γ) over (k²-l²) and then factor out k² and l² to derive > k²(1+cos(γ))+l²(1-cos(γ))? Well, see (adding divisions by 2 that you skipped): (9) -> k^2*(1+cos(gamma))/2 + l^2*(1-cos(gamma))/2 2 2 2 2 (- l + k )cos(gamma) + l + k (9) ------------------------------- 2 Type: Expression(Integer) So this is what we have above. To be really sure you can do: (10) -> rhs(eq2) - % (10) 0 Type: Expression(Integer) We got zero, so the two things are equal (just in case: % above means previous result). This is prefered style of calculations in FriCAS. In particular in many textbook algorithms there are tests for zero. If your expression is properly preprared (your input is simple happy case that needs no preparation), then checking for zero is as easy as above: you just look if result printed as zero. Systems "keep form" of expression have trouble with zero test: either system automatically simplifies expressions to 0, so does not "keep form" of zero, or you need special test for zero. FriCAS normally (as I mentioned, each FriCAS type can use it own rules) tries keep values is so called normal form, that is form where zero is clearly visible. For example (24) -> a := (sqrt(x^2 + 1) + 1)/x +------+ | 2 \|x + 1 + 1 (24) ------------- x Type: Expression(Integer) (25) -> b := x/(sqrt(x^2 + 1) - 1) x (25) ------------- +------+ | 2 \|x + 1 - 1 Type: Expression(Integer) (26) -> a - b (26) 0 Type: Expression(Integer) a and b look different, but subtraction shows that they are equal. There are more complicated cases like (27) -> sin(x)^2 + cos(x)^2 - 1 2 2 (27) sin(x) + cos(x) - 1 Type: Expression(Integer) This does not simplify in automatic way. But 'normalize' discovers that is is zero: (28) -> normalize(%) (28) 0 Type: Expression(Integer) Note: ATM 'normalize' gives you reliable 0 test for trigonometic or exponential functions. But if you add logarithms or inverse trigonometric functions things get more complicated. And 'normalize' is weaker than it should when handling algebraic functions. Anyway, if you want the check that result of calculation is zero, you should nomalize all inputs to your calculation, do the calculation and see if it is zero. Intermatiate results form normalize may look ugly and complicated, but this is powerful simplifcation when you want to compute with something. Coming back to your question, you can create expressions that look the way you want. First, I am not sure what you want to do with division by 2. So I simplify the expression by multiplying it by 2: (33) -> re := 2*rhs(eq2) 2 2 2 2 (33) (- l + k )cos(gamma) + l + k Type: Expression(Integer) Then we need list of kernels: (34) -> lk := kernels(re) (34) [cos(gamma), l, k] Type: List(Kernel(Expression(Integer))) We extract one of kernels, say l: (36) -> ker_l := lk(2) (36) l Type: Kernel(Expression(Integer)) Then 'univariate' separates expression with respect to powers of l (but for printing l is replaced by ?): (37) -> univariate(re, ker_l) 2 2 2 (37) (- cos(gamma) + 1)? + k cos(gamma) + k Type: Fraction(SparseUnivariatePolynomial(Expression(Integer))) To make things simple we extract numerator from the above (denominator is 1 and isn not printed): (38) -> nu := numer(%) 2 2 2 (38) (- cos(gamma) + 1)? + k cos(gamma) + k Type: SparseUnivariatePolynomial(Expression(Integer)) Now we can collect things back, but prevention them from normal simplification rules: (40) -> box(l^2*coefficient(nu, 2)) + box(coefficient(nu, 0)) 2 2 2 2 (40) k cos(gamma) + k + - l cos(gamma) + l Type: Expression(Integer) Note there is a glitch there: '-' before l^2 is inside box, '+' before that is '+' between boxes. This is very general technique: using 'kernels', 'univariate', 'numer', 'donom' and possibly recursing on kernels using 'operator' and 'argument' your routine can dissect expression and transform it in any desirable way. For results you can use 'box' or 'paren', or if only printing is involved you could produce an OutputForm. Note: that still does not control order of printouts, one would have to do slightly more. Of course, it would be very tedious to perform such commands like above by hand. But the nomal approach is that once you find short sequence of commands doung part of needed tranformation you generalize then and convert into function that you can reuse. So you can with come effort accumulate collection of functions performing transformations that you need. I would be better if FriCAS already had builting functions doing transformation that you want. But there is design effort to identify gnerally useful operations. Even more complicated issue it how to make them play nice with rest of FriCAS. For example, integrator to work properly needs to simplify things, which in practice means that as first step interator will "break" all your boxes and parens and arrange things back in defualt way. So possible altnative could be different type that "keeps form" of exprassions and chanes tham only given explicit commands. There were some "proof of concept" attempts to create such domain but nothing general and mature enough to include in FriCAS. Instead, people use limited approches that cover some case combined with ad-hoc tricks. -- Waldek Hebisch -- You received this message because you are subscribed to the Google Groups "FriCAS - computer algebra system" group. To unsubscribe from this group and stop receiving emails from it, send an email to fricas-devel+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/fricas-devel/ZLmCw8JD0ZKTR432%40fricas.math.uni.wroc.pl.