I have a long expression that I would like to split into a collection of terms. For example say I have:
a + b - c + d + 4*e - 3*f
I want to split the expression by addition/subtraction into:
{a, b, -c, d, 4*e, -3*f}
My motivation for this is that I want to deal with the original expression term by term. Is this possible?
Edit: The examples given are VERY simplistic compared to what I'm actually dealing with in Mathematica, it's just that I'm not sure how to write Math around here.
To split the expression, you need to use Level. Level gives you a list of subexpressions and you can specify the level at which you want the subexpressions returned. In this case, you need levelspec 1.
In[1]:= expr = a + b - c + d + 4 e - 3 f;
In[2]:= Level[expr, 1]
Out[2]= {a, b, -c, d, 4 e, -3 f}
An example with a slightly more complicated expression:
In[3]:= expr2 = a^2 + 5 bc/ef - Sqrt[g - h] - Cos[i]/Sin[j + k];
In[4]:= Level[expr2, 1]
Out[4]= {a^2, (5 bc)/ef, -Sqrt[g - h], -Cos[i] Csc[j + k]}
Since no one else has mentioned it, equivalent to Yoda's Level[expr, 1] construction is to use Apply to replace the head of an expression with List:
In[1]:= expr = a + b - c + d + 4 e - 3 f;
In[2]:= List ## expr
Level[expr, 1] == %
Out[2]= {a, b, -c, d, 4 e, -3 f}
Out[3]= True
In[4]:= expr2 = a^2 + 5 bc/ef - Sqrt[g - h] - Cos[i]/Sin[j + k];
In[5]:= List ## expr2
Level[expr2, 1] == %
Out[5]= {a^2, (5 bc)/ef, -Sqrt[g - h], -Cos[i] Csc[j + k]}
Out[6]= True
The two methods do basically the same thing and have identical timings (using my version of a average timing function)
In[1]:= SetOptions[TimeAv, Method -> {"MinNum", 80000}, "BlockSize" -> 20000];
In[7]:= List ## expr // TimeAv
Total wall time is 0.244517, total cpu time is 0.13
and total time spent evaluating the expression is 0.13
The expression was evaluated 80000 times, in blocks of 20000 runs. This yields
a mean timing of 1.625*10^-6 with a blocked standard deviation of 2.16506*10^-7.
Out[7]= {1.625*10^-6, {a, b, -c, d, 4 e, -3 f}}
In[8]:= Level[expr, 1] // TimeAv
Total wall time is 0.336927, total cpu time is 0.16
and total time spent evaluating the expression is 0.16
The expression was evaluated 80000 times, in blocks of 20000 runs. This yields
a mean timing of 2.*10^-6 with a blocked standard deviation of 3.53553*10^-7.
Out[8]= {2.*10^-6, {a, b, -c, d, 4 e, -3 f}}
You might also be able to use MonomialList, if you expression is a polynomial:
In[56]:= MonomialList[a + b - c + d + 4*e - 3*f]
Out[56]= {a, b, -c, d, 4 e, -3 f}
(Doesn't work on non-polynomials, such as Yoda's expr2.)
You could also use Replace:
In[65]:= Replace[a + b - c + d + 4*e - 3*f, HoldPattern[Plus[a___]] :> {a}]
Out[65]= {a, b, -c, d, 4 e, -3 f}
You need to use HoldPattern (or some equivalent trick) to prevent Plus[a__] from evaluating to a__, which has the result of just wrapping the first argument in a list instead of creating a list of the arguments to Plus.
Related
Assume, I would like to solve the following equation:
ax^2+bx+c=0
with a, b and c being parameters later to be determined, a might be even 0.
My try was the following:
In[1]:= sol = Solve[a x^2 + b x + c == 0, x]
Out[1]= {{x -> (-b - Sqrt[b^2 - 4 a c])/(2 a)}, {x -> (-b + Sqrt[b^2 - 4 a c])/(2 a)}}
Now if I would like to get the solution for the case when a=0, I get an error message:
In[2]:= sol /. {a -> 0, b -> 1, c -> 2}
During evaluation of In[2]:= Power::infy: Infinite expression 1/0 encountered.
During evaluation of In[2]:= Power::infy: Infinite expression 1/0 encountered.
During evaluation of In[2]:= Infinity::indet: Indeterminate expression 0 ComplexInfinity encountered.
Out[2]= {{x -> ComplexInfinity}, {x -> Indeterminate}}
Actually I have to solve a cubic equation, I wrote a quadratic one for the sake of simplicity.
I am very new to Mathematica, and I am trying to solve the following problem.
I have a cubic equation of the form Z = aZ^3 + bZ^2 + a + b. The first thing I want to do is to get a function that solves this analytically for Z and chooses the minimal positive root for that, as a function of a and b.
I thought that in order to get the root I could use:
Z = Solve[z == az^3 + bz^2 + a + b, z];
It seems like I am not quite getting the roots, as I would expect using the general cubic equation solution formula.
I want to integrate the minimal positive root of Z over a and b (again, preferably analytically) from 0 to 1 for a and for a to 1 for b.
I tried
Y = Integrate[Z, {a, 0, 1}, {b, a, 1}];
and that does not seem to give any formula or numerical value, but just returns an integral. (Notice I am not even sure how to pick the minimal positive root, but I am playing around with Mathematica to try to figure it out.)
Any ideas on how to do this?
Spaces between a or b and z are important. You can get the roots by:
sol = z /. Solve[z == a z^3 + b z^2 + a + b, z]
However, are you sure this expression has a solution as you expect? For a=0.5 and b=0.5, the only real root is negative.
sol /. {a->0.5, b->0.5}
{-2.26953,0.634765-0.691601 I,0.634765+0.691601 I}
sol = z /. Solve[z == a z^3 + b z^2 + a + b, z];
zz[a0_ /; NumericQ[a0], b0_ /; NumericQ[b0]] :=
Min[Select[ sol /. {a -> a0, b -> b0} ,
Element[#, Reals] && # > 0 & ]]
This returns -infinty when there are no solutions. As sirintinga noted your example integration limits are not valid..
RegionPlot[NumericQ[zz[a, b] ] , {a, -1, .5}, {b, -.5, 1}]
but you can numerically integrate if you have a valid region..
NIntegrate[zz[a, b], {a, -.5, -.2}, {b, .8, .9}] ->> 0.0370076
Edit ---
there is a bug above Select in Reals is throwin away real solutions with an infinitesimal complex part.. fix as:..
zz[a0_ /; NumericQ[a0], b0_ /; NumericQ[b0]] :=
Min[Select[ Chop[ sol /. {a -> a0, b -> b0} ],
Element[#, Reals] && # > 0 & ]]
Edit2, a cleaner approach if you dont find Chop satisfyting..
zz[a0_ /; NumericQ[a0], b0_ /; NumericQ[b0]] :=
Module[{z, a, b},
Min[z /. Solve[
Reduce[(z > 0 && z == a z^3 + b z^2 + a + b /.
{ a -> a0, b -> b0}), {z}, Reals]]]]
RegionPlot[NumericQ[zz[a, b] ] , {a, -2, 2}, {b, -2, 2}]
NIntegrate[zz[a, b], {a, 0, .5}, {b, 0, .5 - a}] -> 0.0491321
The derivative functions D and Dt don't appear to be functioning as advertised.
Following the first example in the "Properties and Relations" section of http://reference.wolfram.com/mathematica/ref/Constants.html I have:
In[1]:= {Dt[ax^2 + b, x, Constants -> {a, b}], D[ax^2 + b, x]}
Out[1]= {2 ax Dt[ax, x, Constants -> {a, b}], 0}
I've duplicated the input, but the output is totally different. How do I get the expected output { 2 a x, 2 a x}?
I am using Mathematica 8.0.1.0 64-bit as installed at Rutgers University.
You need a space between a and x, otherwise it thinks you're talking about a variable named ax:
In[2]:= {Dt[a x^2 + b, x, Constants -> {a, b}], D[a x^2 + b, x]}
Out[2]= {2 a x, 2 a x}
(I realize this isn't really answering the OP's question. But given the level of the question, along with OP's desire to use the Contants option, the following info may prove useful for others in the future.)
My 2 cents on Dt.
IMO, using the Constants option is less than ideal---mainly because it produces messy output. For example:
In[1]:= Dt[x^a y^b, Constants -> {a, b}]
Out[1]= a x^(-1 + a) y^b Dt[x, Constants -> {a, b}] +
b x^a y^(-1 + b) Dt[y, Constants -> {a, b}]
Am I the only one who finds the above behavior annoying/redundant? Is there a practical reason for this design? If so, please educate me... :)
Alternative approaches:
If you don't want to use the Constants option, here are some alternative approaches.
Use UpValues to force constants.
In[2]:= Remove[a, b];
a /: Dt[a] = 0;
b /: Dt[b] = 0;
Dt[x^a y^b]
Out[5]= a x^(-1 + a) y^b Dt[x] + b x^a y^(-1 + b) Dt[y]
Use Attributes. (i.e., give certain symbols the Constant Attribute.
In[6]:= Remove[a, b];
SetAttributes[{a, b}, Constant];
Dt[x^a y^b]
Out[8]= a x^(-1 + a) y^b Dt[x] + b x^a y^(-1 + b) Dt[y]
Use Rules to alter the output of the main Dt[] expression.
In[9]:= Remove[a, b];
Dt[x^a y^b] /. Dt[a] -> 0 /. Dt[b] -> 0
Out[10]= a x^(-1 + a) y^b Dt[x] + b x^a y^(-1 + b) Dt[y]
Given the following list:
{a + b, c + d + e, - a + b, a - b, - c - d - e}
I would like to get as a result:
{a + b, a - b, c + d + e}
To clarify: I'd like to transform the first list in such a way that the first term in each element is normalized to a plus sign and throw away any elements that can be obtained from the final result by multiplying with -1.
I have tried Collect[] and FactorTerms[] and some other functions that look remotely like they would be able to do what I need, but they never touch minus signs ....
Any help is greatly appreciated.
Use FactoredTermsList:
In[5]:= FactorTermsList /# {a + b, c + d + e, -a + b,
a - b, -c - d - e}
Out[5]= {{1, a + b}, {1, c + d + e}, {-1, a - b}, {1, a - b}, {-1,
c + d + e}}
In[6]:= DeleteDuplicates[%[[All, 2]]]
Out[6]= {a + b, c + d + e, a - b}
Replace each by its negative if the syntactic sign of the first element is negative. Then take the union. Example:
ll = {a + b, c + d + e, -a + b, a - b, -c - d - e}
Out[444]= {a + b, c + d + e, -a + b, a - b, -c - d - e}
Union[Map[
If[Head[#] === Plus && Head[#[[1]]] === Times &&
NumberQ[#[[1, 1]]] && #[[1, 1]] < 0, Expand[-#], #] &, ll]]
{a - b, a + b, c + d + e}
Daniel Lichtblau
It looks like you want to eliminate the elements that are duplicate modulo an overall sign. At least in this particular case, the following will work:
In[13]:= Union[FullSimplify#Abs[{a + b, c + d + e, -a + b, a - b, -c - d - e}]] /.
Abs[x_] :> x
Out[13]= {a - b, a + b, c + d + e}
If the order of elements in the list matters, you can use DeleteDuplicates in place of Union.
Here's an attempt.
ClearAll[nTerm];
nTerm[t_] := If[MatchQ[t[[1]], Times[-1, _]], -t, t]
is intended to be mapped over a list; takes a single item (of the list) as input, replaces it by its negative if the first element has a negative sign. So nTerm[-a + b + c] gives a - b - c, which is left invariant by nTerm: nTerm[a - b - c] gives back its argument.
Next,
ClearAll[removeElements];
removeElements[lst_] :=
DeleteDuplicates[lst, (#1 \[Equal] #2) || (#1 \[Equal] -#2) &]
takes a list as argument, removes those list elements that might be obtained from another list element by negation: removeElements[{1, 2, 3, -2, a, -a, "GWB", -"GWB"}] gives {1, 2, 3, a, "GWB"} (!). Finally,
ClearAll[processList];
processList[lst_] := removeElements[nTerm /# lst]
applies the whole lot to an input list; thus, li = {a + b, c + d + e, -a + b, a - b, -c - d - e}; processList[li] gives {a + b, c + d + e, a - b}
I am wondering how I can write a function to be used in the Apply function in Mathematica? For example, I want to trivially re-implement the Or function, I found the following
Apply[(#1 || #2)&,{a,b,c}]
is not okay since it only Or'ed the first two elements in the list. Many thanks!
This will work, no matter how many vars, and is a general pattern:
Or[##]&,
for example
In[5]:= Or[##] & ## {a, b, c}
Out[5]= a || b || c
However, in the case of Or, this is not good enough, since Or is HoldAll and short-circuiting - that is, it stops upon first True statement, and keeps the rest unevaluated. Example:
In[6]:= Or[True, Print["*"]]
Out[6]= True
In[7]:= Or[##] & ## Hold[True, Print["*"]]
During evaluation of In[7]:= *
Out[7]= True
This will be ok though:
Function[Null,Or[##],HoldAll],
for example,
In[8]:= Function[Null, Or[##], HoldAll] ## Hold[True, Print["*"]]
Out[8]= True
and can be used in such cases (when you don't want your arguments to evaluate). Note that this uses an undocumented form of Function. The mention of this form can be found in the book of R.Maeder, "Programming in Mathematica".
HTH
Or ## {a, b, c}
Equivalent
Apply[Or, {a, b, c}]
Equivalent
{a, b, c} /. {x_, y__} -> Or[x, y]
Apply works like this:
{2 #1, 3 #2, 4 #3} & ## {a, b, c}
{2 a, 3 b, 4 c}
Plus[2 #1, 3 #2, 4 #3] & ## {a, b, c}
2 a + 3 b + 4 c
Are you sure you are expecting the right thing from Apply? If you look in the documentation, http://reference.wolfram.com/mathematica/ref/Apply.html, you will see that Apply[f,expr] simply replaces the head of f by expr. It does not, in general, give f[expr].
If you wish to operate with function f onto expr, try f#expr or f[expr].
Perhaps you understand the above and your question really is, "how do I define some f that, when I do Apply[f,{a,b,c}], does the same job as Or[a,b,c]. Is that it?