I have several equations that specify relationships between elements of an ellipse (minor and major semi axis, eccentricity, pericenter and apocenter distance, focal parameter).
I want to find other formulas that express each of those elements through combinations of all other elements. solve() works perfectly fine on some combinations, but not the other.
What is the difference between those cases and how I can make it solve?
sys:[b=a*sqrt(1-e^2),p=a*(1-e^2),c=a*(1+e),d=a*(1-e)];
solve(sys,[a,b,e,p]);
solve(sys,[a,b,e,c]);
solve(sys,[a,b,e,d]);
solve(sys,[a,b,p,c]);
solve(sys,[a,b,p,d]);
solve(sys,[a,b,c,d]);
/* solve(sys,[a,e,p,c]); -- gives error */
/* solve(sys,[a,e,p,d]); -- gives error */
/* solve(sys,[a,e,c,d]); -- gives error */
solve(sys,[a,p,c,d]);
solve(sys,[b,e,p,c]);
solve(sys,[b,e,p,d]);
solve(sys,[b,e,c,d]);
solve(sys,[b,p,c,d]);
solve(sys,[e,p,c,d]);
Here is output for "good" and "bad" case:
(%i5) solve(sys,[a,b,c,d]);
2
p sqrt(1 - e ) p p p
(%o5) [[a = - ------, b = - --------------, c = - -----, d = -----]]
2 2 e - 1 e + 1
e - 1 e - 1
(%i6) solve(sys,[a,e,p,c]);
algsys: tried and failed to reduce system to a polynomial in one variable; give up.
-- an error. To debug this try: debugmode(true);
Try to_poly_solve on these. It is a share package -- you have to enter load(to_poly_solve); before calling it.
Related
I recently posted on here to get help with a formula, here is the link...https://stackoverflow.com/questions/75068029/vlook-up-style-forumla-but-range-is-2-cells A user called rockinfreakshow was really awesome and provided a great solution for me. I'm not very experienced and don't understand what the formula at all but I'd love to be able to add more attributes to it. Is anyone able to help break it down for me ?
I havent tried anything here, it's totally out of my realm of understanding
=MAKEARRAY(COUNTA(B2:B),COUNTA(D1:O1),LAMBDA(r,c,IF(REGEXMATCH(LAMBDA(ax,bx,IFS(REGEXMATCH(ax,"Mixed")*REGEXMATCH(INDEX(C2:C,r),"Blend")*REGEXMATCH(INDEX(C2:C,r),"Filter"),"BLEND-"&bx&"|FILTER-"&bx,REGEXMATCH(ax,"Mixed")*NOT(REGEXMATCH(INDEX(C2:C,r),"Blend"))*REGEXMATCH(INDEX(C2:C,r),"Filter"),"ESP-"&bx&"|FILTER-"&bx,REGEXMATCH(ax,"Mixed")*NOT(REGEXMATCH(INDEX(C2:C,r),"Filter")),"BLEND-"&bx&"|ESP-"&bx,LEN(ax),SUBSTITUTE(ax&"-"&bx,"Espresso","ESP")))(regexextract(INDEX(B2:B,r),"([^\s]*?) Subscription"),IFNA(SWITCH(REGEXEXTRACT(INDEX(C2:C,r),"Small|Medium|Large"),"Small",250,"Medium",450,"Large",900),SWITCH(REGEXEXTRACT(INDEX(B2:B,r),"Medium|Large"),"Medium",225,"Large",450))),"(?i)"&INDEX(D1:O1,,c)),1,)))
see the WHY LAMBDA? part of this answer to understand the LAMBDA
the formula contains 2x LAMBDA and there are a total of 4 placeholders which translates to:
r - COUNTA(B2:B)
c - COUNTA(D1:O1)
ax - REGEXEXTRACT(INDEX(B2:B, r), "([^\s]*?) Subscription")
bx - IFNA(SWITCH(REGEXEXTRACT(INDEX(C2:C, r), "Small|Medium|Large"),
"Small", 250, "Medium", 450, "Large", 900),
SWITCH(REGEXEXTRACT(INDEX(B2:B, r), "Medium|Large"),
"Medium", 225, "Large", 450))
r counts how many items are in B column
c counts how many items are in row 1 of range D1:O1
ax extracts the word from B column that precedes the word Subscription
bx is a bit complex but essentially it extracts from C column word Small or Medium or Large and replaces it with 250, 450 or 900 respectively. then if C column does not contain one of those 3 words it checks for Medium or Large within B column and assigns 225 or 450 respectively
what we are left with is the core of the formula:
IFS( REGEXMATCH(ax, "Mixed")*
REGEXMATCH(INDEX(C2:C, r), "Blend")*
REGEXMATCH(INDEX(C2:C, r), "Filter"), "BLEND-"&bx&"|FILTER-"&bx,
___________________________________________________________________________
REGEXMATCH(ax, "Mixed")*
NOT(REGEXMATCH(INDEX(C2:C, r), "Blend"))*
REGEXMATCH(INDEX(C2:C, r), "Filter"), "ESP-"&bx&"|FILTER-"&bx,
___________________________________________________________________________
REGEXMATCH(ax, "Mixed")*
NOT(REGEXMATCH(INDEX(C2:C, r), "Filter")), "BLEND-"&bx&"|ESP-"&bx,
___________________________________________________________________________
LEN(ax), SUBSTITUTE(ax&"-"&bx, "Espresso", "ESP"))
for better visualization, the IFS formula contains only 4 elements. each of these 4 elements acts as a switch - if there is a match x we get output y. for example let's dissect the first element...
REGEXMATCH(ax, "Mixed")*
REGEXMATCH(INDEX(C2:C, r), "Blend")*
REGEXMATCH(INDEX(C2:C, r), "Filter"), "BLEND-"&bx&"|FILTER-"&bx
there are 3x REGEXMATCHes multiplied by each other. whenever there is such multiplication in array formulae it translates as AND logic gate (if there would be + it would mean OR logic gate) eg.:
1 * 1 = 1
1 * 0 = 0
0 * 1 = 0
0 * 0 = 0
REGEXMATCH outputs TRUE or FALSE so if we get 3x TRUE the whole argument is considered as TRUE (because 1 * 1 * 1 = 1) so we proceed to output our first switch
therefore if B column contains Mixed and C column contains Blend and C column contains Filter then we output Blend-000|Filter-000 where 000 stands for a specific number determined from bx placeholder/formula and also you can notice the | (which btw stands for OR logic within the regex) but in this case, it's just a unique symbol to join stuff for REGEXMATCH. which REGEXMATCH is this for you may ask? ...this one:
so the output of IFS formula is the input for most outer REGEXMATCH and we check if the IFS output matches something within D1:O1 range. IF yes then output 1 otherwise output nothing. shortened:
IF(REGEXMATCH(IFS(...), "(?i)"&INDEX(D1:O1,,c), 1, )
(?i) in regex means "case insensitive". it is there just for safety reasons because regex is by default case sensitive.
and we reached the MAKEARRAY formula that creates an array of numbers across the whole range with height r and width c where output is the result of IF eg. either 1 or empty cell
This code checks that the value a maps uniquely for the values 1 to 100 using the formula (a^x) % 101
local function f(a)
found = {}
bijective = true
for x = 1, 100 do
value = (a^x) % 101
if found[value] then
bijective = false
break
else
found[value] = x
end
end
return bijective
end
However does not produce the expected result.
it maps 2^65 % 101 to 56, which matches the value produced by 2^12 % 101 and I get a false result, however the correct value for 2^65 % 101 is 57 and 2 actually should produce all unique values resulting in a true result.
The error described above is specifically on Lua 5.1, is this just a quirk of Lua's number typing? Is there a way to make this function work correctly in 5.1?
The error described above is specifically on Lua 5.1, is this just a quirk of Lua's number typing? Is there a way to make this function work correctly in 5.1?
First of all, this is not an issue with Lua's number typing since 2^65, being a (rather small) power of two, can be represented exactly by the double precision since it uses an exponent-mantissa representation. The mantissa can simply be set to all zeroes (leading one is implicit) and the exponent must be set to 65 (+ offset).
I tried this on different Lua versions and PUC Lua 5.1 & 5.2 as well as LuaJIT have the issue; Lua 5.3 (and presumably later versions as well) are fine. Interestingly, using math.fmod(2^65, 101) returns the correct result on the older Lua versions but 2^65 % 101 does not (it returns 0 instead).
This surprised me so I dug in the Lua 5.1 sources. This is the implementation of math.fmod:
#include <math.h>
...
static int math_fmod (lua_State *L) {
lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
return 1;
}
this also is the only place where fmod from math.h appears to be used. The % operator on the other hand is implemented as documented in the reference manual:
#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b))
in src/luaconf.h. You could trivially redefine it as fmod(a,b) to fix your issue. In fact Lua 5.4 does something similar and even provides an elaborate explanation in its sources!
/*
** modulo: defined as 'a - floor(a/b)*b'; the direct computation
** using this definition has several problems with rounding errors,
** so it is better to use 'fmod'. 'fmod' gives the result of
** 'a - trunc(a/b)*b', and therefore must be corrected when
** 'trunc(a/b) ~= floor(a/b)'. That happens when the division has a
** non-integer negative result: non-integer result is equivalent to
** a non-zero remainder 'm'; negative result is equivalent to 'a' and
** 'b' with different signs, or 'm' and 'b' with different signs
** (as the result 'm' of 'fmod' has the same sign of 'a').
*/
#if !defined(luai_nummod)
#define luai_nummod(L,a,b,m) \
{ (void)L; (m) = l_mathop(fmod)(a,b); \
if (((m) > 0) ? (b) < 0 : ((m) < 0 && (b) > 0)) (m) += (b); }
#endif
Is there a way to make this function work correctly in 5.1?
Yes: The easy way is to use fmod. This may work for these particular numbers since they still fit in doubles due to the base being 2 and the exponent being moderately small, but it won't work in the general case. The better approach is to leverage modular arithmetics to keep your intermediate results small, never storing numbers significantly larger than 101^2 since (a * b) % c == (a % c) * (b % c).
local function f(a)
found = {}
bijective = true
local value = 1
for _ = 1, 100 do
value = (value * a) % 101 -- a^x % 101
if found[value] then
bijective = false
break
else
found[value] = x
end
end
return bijective
end
While developing BigZ, mostly used for number theoretical experiments, I've discovered the need of orthogonality in the word-set that create, filter or transform sets. I want a few words that logically combinated cover a wide range of commands, without the need to memorize a large number of words and ways to combinate them.
1 100 condition isprime create-set
put the set of all prime numbers between 1 and 100 on a set stack, while
function 1+ transform-set
transform this set to the set of all numbers p+1, where p is a prime less than 100.
Further,
condition sqr filter-set
leaves the set of all perfect squares on the form p+1 on the stack.
This works rather nice for sets of natural numbers, but to be able to create, filter and transform sets of n-tuples I need to be able to count locals in unnamed words. I have redesigned words to shortly denote compound conditions and functions:
: ~ :noname ;
: :| postpone locals| ; immediate
1 100 ~ :| p | p is prime p 2 + isprime p 2 - isprime or and ;
1 100 ~ :| a b | a dup * b dup * + isprime ;
Executing this two examples gives the parameter stack ( 1 100 xt ) but to be able to handle this right, in the first case a set of numbers and in the second case a set of pairs should be produced, I'll have to complement the word :| to get ( 1 100 xt n ) where n is the numbet of locals used. I think one could use >IN and PARSE to do this, but it was a long time ago I did such things, so I doubt I can do it properly nowadays.
I didn't understand (LOCALS) but with patience and luck I managed to do it with my original idea:
: bl# \ ad n -- m
over + swap 0 -rot
do i c# bl = +
loop negate ;
\ count the number of blanks in the string ad n
variable loc#
: locals# \ --
>in # >r
[char] | parse bl# loc# !
r> >in ! ; immediate
\ count the number of locals while loading
: -| \ --
postpone locals#
postpone locals| ; immediate
\ replace LOCALS|
Now
: test -| a b | a b + ;
works as LOCALS| but leave the number of locals in the global variable loc#.
Maybe you should drop LOCALS| and parse the local variables yourself. For each one, call (LOCAL) with its name, and end with passing an empty string.
See http://lars.nocrew.org/dpans/dpans13.htm#13.6.1.0086 for details.
I implemented the bubble sort method in Maxima as:
burbuja(l) := block(
for i : 1 step 1 thru length(l) do (
for j : length(l) - 1 step -1 while j >= i do (
if l[j] > l[j + 1] then (
elemento : l[j],
l[j] : l[j + 1],
l[j + 1] : elemento
)
)
), print(l)
);
The problem is that the output is something like this:
(%i1) burbuja([3,2,1]);
[1, 2, 3]
(%o1) [1, 2, 3]
If I remove print(l) from the penultimate line, this is the output:
(%i1) burbuja([3,2,1]);
(%o1) done
The question is how can I print the result without duplicating it?
Thanks.
Instead of print(l) just put l to return the value of l from the function. (Do not put return(l) as the effect of return is actually somewhat different from other languages.)
I also recommend copying the list before sorting it, so that you don't modify the original list. Try l : copy(l) before anything else.
As a complement of Robert Dodier's answer, some more words for explaining what is happening. Maxima has a functional language with following features:
last term in a block is also the value "returned" by this block;
print has to be taken as a function rather than a mere statement.
These two ideas explain what happend in your case:
the print(l) in your code performs something on your screen but also is an expression evaluating to l (try for instance something like a:print(5)$ which will print the number 5 but also assign the value 5 to the variable a;
since print(l) is also the last term in your block, your block will evaluate to l.
Thus your code prints l and also "return" it.
I found the problem. Instead of print(l) I should use append(l).
Formula which I wanna solve looks like this in C:
#define foo(w,x,y) ((((w)*(x)*(y)+31) & ~31) / 8)
WORD w,x,y,z;
y = 24;
if( (foo(w,x,y) * z) == -1 )
printf("yeah!");
I rewrite it to z3py in the following way:
from z3 import *
w= BitVec('w',16)
x= BitVec('x',16)
z= BitVec('z',16)
y= BitVecVal(24,16)
solve( (UDiv( (w*x*y+31) & ~31, 8 )) * z == 0xffffffff)
Any suggestions ?
PS: Please notice that trying to solve formula in that form:
solve( (UDiv( (w*x*y+31), 8 )) * z == 0xffffffff)
is possible, so I can't belive that bit-wise operation causes this formula Unsatisfiable.
I don't see anything wrong in Z3 behavior. Why do you think the formula should be satisfiable?
A = (w*x*y+31) & ~31 -- imply that the 5 rightmost bits will be always zero
B = UDiv( A & ~31, 8 ) (equal to a logical shift right by 3) -- imply that the 2 rightmost bits will be always zero.
C = B * z -- this will always have the 2 rightmost bits zero
c == 0xffffffff -- that's impossible
If you change the constant to 0xfffffffc, then you'll get a solution.
The C program doesn't print anything for me. And Z3 says "no solution". So, it's consistent.
Does your C program prints "yeah!"? If so, aren't you on a big-endian machine? I've tried your example in an x86 machine.