Carl Love

Carl Love

27636 Reputation

25 Badges

12 years, 103 days
Himself
Wayland, Massachusetts, United States
My name was formerly Carl Devore.

MaplePrimes Activity


These are answers submitted by Carl Love

(simplify@eval)(
    sqrt(a^2+b^2),
    solve({d-b = c-d, a/d = tan(45*Pi/180), a*(c-b)/2 = 60, a^2+c^2 = 19^2})
);

                               11

The variables sx, and y are clearly irrelevant because they only appear once in the problem.

Since the constraints are all easily made polynomial, this works also:

(simplify@@2)(
    sqrt(a^2+b^2), 
    {d-b = c-d, a/d = tan(45*Pi/180), a*(c-b)/2 = 60, a^2+c^2 = 19^2}
);

                               
11

This form of simplify requires only the constraints, not the objective, to be polynomial, or easily convertible to polynomial (as in a/d = ...). It's help page is ?simplify,siderels.

The extra simplify (as in simplify@@2) is unfortunately required to simplify sqrt(121) to 11. To avoid that awkwardness, you could do this:

(sqrt@simplify)(
    a^2+b^2, 
    {d-b = c-d, a/d = tan(45*Pi/180), a*(c-b)/2 = 60, a^2+c^2 = 19^2}
);

                               11

The other responders are making the mistake of assuming that all the variables are integer. The problem only requires AD to be integer. On a number line, let A, B, C, D 0, 7/3, 20/3, 21/3. Then AD = 7.

This is an excellent problem for testing any mathematical natural-language AI system. Solving it requires more than just middle-school Algebra I. This is a GRE-level problem (admittedly a fairly easy one). (GRE = Graduate Record Exam, a nationally standardized exam that one takes in the U.S. before applying to graduate school.)

@mmcdara In English, there is no ambiguity or lack of precision in this problem's statement. "Consecutive" means that they are distinct points, and are in the stated order. "Confounded" is not a word used in ordinary mathematical English; its only common usages are to describe mental states.

The diagram has two quadrilaterals that I'll call the "kite" and the "dart". They share two sides. I'll label these points as vertices:

  • A: point at the 60-degree angle
  • N: point where n is used
  • C: point in center where two lines cross
  • M: point where is used
  • X: point where x is used.

The kite is ANCM; the dart is XNCM. Now make two equations using that the sum of the angles of a quadrilateral is 360 degrees.

#quadrilateral ANCM:
Kite:= 60 + (180-2*n) + (180-40) + (180-2*m) = 360;
#       A       N           C          M
                 Kite := 560 - 2 m - 2 n = 360

#quadrilateral XNCM:
Dart:= x + n + (180+40) + m = 360;
#      X   N       C      M
                 Dart := x + m + 220 + n = 360

x = eval(x, solve({Kite, Dart}));
                             x = 40

 

Converting expr to disjunctive normal form makes it much easier to process. We will see that there's no solution, but there's a bug in solve that led you to believe that there was one. Of the 98 cases (as also mentioned by Christian Wolinski), solve finds a solution for 3, it's the same solution for all 3, and it's essentially the same solution that you got with RealDomain:-solve. But it's very easy to show (done below) that these solutions are incorrect.

restart;

