Carl Love

Carl Love

28055 Reputation

25 Badges

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

MaplePrimes Activity


These are answers submitted by Carl Love

I can't work with your equations because of the reason that I just wrote in the Reply above. But apparently you already have some means of solving them (which command?). So, just add one more equation that expresses that you want the sum of the variables to be 32. That can be done simply as follows. Suppose that the list of equations in your worksheet is named Eqns. Then do

Con:= add(indets(Eqns, name)) = 32: #Constraint
Sys:= [Eqns[], Con]:

And proceed to solve Sys by whatever means you were using to solve Eqns.

Of course, this idea is worthless if your unspecified solver reduces all constants (such as the 32) modulo 2.

Some evaluations, such as simple arithmetic with explicitly numeric operands, are always done regardless of the encapsulation with -> or proc ... end proc or '...'. These are called automatic simplifications. That's what's happening with 2+3. If you have a specific need to prevent such an evaluation, please ask, because there are some specialized techniques available.

Except for the few usually innocuous automatic simplifications, the expression on the right side of the -> is not evaluated at the time that the arrow expression is created. In the vast, vast majority of cases of automatic simplification, its use does not change the final result. Obviously such is the case with 2+3.

Regarding your second question: If you want to evaluate first, then turn the result into an arrow expression, the standard command for that is unapply:

unapply(int(1,y), x);

Note that x-> e and proc(x) e end proc are semantically equivalent for any symbol x and expression e (which likely (but not necessarily) depends on x).

The usual way is to run in "batch mode"; that is, run command-line Maple with its input coming from and its output going to files specified on the command line that initiates the Maple session. See ?Maple for details of command-line options.

Here's a way to do it, but I suspect that there's an easier way. Suppose that MkL, and have already been defined. Then do 

Z:= Matrix(M$2): #All zero
T:= 
   Matrix((2^(k-1))$2, (i,j)-> `if`(i=j, L, F), shape= triangular[upper]) + 
   Matrix((2^(k-1))$2, (i,j)-> `if`(i=j, 0, Z), shape= triangular[lower])
:
P:= Matrix((2^(k-1)*M)$2, (i,j)-> T[iquo(i-1,M,'r')+1, iquo(j-1,M,'c')+1][r+1, c+1])/2^k;

The difference between my Answer and Tom's is that I've deconstructed the blocks so that the result is a "flat" Matrix.

Here's a complete implementation of RSA (key generation, encryption, and decryption). Maple makes this surprisingly easy. Notice that it's not much longer than your procedure, whose function is performed by my one-line procedure Stringify.

RSA:= module()
export
   bytelen:= 8,
   GenKey:= proc(B::And(posint, satisfies(B-> B>3)), seed::posint:= ())
   local r:= randomize(seed), p, q, C, e, d, R;
      p:= nextprime(rand(2^B..2^(B+1))());
      R:= rand(2^(B+5)..2^(B+6));
      do q:= nextprime(R()) until igcd(p-1, q-1) = 2;    
      C:= (p-1)*(q-1)/2;
      R:= rand(3..C-1);
      do e:= R() until igcd(e, C) = 1;
      if seed=() then randomize(r) fi;
      p*q, e, (1/e mod C)
   end proc,

   Encrypt:= (S::string, n::posint, e::posint)-> 
      Chunkify(
         sprintf("%m", Numerify~(Chunkify(S, iquo(ilog2(n),bytelen))) &^ ~ e mod n),
         interface('screenwidth')
      ),
   Decrypt:= (S::list(string), n::posint, d::posint)->
      cat(Stringify~(sscanf(cat(S[]), "%m")[] &^ ~ d mod n)[]),

   Chunkify:= proc(S::string, L::posint)
   local k, r, len:= length(S);
      [seq(S[1+L*(k-1)..min(L*k,len)], k= 1..iquo(len,L,r)+`if`(r>0,1,0))]
   end proc,

   Numerify:= (S::string)-> 
      convert(convert(S, bytes), base, 2^bytelen, 2^(length(S)*bytelen))[],
   Stringify:= (N::posint)-> cat(convert(convert(N, base, 2^bytelen), bytes)),
`;`;
end module:

Example usage:

(n,e,d):= RSA:-GenKey(32);
   n, e, d := 1570972592032860729287, 122831757217576938571, 
     678402947328820371811
