Extract complete argument and function name(s) from the Expression, (standard mathematical functions only) MAPLE - symbolic-math

For expressions like
a1 := sin(1+a/b);
a2 := log(1+ a*b);
a3 := abs(a^2+b);
how can I get expressions of respective functions. For example
someCommand(a1) # should get an output 1+a/b
someCommand(a2) # should get an output 1+a*b
someCommand(a3) # should get an output a^2+b
I have tried to get related topics from maple documentation but unfortunately am not able to get exactly.
edited: Also how is it possible to get list (in sequence)of functions used
let
a :=sin(log(abs(a+b)));# functions can be of more than two
someCommand(a) # have to return [{sin, log, abs}, a+b]

You can use the op() command, which breaks down expressions into their operands. For instance:
f := sin(1+a/b);
g := op(0,f); # sin
h := op(1,f); # 1+a/b

That's not complicated to construct. (More thoughts on that, below...)
restart;
W := (ee,nm::name) -> [op(map(`[]`#op,indets(ee,':-specfunc'(nm))))]:
And now to test it,
a1 := sin(1+a/b):
a2 := log(1+ a*b):
a3 := abs(a^2+b):
W( a1, sin );
[[ a]]
[[1 + -]]
[[ b]]
W( a2, ln );
[[a b + 1]]
W( a3, abs );
[[ 2 ]]
[[a + b]]
Now a slightly longer example,
foo := cos(1+a/b)/abs(a^2+b)
+log(1+ a*b)*cos(s-v)
+sin(c+d/r);
/ a\
cos|1 + -|
\ b/ / d\
foo := ---------- + ln(a b + 1) cos(s - v) + sin|c + -|
| 2 | \ r/
|a + b|
W( foo, sin );
[[ d]]
[[c + -]]
[[ r]]
W( foo, cos );
[[ a] ]
[[1 + -], [s - v]]
[[ b] ]
W( foo, abs );
[[ 2 ]]
[[a + b]]
W( foo, ln );
[[a b + 1]]
With no other context to judge by, I personally prefer to have the items above be returned within lists, to be able to handle them later more easily.
But it looks even simpler, if one leaves out the encapsulating lists,
Y := (ee,nm::name) -> op(map(op,indets(ee,':-specfunc'(nm)))):
Y( foo, cos );
a
1 + -, s - v
b
Now a few opinions. The reason that there is no dedicated command for doing precisely this is because there are so very many tasks in a similar vein. A programming language that is crammed full of hundreds of distinct commands to do too similar things can be awkward (or worse) to use.
To use Maple effectively it helps to learn the basic building blocks very well. Those include at least things like,
op, map, map[n], zip, select, remove, selectremove,
table, indices, entries, type, indets, subsindets,
normal, radnormal, simplify, evalc, evala, rationalize

In your followup comment to another Answer you gave the further example of sin(log(abs(a+b))). I suspect that you want to be able to slice and dice even more complicated examples.
You haven't really told use what your final goal is. Perhaps you're trying to build an expression tree. Or perhaps you're evenutally planning on doing something else with this analysis. It'd really help if you told us the final goal.
Having said that, the following might be of some use to you.
restart;
ee := "sin(log(abs(a+b))) + sin(s+t) + abs(log(v+w))":
P:=InertForm:-Parse(ee):
lprint(P);
`%+`(%sin(%log(%abs(`%+`(a,b)))),%sin(`%+`(s,t)),
%abs(%log(`%+`(v,w))))
It may be that the above inert form is something you can work with, for whatever your goal might be.
indets(P, specfunc(name,`%+`));
{a %+ b, s %+ t, v %+ w}
indets(P, specfunc(anything,%abs));
{%abs(a %+ b), %abs(%log(v %+ w))}
indets(P, specfunc(specfunc(name,`%+`),%abs));
{%abs(a %+ b)}
indets(P, specfunc(specfunc(name,`%+`),%log));
{%log(v %+ w)}
Using a routine limke from my earlier Answer,
W := (ee,nm) -> [op(map(`[]`#op,indets(ee,':-specfunc'(nm))))]:
W( indets(P, specfunc(specfunc(name,`%+`),%log)), `%+` );
[[v, w]]
W( indets(P, specfunc(specfunc(name,`%+`),%sin)), `%+` );
[[s, t]]
W( indets(P, specfunc(specfunc(name,`%+`),%abs)), `%+` );
[[a, b]]
There are other ways to get those last results (using something like W on an actual expression and not its inert form, say). I'm just trying to show you how you can do a bit more with it all.

Related

perl6 What is a quick way to de-select array or list elements?

To select multiple elements from an array in perl6, it is easy: just use a list of indices:
> my #a = < a b c d e f g >;
> #a[ 1,3,5 ]
(b d f)
But to de-select those elements, I had to use Set:
> say #a[ (#a.keys.Set (-) (1,3,5)).keys.sort ]
(a c e g)
I am wondering if there is an easier way because the arrays I use are often quite large?
sub infix:<not-at> ($elems, #not-ats) {
my $at = 0;
flat gather for #not-ats -> $not-at {
when $at < $not-at { take $at++ xx $not-at - $at }
NEXT { $at++ }
LAST { take $at++ xx $elems - $not-at - 1 }
}
}
my #a = < a b c d e f g >;
say #a[ * not-at (1, 3, 5) ]; # (a c e g)
I think the operator code is self-explanatory if you know each of the P6 constructs it uses. If anyone would appreciate an explanation of it beyond the following, let me know in the comments.
I'll start with the two aspects that generate the call to not-at.
* aka Whatever
From the Whatever doc page:
When * is used in term position, that is, as an operand, in combination with most operators, the compiler will transform the expression into a closure of type WhateverCode
* is indeed used in the above as an operand. In this case it's the left argument (corresponding to the $elems parameter) of the infix not-at operator that I've just created.
The next question is, will the compiler do the transform? The compiler decides based on whether the operator has an explicit * as the parameter corresponding to the * argument. If I'd written * instead of $elems then that would have made not-at one of the few operators that wants to directly handle the * and do whatever it chooses to do and the compiler would directly call it. But I didn't. I wrote $elems. So the compiler does the transform I'll describe next.
The transform builds a new WhateverCode around the enclosing expression and rewrites the Whatever as "it" aka the topic aka $_ instead. So in this case it turns this:
* not-at (1,3,5)
into this:
{ $_ not-at (1,3,5) }
What [...] as a subscript does
The [...] in #a[...] is a Positional (array/list) subscript. This imposes several evaluation aspects, of which two matter here:
"it" aka the topic aka $_ is set to the length of the list/array.
If the content of the subscript is a Callable it gets called. The WhateverCode generated as explained above is indeed a Callable so it gets called.
So this:
#a[ * not-at (1,3,5) ]
becomes this:
#a[ { $_ not-at [1,3,5] } ]
which turns into this:
#a[ { infix:not-at(7, [1,3,5]) } ]
Given the indexer wants the elements to extract, we could solve this by turning the list of elements to exclude into a list of ranges of elements to extract. That is, given:
1, 3, 5
We'd produce something equivalent to:
0..0, 2..2, 4..4, 6..Inf
Given:
my #exclude = 1, 3, 5;
We can do:
-1, |#exclude Z^..^ |#exclude, Inf
To break it down, zip (-1, 1, 3, 5) with (1, 3, 5, Inf), but using the range operator with exclusive endpoints. This results in, for the given example:
(-1^..^1 1^..^3 3^..^5 5^..^Inf)
Which is equivalent to the ranges I mentioned above. Then we stick this into the indexer:
my #a = <a b c d e f g>
my #exclude = 1, 3, 5;
say #a[-1, |#exclude Z^..^ |#exclude, Inf].flat
Which gives the desired result:
(a c e g)
This approach is O(n + m). It will probably work out quite well if there array is long, but the number of things to exclude is comparatively small, since it only produces the Range objects needed for the indexing, and then indexing by range is relatively well optimized.
Finally, should the flat on the outside be considered troublesome, it's also possible to move it inside:
#a[{ flat -1, |#exclude Z^..^ |#exclude, $_ }]
Which works because the block is passed the number of elements in #a.
Here's another option:
my #a = < a b c d e f g >;
say #a[#a.keys.grep(none(1, 3, 5))];
But all in all, arrays aren't optimized for this use case. They are optimized for working with a single element, or all elements, and slices provide a shortcut for (positively) selecting several elements by key.
If you tell us about the underlying use case, maybe we can recommend a more suitable data structure.
This might be slow for big arrays, but it's logically the closer to what you're looking for:
my #a = <a b c d>;
say (#a ⊖ #a[0,1]).keys; # (c d)
It's basically the same solution you proposed at the beginning, using set difference, except it's using it on the whole array instead of on the indices. Also, in some cases you might use the set directly; it depends on what you want to do.
#raiphs solution combined with #Jonathan Worthington 's:
The operator should be very efficient for huge numbers and large #not-ats lists as it returns a list of ranges, and it even creates that list of ranges lazily. For the #not-ats it supports integers and ranges with included and excluded bounds and infinity. But it has to be ascending.
The $elems can be a Range or an Int. It is interpreted as .Int as in Jonathan Worthington's solution to support (but needs a .flat applying it to array slicing - the price of performance for the lazy operator - this could be changed by using flat gather instead of lazy gather in the 2nd line)
#a[ (* not-at (1, 3, 5)).flat ];
or newly support
#a[ (* not-at (1, 3^ .. 5, 8 .. 8, 10, 14 .. ^18, 19 .. *)).flat ];
The performance improvements can be seen, when not slicing the array at once, but operating on parts of the array, optimally with multithreading.
sub infix:<not-at> ($elems, #not-ats) {
lazy gather {
my $at = 0;
for #not-ats { # iterate over #not-ats ranges
my ($stop, $continue) = do given $_ {
when Int { succeed $_, $_ } # 5
when !.infinite { succeed .int-bounds } # 3..8 | 2^..8 | 3..^9 | 2^..^9
when !.excludes-min { succeed .min, $elems.Int } # 4..*
default { succeed .min + 1, $elems.Int } # 3^..*
}
take $at .. $stop - 1 if $at < $stop; # output Range before current $not-at range
$at = $continue + 1; # continue after current $not-at range
}
take $at .. $elems.Int - 1 if $at < $elems; # output Range with remaining elements
}
}

Vector string replace with Julia

I would like to find the elements of x which contain "X" and replace "X" with "".
v = split("a b c d e f g h i j k l m n o p X")
x = rand(v,100) .* rand(v,100) .* rand(v,100)
A using a for loop I could:
for i=1:length(x)
x[i] = replace(x[i], "X", "")
end
Is this how string vector manipulation is done in Julia? Or is there a .replace or apply(sapply(x, replace, "X", "") as used in R) set of functions I should be using?
Using for loops or comprehensions is a great solution and is typically a very performant solution. Loops are fast in Julia, so you don't need to worry about vectorizing code just to make it fast. That said, in the upcoming 0.6 release, you can write fast vectorized code in Julia using dot-broadcasting since strings are now treated as scalar elements in broadcast:
julia> replace.(x, "X", "")
100-element Array{String,1}:
"lod"
"kk"
"eco"
"jac"
⋮
"ojn"
"hmc"
"pb"
You can do it in-place with:
x .= replace.(x, "X", "")
You can do it like
[replace(i,"X","") for i in x]
But as Stefan pointed out in the comments, it creates a new vector.
The correct way should be (as explained by Matt)
x .= replace.(x, "X", "")
Just to have a quick recap of replace function, here is what the Julia official docs says.
help?> replace
search: replace redisplay
replace(string, pat, r[, n])
Search for the given pattern pat, and replace each occurrence with r. If n is provided, replace at most n occurrences. As
with search, the second argument may be a single character, a vector or a set of characters, a string, or a regular
expression. If r is a function, each occurrence is replaced with r(s) where s is the matched substring. If pat is a
regular expression and r is a SubstitutionString, then capture group references in r are replaced with the corresponding
matched text.
julia>

R- outer with matrix

Let's suppose I want to minimize a function:
x<-seq(-4.5,4.5,by=.2)
y<-seq(-4.5,4.5,by=.2)
f <- function(x1,x2){(x1^2 + x2)^2 }
z <- outer(x,y,f)
Where z is a matrix of dimension 46 x 46:
> class(z)
[1] "matrix"
> dim(z)
[1] 46 46
So I make a graph of the result with:
persp(x,y,z,phi=-45,theta=45,col="yellow",shade=.65 ,ticktype="detailed")
If I write the previous, it works, but since I want to minimize the function using optim, if I use that I get:
optim(c(-4,-4), f, df)$par
> Error in fn(par, ...) : argument "x2" is missing, with no default
So I need to use an array in order to use optim after all. So if I write:
f <- function(x) (x[1]^2 + x[2])^2
x <- seq(-4.5,4.5,by=.2)
y <- seq(-4.5,4.5,by=.2)
s<-data.frame(cbind(x,y))
I can use optim:
optim(c(-4,-4), f, df)$par
But outer gives an error:
z <- outer(s,f)
Error in as.vector(x, mode) : cannot coerce type 'closure' to
vector of type 'any'
I don't know how to solve it.
I believe the goal here is to not have to write the function two different ways, right?
f0 <- function(x1,x2) ( x1^2 + x2 )^2
f <- function(x) ( x[1]^2 + x[2] )^2
Similarly, maybe you just want to use just s<-data.frame(cbind(x,y)) (without x and y).
Here's what I would consider doing:
outer(s[[1]],s[[2]],Vectorize(function(xi,yi) f(c(xi,yi))))
This way you only have to write the function once, in the way amenable to using optim (with a single argument).
Note: If you want the grids x and y to have a different number of points, you should store s <- list(x,y) instead. The code will work the same.

Using nested loops in bash to replace characters in a string with an array of words

I've been picking up Bash lately and I'm having trouble wrapping my head around nested loops.
Here's what I got.
input='ATAATAATAATG'
CODONTABLE=(ATA I ATC I ATT I ATG M ACA T
ACC T ACG T ACT T AAC N AAT N
AAA K AAG K AGC S AGT S AGA R
AGG R CTA L CTC L CTG L CTT L
CCA P CCC P CCG P CCT P CAC H
CAT H CAA Q CAG Q CGA R CGC R
CGG R CGT R GTA V GTC V GTG V
GTT V GCA A GCC A GCG A GCT A
GAC D GAT D GAA E GAG E GGA G
GGC G GGG G GGT G TCA S TCC S
TCG S TCT S TTC F TTT F TTA L
TTG L TAC Y TAT Y TAA _ TAG _
TGC C TGT C TGA _ TGG W)
for ((i=0;i<${#input};i++)) ; do
let w+=1
for c in $input ; do
for h in $CODONTABLE ; do
if [ $(echo ${input:x:3})=$(echo $CODONTABLE[w]) ] ; then
mod+=(${CODONTABLE[w]})
let x+=1
else
let w+=1
fi
done
done
done
echo $mod
echo $input
What I get from this is...
ATAATAATAATG
I
So it seems that at least ATA was properly translated into an I.
However, what I want is
**ATA**ATAATAATG -> I
A**TAA**TAATAATG -> _
AT**AAT**AATAATG -> N
ATA**ATA**ATAATG -> I
So that the final output reads I_NI_NI_NM, which I use later.
In short, how do I create a proper repeating loop that goes through my input, translates every possible 3 character frame, and appends this to another array?
There are actually a lot of problems with your code. Some of them are pure logic errors; others are due to misunderstandings about what various Bash constructs do. (Though I'm guessing that some of the pure logic errors are due to trial-and-error attempts to fix problems caused by misunderstandings about what various Bash constructs do.) So as a general suggestion, I'd suggest writing and testing small pieces, to see how they work, and using debugging output (small statements like echo "i=$i w=$w c=$c h=$h" that help you see what's going in your code). That will help you build up to a working program.
Below are a few specific problems. They are not a complete list.
This:
for ((i=0;i<${#input};i++)) ; do
let w+=1
...
done
will give w the values 1, 2, 3, … 12. But I think you actually want w to take the values 0, 3, 6, 9? For that, you should write:
for (( w = 0 ; w < ${#input} ; w += 3)) ; do
...
done
(I apologize if I've misunderstood what w is supposed to be. Its name is not very mnemonic, and you seem to use it a few different ways, so it's hard to be sure. Incidentally — I recommend putting some effort into naming your variables better. It makes code so much easier to understand and debug.)
Since $input does not contain any whitespace, this:
for c in $input ; do
...
done
is equivalent to this:
c=$input
...
(Maybe you were expecting for c in $input to loop over the characters of $input? But that's not what that notation does.)
You seem to be trying to treat CODONTABLE as an associative array, but you haven't written it to be one. If you're using a version of Bash that supports associative arrays, then you should use a real one:
declare -A CODONTABLE=([ATA]=I [ATC]=I [ATT]=I [ATG]=M [ACA]=T
[ACC]=T [ACG]=T [ACT]=T [AAC]=N [AAT]=N
[AAA]=K [AAG]=K [AGC]=S [AGT]=S [AGA]=R
[AGG]=R [CTA]=L [CTC]=L [CTG]=L [CTT]=L
[CCA]=P [CCC]=P [CCG]=P [CCT]=P [CAC]=H
[CAT]=H [CAA]=Q [CAG]=Q [CGA]=R [CGC]=R
[CGG]=R [CGT]=R [GTA]=V [GTC]=V [GTG]=V
[GTT]=V [GCA]=A [GCC]=A [GCG]=A [GCT]=A
[GAC]=D [GAT]=D [GAA]=E [GAG]=E [GGA]=G
[GGC]=G [GGG]=G [GGT]=G [TCA]=S [TCC]=S
[TCG]=S [TCT]=S [TTC]=F [TTT]=F [TTA]=L
[TTG]=L [TAC]=Y [TAT]=Y [TAA]=_ [TAG]=_
[TGC]=C [TGT]=C [TGA]=_ [TGG]=W)
If not, then your regular-array approach is fine, but rather than trying to use a deeply-nested loop to find the right mapping in CODONTABLE, you should put that logic in its own function:
function dna_codon_to_amino ($) {
local dna_codon="$1"
local i
for (( i = 0 ; i < ${CODONTABLE[#]} ; i += 2 )) ; do
if [[ "$dna_codon" = "${CODONTABLE[i]}" ]] ; then
echo "${CODONTABLE[i+1]}"
return
fi
done
# whoops, didn't find anything. print a warning to standard error,
# return the amino acid '#', and indicate non-success:
echo "Warning: invalid DNA codon: '$dna_codon'" >&2
echo '#'
return 1
}
Then you can call it by writing something like:
amino_codon="$(dna_codon_to_amino "$dna_codon")"
There's a lot of good in ruakh's answer, but there isn't an explanation of how to step through the string 3 letters at a time, I think. This code does that:
#!/usr/bin/env bash-4.3
declare -A CODONTABLE
CODONTABLE=(
[ATA]=I [ATC]=I [ATT]=I [ATG]=M [ACA]=T
[ACC]=T [ACG]=T [ACT]=T [AAC]=N [AAT]=N
[AAA]=K [AAG]=K [AGC]=S [AGT]=S [AGA]=R
[AGG]=R [CTA]=L [CTC]=L [CTG]=L [CTT]=L
[CCA]=P [CCC]=P [CCG]=P [CCT]=P [CAC]=H
[CAT]=H [CAA]=Q [CAG]=Q [CGA]=R [CGC]=R
[CGG]=R [CGT]=R [GTA]=V [GTC]=V [GTG]=V
[GTT]=V [GCA]=A [GCC]=A [GCG]=A [GCT]=A
[GAC]=D [GAT]=D [GAA]=E [GAG]=E [GGA]=G
[GGC]=G [GGG]=G [GGT]=G [TCA]=S [TCC]=S
[TCG]=S [TCT]=S [TTC]=F [TTT]=F [TTA]=L
[TTG]=L [TAC]=Y [TAT]=Y [TAA]=_ [TAG]=_
[TGC]=C [TGT]=C [TGA]=_ [TGG]=W
)
input='ATAATAATAATG'
i=("AAAAACAAGAATACAACCACGACTAGAAGCAGGAGTATAATCATGATT"
"CAACACCAGCATCCACCCCCGCCTCGACGCCGGCGTCTACTCCTGCTT"
"GAAGACGAGGATGCAGCCGCGGCTGGAGGCGGGGGTGTAGTCGTGGTT"
"TAATACTAGTATTCATCCTCGTCTTGATGCTGGTGTTTATTCTTGTTT"
)
for string in "$input" "${i[#]}"
do
echo "$string"
fmt=$(printf " %%-%ds %%3s %%s\\\\n" ${#string})
#echo "$fmt"
output=""
while [ ${#string} -ge 3 ]
do
codon=${string:0:3}
output="$output${CODONTABLE[$codon]}"
printf "$fmt" "$string" "$codon" "$output"
string=${string#?}
done
done
The key parts are the associative array and the two expressions:
codon=${string:0:3} # Extract 3 characters from offset 0 of string
string=${string#?} # Drop the first character from string
The first part of the output is:
ATAATAATAATG
ATAATAATAATG ATA I
TAATAATAATG TAA I_
AATAATAATG AAT I_N
ATAATAATG ATA I_NI
TAATAATG TAA I_NI_
AATAATG AAT I_NI_N
ATAATG ATA I_NI_NI
TAATG TAA I_NI_NI_
AATG AAT I_NI_NI_N
ATG ATG I_NI_NI_NM

Difference between gcc and Microsoft preprocessor

I discovered that Microsoft Visual Studio compiler and gcc preprocess the following small snippet differently:
# define M3(x, y, z) x + y + z
# define M2(x, y) M3(x, y)
# define P(x, y) {x, y}
# define M(x, y) M2(x, P(x, y))
M(a, b)
'gcc -E' gives the following:
a + {a + b}
, while 'cl /E' issues a warning about missing macro argument and produces the following output:
a + {a, b} +
It seems that commas that came from nested macro expansions are not considered to be argument separators. Unfortunately, I found no description of the algorithm implemented in cl preprocessor, and so I'm not sure that my suggestion is correct. Does anyone know how cl preprocessor works and what's the difference between its algorithm and gcc's? And how the observed behaviour can be explained?
# define M3(x, y, z) x + y + z
# define M2(x, y) M3(x, y)
# define P(x, y) {x, y}
# define M(x, y) M2(x, P(x, y))
M(a, b)
Let us roll this out manually, step by step:
M(a, b)
--> M2(a, P(a, b))
--> M2(a, {a, b})
The standard says:
The individual arguments within the list are separated by comma
preprocessing tokens, but comma preprocessing tokens between matching inner parentheses do not separate
only parentheses are mentioned, so ...
--> M3(a, {a, b})
--> a + {a + b}
Important:
M3(a, {a, b})
Here, according to the previous quote from the standard, three "arguments" are passed to M3 (using single-quotes to describe tokens/arguments):
M3('a', '{a', 'b}')
which are expanded to
'a' + '{a' + 'b}'
And this is what cpp (4.6.1) gives verbatim:
# 1 "cpp.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "cpp.cpp"
a + {a + b}
cpp (or gcc and g++) are correct, MSVC isn't.
As a nobleman make sure a bug report exists.
The only logic that explains such a behavior looks like this.
CL way:
M(a,b)
M2(a,P(a,b))
M3(a,P(a,b))
M3(a,{a,b}) -> M3 gets 2 arguments ( 'a' and '{a,b}') instead of 3.
| \ /
arg1 |
arg2
Gcc way:
M(a,b)
M2(a,P(a,b))
M3(a,P(a,b))
M3(a,{a,b}) -> Gcc probably thinks there are 3 arguments here ('a', '{a', 'b}').
| | |
arg1 | |
arg2 |
arg3
I think gcc gets it right, what Microsoft does is incorrect.
When macro substitution is done for the line
M2(a, P(a, b))
the standard (section 6.10.3.1) requires that before replacing the second parameter ("y") in the macro's replacement list ("M3(x, y)") with its argument ("P(a, b)"), macro replacement is to be performed for that argument. This means "P(a, b)" is processed to "{a, b}" before it is inserted, resulting in
M3(a, {a, b})
which is then further replaced to
a + {a + b}

Resources