expr := Or(And(-p^2 + 3*q < 0, p < 0, p^2 - 4*q < 0, Or(And(p < 0, -q < 0), p < 0, q < 0), Or(And(-2*p^2 + 3*q < 0, -q^2 < 0), And(p <= 0, Or(-2*p^2 + 3*q < 0, q^2 < 0))), Or(And(Or(And(p < 0, -q < 0), p < 0, q < 0), Or(And(-2*p^2 + 3*q < 0, -q^2 < 0), And(p <= 0, Or(-2*p^2 + 3*q < 0, q^2 < 0)))), And(p < 0, -q < 0), p < 0, q < 0, And(2*p^2 - 3*q < 0, -q^2 < 0), And(-p <= 0, Or(2*p^2 - 3*q < 0, q^2 < 0))), -2*p^5 + 15*p^3*q - 27*p*q^2 <= 0, p^2*q^2 - 4*q^3 = 0), And(p^2 - 3*q = 0, p < 0, -2*p^2 + 3*q < 0, Or(And(p < 0, -2*p^2 + 3*q < 0), p < 0, 2*p^2 - 3*q < 0), 2*p^3 - 9*p*q = 0), And(-p^2 + 3*q < 0, Or(And(p < 0, p^2 - 4*q < 0), p < 0, -p^2 + 4*q < 0), p < 0, -q < 0, Or(And(-2*p^2 + 3*q < 0, -q^2 < 0), And(-p <= 0, Or(-2*p^2 + 3*q < 0, q^2 < 0))), Or(And(p < 0, -q < 0, Or(And(-2*p^2 + 3*q < 0, -q^2 < 0), And(-p <= 0, Or(-2*p^2 + 3*q < 0, q^2 < 0)))), And(p < 0, -q < 0), And(2*p^2 - 3*q < 0, -q^2 < 0), And(p <= 0, Or(2*p^2 - 3*q < 0, q^2 < 0))), 2*p^5 - 15*p^3*q + 27*p*q^2 <= 0, p^2*q^2 - 4*q^3 = 0)):

Convert to disjunctive normal form (DNF):

use L= Logic in    
    DFT:= eval(
        L:-Convert(eval(expr, [And= L:-`&and`, Or= L:-`&or`]), 'DNF'),
        [L:-`&and`= `{}`, L:-`&or`= `[]`]
     )
end use:

Verify accuracy and feasibility:

nops(%), indets~((S:= {%[]}), name), nops~(S),
type(DFT, list(set({`=`, `<`, `<=`}))), nops~((eq:= select~(type, S, `=`))),
indets~(eq, name);

98, {{p, q}}, {4, 5, 7, 8, 9, 10, 11}, true, {1, 2}, {{p, q}}

Separate sets that should be solved for 1 variable and those solved for 2, based on the number of equations in the set:

(eqs1, eqs2):= selectremove(s-> nops(indets(s, `=`))=1, S):

sols:= remove~(rhs=(), map~(1@@0@curry(op,1)@`[]`=solve, [eqs1$2, eqs2], [{p}, {q}, {p,q}]));

sols := [{{p^2*q^2-4*q^3 = 0, -p <= 0, 2*p^5-15*p^3*q+27*p*q^2 <= 0, p < 0, -q < 0, -2*p^2+3*q < 0, -p^2+3*q < 0} = piecewise(q <= 0, [], 0 < q, [{p = -2*sqrt(q)}, {p = 2*sqrt(q)}]), {p^2*q^2-4*q^3 = 0, 2*p^5-15*p^3*q+27*p*q^2 <= 0, p < 0, -q < 0, -q^2 < 0, -2*p^2+3*q < 0, -p^2+3*q < 0} = piecewise(q <= 0, [], 0 < q, [{p = -2*sqrt(q)}, {p = 2*sqrt(q)}]), {p^2*q^2-4*q^3 = 0, -p <= 0, 2*p^5-15*p^3*q+27*p*q^2 <= 0, p < 0, -q < 0, -q^2 < 0, -2*p^2+3*q < 0, -p^2+3*q < 0} = piecewise(q <= 0, [], 0 < q, [{p = -2*sqrt(q)}, {p = 2*sqrt(q)}])}, {}, {}]

L:= lhs~(sols[1]): <L[]>;

Vector(3, {(1) = {p^2*q^2-4*q^3 = 0, -p <= 0, 2*p^5-15*p^3*q+27*p*q^2 <= 0, p < 0, -q < 0, -2*p^2+3*q < 0, -p^2+3*q < 0}, (2) = {p^2*q^2-4*q^3 = 0, 2*p^5-15*p^3*q+27*p*q^2 <= 0, p < 0, -q < 0, -q^2 < 0, -2*p^2+3*q < 0, -p^2+3*q < 0}, (3) = {p^2*q^2-4*q^3 = 0, -p <= 0, 2*p^5-15*p^3*q+27*p*q^2 <= 0, p < 0, -q < 0, -q^2 < 0, -2*p^2+3*q < 0, -p^2+3*q < 0}})

rhs~(sols[1])[];