S:= "It's so easy and so much fun to write an RSA module in Maple!":
E:= RSA:-Encrypt(S, n, e);
E := 
  ["7*"7>xa***p9OT`O""7&prhA'H;w!37""7p#**zDPbe$yf:"7AJG!Q%e'*)*[a5"6Ty!yo%*\+8T]"7", 
  "rB?_()RpV(3d""7$="y+67I`,^7"6[6%4Tr(ogYe("]

RSA:-Decrypt(E, n, d);
"It's so easy and so much fun to write an RSA module in Maple!"

Maple has special commands (such as ilog10, ilog2, iquo, irem, ilcm, igcd, &^, and mod) for high-speed large-integer arithmetic. You should avoid floating-point and/or symbolic commands such as log10floorevalf, and frac when doing large-integer arithmetic.

I confirm Tom's work; there are no typos. I obtained identical results independently.

restart:
(k,j):= (3,0):
add(
   add(`if`(l=m, 0, mul(`if`(q=m or q=l, 1, r-q+1), q= 0..k)), l= 0..k)
   /mul(`if`(l=m, 1, m-l), l= 0..k),
   m= j+1..k
);
eval(%, r= 1); 

My code is almost identical to Tom's, which is just a coincidence.

You wrote the following the very hand-wavy excuse:

  • (i know the command is weird, i.e. subs(beta=beta, ..), etc.. this is part of some larger code base and i just put this in when trying to undertand what's going on).

Your command is weird, period. "When trying to understand what's going on" is the last place that you'd want to do something weird. The weirdness is not so much the beta= beta part; it's when that's combined with an assuming clause that uses beta. Personally, I'd steer clear of any use of subs inside assuming.

These things might not have anything to do with your issue. I can't tell until you post the executable code.

The backslash is the escape character in Maple. So, if you want to pass a string literal that contains backslashes, then you must code each backslash as \\. So, if you want to pass a literal that has four backslashes, as you show (two at the beginning and two at the end), then it needs to be

"\\\\((.+)\\\\)"

You almost have it. I like your symbolic approach. Some tips and corrections:

  • If gamma is supposed to be a constant that you will specify, then you should use a different name for it, because gamma is a pre-defined constant in Maple, similar to Pi. While it's not an error to use your own value for gamma (or Pi for that matter), doing so can lead to incorrect numeric results being returned in some situations which otherwise would've (and should've!) returned error messages.
  • f should return a column vector, not a matrix.
  • In the definition of f, you've inappropriately used square brackets for parentheses.
  • You need to give a little bit of structural definition before you can do diff~(X, ...), etc. X:= t-> Vector(n, i-> x[i](t)) is sufficient (or use any other unused symbol for x).
  • Shouldn't tau become in the sys:= ... definition? Mathematically, it makes sense either way, but there's a big difference in meaning. Using tau would make it a constant-coefficient system (and perhaps that's what you intend).

There are commands numer and denom that extract the numerator and denominator of expressions. So,

coeff(denom(expr2), sin(a)^2)

I was surprised at how easy this was: To find (and print neatly) all references to _SolutionsMayBeLost in all library procedures whose names begin with isolve (This could be repeated for any names):

macro(pre= "isolve", SMBL= "_SolutionsMayBeLost", ST= StringTools):

#Select all library entries (19) whose names begin "isolve":
IP:= map(
   p-> convert(p[1][1..-3], name), #-3 to remove .m file extension
   select(p-> p[1][1..length(pre)]=pre, LibraryTools:-ShowContents())
);   
#Select those (4) that contain any reference to _SolutionsMayBeLost:
SIP:= select(p-> has(ToInert(eval(p)), SMBL), IP);

#Select the lines in those procedures that contain _SolutionsMayBeLost:
R:= map(
   p-> [
      p, 
      select(
         L-> ST:-Search(SMBL,L) > 0, ST:-Split(debugopts(procpretty= p), `\n`))[]
   ], 
   SIP
):
#Formatted print:
printf(cat("\n", seq(cat("%s\n"$r, "\n\n"), r= nops~(R))), op~(R)[]);  

isolve
global _SolutionsMayBeLost;
  26   _SolutionsMayBeLost := '_SolutionsMayBeLost';
  28   if _SolutionsMayBeLost = true then


isolve/inequalities
global _SolutionsMayBeLost;
  10       _SolutionsMayBeLost := true;


isolve/inequalities/convert_to_Z
global _SolutionsMayBeLost;
  21           _SolutionsMayBeLost := true;
  28           _SolutionsMayBeLost := true;
  34               _SolutionsMayBeLost := true;
  39                   _SolutionsMayBeLost := true;
  41           _SolutionsMayBeLost := true;
  43       _SolutionsMayBeLost := true;


isolve/inequalities/internal
global _SolutionsMayBeLost;
   6           _SolutionsMayBeLost := true;

So, if you execute the above in Maple 2018, you'll see that there are 19 library entries whose names begin with isolve. All are procedures. Of those, there are only 4 that contain any reference at all to _SolutionsMayBeLost. Only 3 of those set the value, and all 3 of those are specific to inequalities.

Here is another workaround. It is similar to yours, but it doesn't require any foreknowledge about which variable(s) are good candidates for elimination.

`isolve/sep_degrees`:= proc(Sys::set({algebraic, `=`}))
local L, N, S, LS, LN;
   (L,N):= selectremove(type, subsindets(Sys, `=`, lhs-rhs), 'linear');  
   S:= {isolve(eval(N, (L:= isolve(L))), _rest)};
   (LN,LS):= selectremove(type, L, name=name);
   eval(map(`union`, S, LS), (rhs=lhs)~(LN))[]
end proc:

sys:={x+y=10, x^2-y^2+z^2=1}:
`isolve/sep_degrees`(sys, n);

 

Maple 18 was wrong because the "closed form" that you give is not valid for all x. In Maple 2018, this error has been corrected. Now you either need to put an assuming clause (such as assuming x > 0) or throw caution to the wind and include the formal option:

sum(1/(1+x)^t, t= 1..infinity, 'formal');
sum(1/(1+x)^t, t= 1..infinity) assuming x > 0;

Here's an example of what you're trying to do. The procedure immediately below takes an expression f and returns the Newton's method iteration that can be used to solve f=0 for "some variable". The user can specify the variable to use as that "with respect to" variable (to bind that variable is the logician's parlance) in the second argument or leave the second argument blank to let the procedure try to figure that out on its own.

Newton:= proc(f::algebraic, var::name:= ())
local x:= var;
   if x=() then #User didn't pass a 2nd argument.
      #The Not(constant) part is to prevent things like 
      #Pi from being considered variables. 
      x:= indets(f, And(name, Not(constant)));
      #indets always returns a set, which we process based on its
      #number of elements, nops.
      if nops(x)=1 then x:= x[] #Extract the one and only member.
      elif x={} then error "No variables found"
      else error "Multiple variables found"
      fi
   fi;
   x - f/diff(f,x) #Return Newton iteration.
end proc: 

Then try

Newton(y^2 - 2);
Newton(x^2 - a);
Newton(x^2 - a, x);
Newton(2);
Newton(2, x); #Intentional divide-by-zero error

Note that the parameter specification var::name:= () has both a type, name, and a default value, (), and that that default value doesn't match the type. Thus the procedure knows that if var=(), then the user definitely didn't pass a second argument. (Actually, it's impossible to pass the particular value () as an argument, but that's beside the point. This type/default mismatch trick works for any default.)

The example that you showed of plot(x^2) is unusual compared to most Maple commands in that the input is an expression, yet the command doesn't require the user to specify the variable to bind. (And that's what I did in Newton.) But the far more common situation is that the procedure assumes that if no variable is specifed then the function/expression argument is a procedure whose (first) argument is the variable to bind (as in the commands plot(x-> x^2, -2..2) and plot(sin, -Pi..Pi)). This is simpler to code. Here's an example:

Newton2:= proc(f, var::name:= ())
local x;
   if var=() then #User didn't pass a 2nd argument.
      #Treat f as a procedure, temporarily bind a local, and return a procedure:
      unapply(x - f(x)/D(f)(x), x)
   else
      #Bind var and return an expression
      var - f/diff(f,var)
   fi
end proc:

Note that binding a variable is mostly a logical/mental process rather than something that happens inside the computer. It is something that happens in the minds of the writer and user of the procedure that gives a particular variable a different status.

When Maple needs to bind a variable that will appear in the output of a user-level procedure but which was not specifed in the input, it almost always chooses one whose name is an underscore, followed by one or two letters, followed by a nonnegative integer. Mostly, this is a convention that is respected by programmers rather than something that is enforced by a compiler.

The relation is not generally true. It would be true if you changed 2*Pi to Pi. The argument of a complex number is defined (in Maple, and perhaps generally) to be in the interval (-Pi, Pi]. I think you're assuming that that interval is [0, 2*Pi).

First 156 157 158 159 160 161 162 Last Page 158 of 395