Carl Love

Carl Love

28035 Reputation

25 Badges

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

MaplePrimes Activity


These are replies submitted by Carl Love

Note the similarity in the two quoting styles: In both cases, both of the functions which must initially remain unevaluated get a pair of quotes. The difference is whether just the function names (Kitonum's Answer) or the whole function calls (my Answer) are quoted. I cannot explain the efficiency difference, nor have I thought much about it.

In either case, the square brackets are superfluous. They're just a red herring for this Question. If they improve the readability of your code, feel free to use them. (Warning: Generally extra square brackets are erroneous; this is a special case.)

Like Acer, I think that most nasty multiple-quoting situations should be and can be more gracefully and more robustly handled by using procedures.

Thanks, Acer.

By making a few modifications to only the first procedure, Params, (once again, fewer modifications than I was anticipating), I was able to include support for the end-of-parameters marker $. (Another thing that I love about Maple is that the final code is usually shorter than I was anticipating.) Including support for keyword parameters is also possible, but I don't see how they could be meaningfully used in this iteration scheme. Anyway, here's just the new  procedure:

Params:= proc(f::procedure)
description 
    `Extracts a procedure's parameter names, safely localized`
;
option remember;
local 
    PSq:= op(1, ToInert(eval(f))), #_Inert_PARAMSEQ(...)
    r:= [op(map(Param, PSq))], #parameter names as strings
    `$`:= evalb(r[-1] = "$") #Is end-of-parameters `$` used?
; 
    if `$` then r:= r[..-2] fi; #It's not really a parameter.
    return   
        convert~(parse~(r), `local`), #localized parameter names 
        PSq,  #exact inert parameter sequence
        `$` or hastype(PSq, specfunc(_Inert_ASSIGN)) #Is `proc` needed?
end proc
:    

 

@auliani3 Oops, you're right: Brian's posted worksheet does not use LPSolve to solve the integer linear program (ILP) for the 2- or 3-route cases. (It's easy to miss a detail like that while scanning a three-year-old thread.) I'll see if I can do something with it. But note that a small number (substantially less than the number of deliveries but greater than one) of routes (or truckloads) is computationally harder than the one-route case, which is known as a travelling salesman problem (TSP); so I don't know if LPSolve is up to the task. Ad hoc combinatorial solutions such as VV's do not use the huge number of decision variables that an ILP uses, and thus they're often more practical for small problems.

The posted textbook pages are incomplete and difficult to read, so maybe you can answer this for me: Does the cost of a trip include driving the empty truck(s) back to the warehouse? It seems that cost is equivalent to distance in this problem (which is likely a reasonable approximation of reality). But both storing the empty truck(s) near their final delivery point(s) (as with a one-way van rental) or driving them back to the warehouse seem like realistic cost-effective possibilities.

@acer The same factoring trick works for the next Fermat prime, 257:

factor(convert(cos(Pi/257), RootOf), sqrt(257));

Now you have two degree-64 polynomials (FWIW).

With a few modifications (fewer than I was anticipating), we can preserve the exact parameter sequence of the input procedure, meaning that the output procedure will include any parameter type declarations and default-value parameter assignments from the input. This involves a "transplant surgery" of the parameter sequence between the inert forms of the input and output procedures.

Params:= proc(f::procedure)
option remember;
local 
    PSq:= op(1, ToInert(eval(f))), #_Inert_PARAMSEQ(...)
    r:= [op(map(Param, PSq))]
; 
    if r[-1]="$" then
        error "end-of-parameters marker $ not allowed"
    else
        convert~(parse~(r), `local`), 
        PSq, 
        hastype(PSq, specfunc(_Inert_ASSIGN))
    fi
end proc
:
#This didn't need any changes. I just changed the indentation:    
Param:= (e::function)->
    if e::specfunc({_Inert_NAME, _Inert_ASSIGNEDNAME}) then 
        op(1,e)
    elif e::specfunc({_Inert_ASSIGN, _Inert_DCOLON}) then 
        op(thisproc(op(1,e)))
    elif e::specfunc(_Inert_SET) then
        error "keyword parameters not allowed", FromInert(e)
    else 
        error "unknown InertForm", e
    fi
:
Iter:= proc(f::procedure, n::nonnegint, p::posint:= 1)
local P, PSq, proc_flag, body, form;
    if n=1 then return eval(f) fi;
    (P, PSq, proc_flag):= Params(f);
    body:= 
        `if`(n=0, P[p], f(P[..p-1][], thisproc(f, n-1, p)(P[]), P[p+1..][]))
    ;
    form:= `if`(proc_flag, proc(_P) _F end proc, _P-> _F); 
    FromInert(subsop(1= PSq, ToInert(subs(_P= P[], _F= body, eval(form))))) 
end proc
:
#Examples:
y:= 1: #Global assigned value, for testing

for k from 0 to 3 do
    Iter((x::{name, function}, y, z)-> f(x,y,z), k) 
od;  
     (x::{name, function}, y, z)-> x 
     (x::{name, function}, y, z)-> f(x, y, z)
     (x::{name, function}, y, z)-> f(f(x, y, z), y, z)
     (x::{name, function}, y, z)-> f(f(f(x, y, z), y, z), y, z)

#If there are parameters with default values, then both the input and
#return procedures must be in proc form:
for k from 0 to 3 do 
    Iter(
        proc(x::{name,function}, y, z::{name,function,posint}:= 3) 
            f(x,y,z) 
        end proc, 
        k, #kth iterate
        2  #Iterate on the 2nd position
    ) 
od;
proc (x::{name, function}, y, z::{name, posint, function} := 3) 
    y 
end proc
proc (x::{name, function}, y, z::{name, posint, function} := 3) 
    f(x, y, z) 
end proc
proc (x::{name, function}, y, z::{name, posint, function} := 3) 
    f(x, f(x, y, z), z) 
end proc
proc (x::{name, function}, y, z::{name, posint, function} := 3) 
    f(x, f(x, f(x, y, z), z), z) 
end proc

 

@auliani3 There are 2- and 3-route solutions both in Brian Bovril's integer linear programming worksheet and in VV's "brute force" plaintext code.

@acer If by "nice form" you mean with no "large" square roots (i.e., no square roots of non integers), I can get that for sin(Pi/7) with evala(Normal(simplify(...))). In the following worksheet, `CPi/14` stands for cos(Pi/14), etc.
 

restart:

CP:= expand(cos(7*x));

64*cos(x)^7-112*cos(x)^5+56*cos(x)^3-7*cos(x)

`CPi/14`:= allvalues(RootOf(subs(cos(x)= _Z, CP), evalf(cos(Pi/14))));

(1/12)*6^(1/2)*((-28+(84*I)*3^(1/2))^(1/3)*((-28+(84*I)*3^(1/2))^(2/3)+14*(-28+(84*I)*3^(1/2))^(1/3)+28))^(1/2)/(-28+(84*I)*3^(1/2))^(1/3)

`CPi/7`:= eval(expand(cos(2*x)), cos(x)= `CPi/14`);

(1/12)*((-28+(84*I)*3^(1/2))^(2/3)+14*(-28+(84*I)*3^(1/2))^(1/3)+28)/(-28+(84*I)*3^(1/2))^(1/3)-1

`SPi/7`:= (numer/denom)(evala(Normal(simplify(eval(sqrt(1-x^2), x= `CPi/7`)))));

-(1/336)*7^(1/2)*(I*(-28+(84*I)*3^(1/2))^(2/3)*3^(1/2)+(4*I)*(-28+(84*I)*3^(1/2))^(1/3)*3^(1/2)-(-28+(84*I)*3^(1/2))^(2/3)-8*(-28+(84*I)*3^(1/2))^(1/3)+56)

evalf(abs(sin(Pi/7)-`SPi/7`));

0.5061624214e-9

 


 

Download sin_Pi_over_7.mw

I don't know how it could happen, but it looks like displayprecision was set to 7, but only inside the plot window. Yeah, it could be a bug, but there's much less chance of fixing it if it's not known how to reproduce it.

@tomleslie Thank you, Tom, for stepping up.

@Stretto Using 1D Input (aka Maple Input), enter the command that I originally gave, a %/ b * c. If you don't know what 1D Input means, I'll explain later. 

This should work in any input mode: 

`%/`(a,b)*c

but hopefully you won't need to "go there".

My comments about needing parentheses and needing to see the worksheet pertained to your examples with 3s and exponents, not to your original Question.

@Stretto I understand (and did understand) exactly what you want; no further explanation of that is necessary; I don't need to see (nor did I ask to see) a worksheet of your original problematic output; I know that it puts under c. In order to help you properly, I need to see the output of

interface(version); interface(prettyprint); interface(typesetting);

You make it exasperating for us to help you, and exasperating for yourself, by going off on tangents, such as what happens for expressions with exponents.

 

@Rouben Rostamian Your solution works if k evaluates to a name (as opposed to, say, a number), and f behaves reasonably when given symbolic input. If either of these things are not true, unevaluation quotes are needed, as in

['f(k)' $ 'k'= 0..5]

One thing that I like about is that it doesn't require introducing a bound variable, the k in this case.

If speed is a concern, seq is usually faster than either of these, and also faster than map. Unfortunately seq has ugly syntax.

@Stretto You're right, it's no different. To answer properly, I need to see exactly how it displays on your screen. Can you post an executed worksheet?

If you're using the command-line interface, I don't think that it's going to be possible to get the display that you want.

If you want it to simplify to 9, just use the regular operators, not the inert ones.

@Stretto Unfortunately, the operators do not have the same precedence as their regular counterparts. I'll admit that this is bad design on Maple's part. So, you need to use parentheses to clarify:

(3^3) %/ 3

This is different from (3^3)(%/3). This latter expression is probably something that you'd never actually want. And I'll explain what it does, if you'd care to know.

To answer properly, I need to know exactly how the output of the things that you show appears on the screen. The copy-and-paste mangles it.

If you give the command 

interface(displayprecision);

what is the result? If it's anything other than -1, then do

interface(displayprecision= -1);

Then explicitly delete the plot output (Ctrl-Delete), and rerun the plotting command. I'm just guessing that this might work.

First 227 228 229 230 231 232 233 Last Page 229 of 708