piecewise(q <= 0, [], 0 < q, [{p = -2*sqrt(q)}, {p = 2*sqrt(q)}])

So q=1, p=2 is a witness, which we'll test:

W:= [q=1, p=2]:

ormap(evalb, andmap~(evalb, eval(L, W)));

false

It's a bug in solve! Easy to confirm by eye also:

eval(L, W);

{{0 = 0, -2 <= 0, -5 < 0, -1 < 0, 2 < 0}}

Note the 2 < 0.

map(solve, L, {q}), map(solve, L, {p,q}, parametric);

{}, {[]}

evalb(eval(eval(expr, W), [And= `and`, Or= `or`]));

false

Download DisNormForm.mw

The command Worksheet:-WorksheetToMapleText should do most of the work of converting a worksheet to a procedure. You'll still need to do a little clean-up by hand. Save the worksheet without output (Ctrl-D) before doing this.

Yes, the not-publically-documented command for doing this is `tools/genglobal`. Most commands that generate arbitrary constant names use it. I believe that dsolve used to use it but doesn't anymore, instead always using _C1_C2, ..., possibly aliased to c__1c__2, .... So, we just put a little wrapper around commands to change the constants:

restart:
SeqConst:= proc(e, prefix::symbol:= :-_C, new_prefix::symbol:= :-_C)
    subsindets['flat', 2](e, suffixed(prefix, nonnegint), new_prefix, `tools/genglobal`[1]) 
end proc
:
SeqConst(dsolve(diff(y(x),x)=2*y(x)));

                             y(x) = _C2 exp(2 x)

SeqConst(dsolve(diff(y(x),x)=3*y(x)));
                             y(x) = _C3 exp(3 x)
 

Here is my Maple implementation of the Mathematica command Cases that you showed. If that command allows more-complicated patterns or wildcards that you'd like implemented, let me know. The objects in the pattern are either types or the triple-underscore zero-or-more-of-anything wildcard. (All explicit numbers are also considered types in Maple.)

WildcardPatternPredicate:= proc(Pat::list({type, identical(:-___)}))
local P:= Array(1..0, datatype= integer[1]), t, k, np:= nops(Pat);
    for k,t in Pat do
        P,= `if`(k=1, "proc(", `if`(k<np or t::type, ", ", ""));
        if t::type then P,= sprintf("%a::(%a)", _||k, t);
        elif k=np then break
        elif (t:= Pat[k+1]) = :-___ then next
        else P,= sprintf("%a::seq(Not(%a))", _||k, t)
        fi
    od;
    if t::type then P,= ", $" else np-- fi;
    P,= sprintf(") option overload; %a; true end proc", _||np);
    overload([parse(String(P)), ()-> false])@op
end proc
:
Cases:= (L, P::list({type, identical(:-___)}))->
    select(WildcardPatternPredicate(P), L)
:
Cases(combinat:-permute(4), [___,2,___,3,___]);
   [[1, 2, 3, 4], [1, 2, 4, 3], [1, 4, 2, 3], [2, 1, 3, 4], 
     [2, 1, 4, 3], [2, 3, 1, 4], [2, 3, 4, 1], [2, 4, 1, 3], 
     [2, 4, 3, 1], [4, 1, 2, 3], [4, 2, 1, 3], [4, 2, 3, 1]]

#Large-case time test:
CodeTools:-Usage(Cases(combinat:-permute(9), [___,2,___,3,___])):
nops(%) = 9!/2;
memory used=1.99GiB, alloc change=169.75MiB, 
cpu time=3.16s, real time=6.99s, gc time=2.55s

                        181440 = 181440


The brilliant idea of using overload with the seq parameter modifier to effectively allow type-checking of expression sequences is due to @sursumCorda . Turning the patterns into predicates would be much more complicated without this idea.

This method is somewhat slower than most of the other methods presented in this thread, but it's not horribly slow. However, the patterns that it can handle are much more complicated than just permutations; in particular, the non-wildcards can be any type; they needn't be specific entities such as 2 or 3

I don't know the extent of all your cases, but in this case the following does it:

primpart(factor(expr));
                        40 x - 24 y - 3

primpart returns what's left after all the constants have been factored out.

Your error was mixing up the argument order for has. The object being searched is its first argument; the things being searched for (disjunctively) are its second argument.

I know that you like rule-based and pattern-based constructs. Unfortunately, the command applyrule (and its ilk, such as patmatch) has very limited capability, was written decades ago, the writer likely left Maple decades ago, and likely will never be significantly improved. So, you might as well stop torturing yourself by trying to use these commands, because it's usually impossible. (There might be a way to use applyrule in this case, but I'm not going to take the time to find out.)

Here's a way with subsindets:

subsindets(
    eq, `*`,   
    proc(e) 
    local (S,R):= selectremove(type, e, anything^(And(fraction, 2 &under denom)));
        `if`(denom(R)=1 or S=1, e, R %* S)
    end proc
);    

There are a vast number of features of the Maple language that do not work in 2D Input. Using `?` in symbols (names) is one of them. For many of the features that don't work in 2D, that fact is mentioned on the help page of the feature.

I've always found the depends parameter modifier to be undependable. (Note for other readers: This has nothing to do with the depends command.) I'd guess that your goal is to make the 2 essentially a parameter of a procedure-valued procedure so that such procedures can be constructed on-the-fly for pattern matching. Here's a way to do it:

f3:= subs(_ty= 2, proc(x::seq(Not(_ty)), y::_ty) [[x], [y]] end proc):
f3(0, 1, 2);

                         [[0, 1], [2]]

The repeated use of abs(...)^2 in the equation strongly suggests that a complex solution is expected. To get complex solutions from fsolve, include complex as the last argument. Doing that, I get

             tg := -3.401652391 - 3.401652391*I

There may be other complex solutions.

Factoring the non-constant terms of the polynomial is sufficient to control the wild oscillations:

restart:
p0:= expand(2*sin(45*arcsin(x/2)));
p:= factor(p0) - sqrt(7-sqrt(5)-sqrt(30-6*sqrt(5)))/2;
plot(p, x= -2.1..2.1, numpoints= 1000, size= [1500,300]);

The stated task can be done in Maple by

{seq}([seq](p[]), p= Iterator:-TopologicalSorts(4, {2<3}));

{[1, 2, 3, 4], [1, 2, 4, 3], [1, 4, 2, 3], [2, 1, 3, 4], [2, 1, 4, 3], [2, 3, 1, 4],
 [2, 3, 4, 1], [2, 4, 1, 3], [2, 4, 3, 1], [4, 1, 2, 3], [4, 2, 1, 3], [4, 2, 3, 1]}

You can put any number of inequalities in the second argument.

This command does not generate all the permutations and then filter them to get the ones that match the pattern. Rather, it generates only the ones that match in the first place.

You wrote:

L:=combinat:-permute([1,2,3,4]);
map(X->`if`(has(X,2) and has(X,3) and ListTools:-Search(2,X)<ListTools:-Search(3,X),X,NULL) ,L);

The commands has and member are not the same thing! Using has for a job that can be done by member can be very inefficient and sometimes incorrect. Also, one shouldn't use map for a job that can be done by select (however, that's only slightly inefficient). Your code can be replaced by

select(P-> member(2,P,'p') and member(3,P,'q') and p<q, combinat:-permute(4));


Here's a little example that highlights the crucial difference between has and member:

L:= [3, x+2];
has(L,2);
                              true
member(2,L)
                             false

 

All your for loops could be replaced by a single very short elementwise operation:

Test:= Q =~ Multi

See help page ?elementwise.

It looks like you're trying to invert a symbolic 5x5 matrix by solving a system of equations. You could instead simply ask Maple for the inverse:

MAinv:= 1/MA

There is a tremendous amount known about symbolic matrix inverses, but perhaps you want to see what you discover on your own. That's fine. I won't spoil it by disclosing any findings. But I'll hint to you that you'll discover the same things easier if you make MA a 3x3 matrix. And you can make its entries such that you can tell immediately which row and column they come from:

M:= <a1,a2,a3; b1,b2,b3; c1,c2,c3>

2 3 4 5 6 7 8 Last Page 4 of 392