Pattern to match only "children" of certain elements - wolfram-mathematica

I would like to be able to have a pattern that matches only expressions that are (alternately: are not) children of certain other elements.
For example, a pattern to match all Lists not within a Graphics object:
{ {1,2,3}, Graphics[Line[{{1,2},{3,4}}]] }
This pattern would match {1,2,3} but not {{1,2},{3,4}}.
There are relatively easy ways to extract expressions matching these criteria, but patterns are not only for extraction, but also for replacement, which is my main use case here (ReplaceAll).
Do you know of any easy, concise, and general ways to do this?
Is it possible to do this at all with just patterns?

I will propose a solution based on expression pre-processing and soft redefinitions of operations using rules, rather than rules themselves. Here is the code:
ClearAll[matchChildren, exceptChildren];
Module[{h, preprocess},
preprocess[expr_, parentPtrn_, lhs_, match : (True | False)] :=
Module[{pos, ptrnPos, lhsPos},
ptrnPos = Position[expr, parentPtrn];
lhsPos = Position[expr, lhs];
pos = Cases[lhsPos, {Alternatives ## PatternSequence ### ptrnPos, __}];
If[! match,pos = Complement[Position[expr, _, Infinity, Heads -> False], pos]];
MapAt[h, expr, pos]];
matchChildren /:
fun_[expr_, matchChildren[parentPtrn_, lhs : Except[_Rule | _RuleDelayed]],
args___] :=
fun[preprocess[expr, parentPtrn, lhs, True], h[lhs], args] //.
h[x_] :> x;
matchChildren /:
fun_[expr_, matchChildren[parentPtrn_, lhs_ :> rhs_], args___] :=
fun[preprocess[expr, parentPtrn, lhs, True], h[lhs] :> rhs, args] //.
h[x_] :> x;
exceptChildren /:
fun_[expr_,exceptChildren[parentPtrn_, lhs : Except[_Rule | _RuleDelayed]],
args___] :=
fun[preprocess[expr, parentPtrn, lhs, False], h[lhs], args] //.
h[x_] :> x;
exceptChildren /:
fun_[expr_, exceptChildren[parentPtrn_, lhs_ :> rhs_], args___] :=
fun[preprocess[expr, parentPtrn, lhs, False], h[lhs] :> rhs, args] //.
h[x_] :> x;
]
A few details on implementation ideas, and how it works. The idea is that, in order to restrict the pattern that should match, we may wrap this pattern in some head (say h), and also wrap all elements matching the original pattern but also being (or not being) within some other element (matching the "parent" pattern) in the same head h. This can be done for generic "child" pattern. Technically, one thing that makes it possible is the intrusive nature of rule application (and function parameter-passing, which have the same semantics in this respect). This allows one to take the rule like x_List:>f[x], matched by generic pattern lhs_:>rhs_, and change it to h[x_List]:>f[x], generically by using h[lhs]:>rhs. This is non-trivial because RuleDelayed is a scoping construct, and only the intrusiveness of another RuleDelayed (or, function parameter-passing) allows us to do the necessary scope surgery. In a way, this is an example of constructive use of the same effect that leads to the leaky functional abstraction in Mathematica. Another technical detail here is the use of UpValues to overload functions that use rules (Cases, ReplaceAll, etc) in the "soft" way, without adding any rules to them. At the same time, UpValues here allow the code to be universal - one code serves many functions that use patterns and rules. Finally, I am using the Module variables as a mechanism for encapsulation, to hide the auxiliary head h and function preprocess. This is a generally very handy way to achieve encapsulation of both functions and data on the scale smaller than a package but larger than a single function.
Here are some examples:
In[171]:= expr = {{1,2,3},Graphics[Line[{{1,2},{3,4}}]]};
In[168]:= expr/.matchChildren[_Graphics,x_List:>f[x]]//FullForm
Out[168]//FullForm= List[List[1,2,3],Graphics[Line[f[List[List[1,2],List[3,4]]]]]]
In[172]:= expr/.matchChildren[_Graphics,x:{__Integer}:>f[x]]//FullForm
Out[172]//FullForm= List[List[1,2,3],Graphics[Line[List[f[List[1,2]],f[List[3,4]]]]]]
In[173]:= expr/.exceptChildren[_Graphics,x_List:>f[x]]//FullForm
Out[173]//FullForm= List[f[List[1,2,3]],Graphics[Line[List[List[1,2],List[3,4]]]]]
In[174]:= expr = (Tan[p]*Cot[p+q])*(Sin[Pi n]+Cos[Pi m])*(Tan[q]+Cot[q]);
In[175]:= expr/.matchChildren[_Plus,x_Tan:>f[x]]
Out[175]= Cot[p+q] (Cot[q]+f[Tan[q]]) (Cos[m \[Pi]]+Sin[n \[Pi]]) Tan[p]
In[176]:= expr/.exceptChildren[_Plus,x_Tan:>f[x]]
Out[176]= Cot[p+q] f[Tan[p]] (Cos[m \[Pi]]+Sin[n \[Pi]]) (Cot[q]+Tan[q])
In[177]:= Cases[expr,matchChildren[_Plus,x_Tan:>f[x]],Infinity]
Out[177]= {f[Tan[q]]}
In[178]:= Cases[expr,exceptChildren[_Plus,x_Tan:>f[x]],Infinity]
Out[178]= {f[Tan[p]]}
In[179]:= Cases[expr,matchChildren[_Plus,x_Tan],Infinity]
Out[179]= {Tan[q]}
In[180]:= Cases[expr,matchChildren[_Plus,x_Tan],Infinity]
Out[180]= {Tan[q]}
It is expected to work with most functions which have the format fun[expr_,rule_,otherArgs___]. In particular, those include Cases,DeleteCases, Replace, ReplaceAll,ReplaceRepeated. I did not generalize to lists of rules, but this should be easy to do. It may not work properly in some subtle cases, e.g. with non-trivial heads and pattern-matching on heads.

According to your explanation in the comment to the acl's answer:
Actually I'd like it to work at any
level in the expression <...>. <...>
what I need is replacement: replace
all expression that match this
"pattern", and leave the rest
unchanged. I guess the simplest
possible solution is finding the
positions of elements, then using
ReplacePart. But this can also get
quite complicated in the end.
I think it could be done in one pass with ReplaceAll. We can rely here on the documented feature of the ReplaceAll: it does not look at the parts of the original expression which were already replaced even if they are replaced by themselves! Citing the Documentation: "ReplaceAll looks at each part of expr, tries all the rules on it, and then goes on to the next part of expr. The first rule that applies to a particular part is used; no further rules are tried on that part, or on any of its subparts."
Here is my solution (whatIwant is what you want to do with matched parts):
replaceNonChildren[lst_List] :=
ReplaceAll[#, {x_List :> whatIwant[x], y_ :> y}] & /# lst
Here is your test case:
replaceNonChildren[{{1, 2, 3}, Graphics[Line[{{1, 2}, {3, 4}}]]}] // InputForm
=> {whatIwant[{1, 2, 3}], Graphics[Line[{{1, 2}, {3, 4}}]]}
Here is a function that replaces only inside certain head (Graphics in this example):
replaceChildren[lst_List] :=
ReplaceAll[#, {y : Graphics[__] :> (y /. x_List :> whatIwant[x])}] & /# lst
Here is a test case:
replaceChildren[{{1, 2, 3}, Graphics[Line[{{1, 2}, {3, 4}}]]}] // InputForm
=> {{1, 2, 3}, Graphics[Line[whatIwant[{{1, 2}, {3, 4}}]]]}

You might write a recursive function that descends an expression tree and acts on the types of expression you want only if inside the right type of sub-expression, while leaving everything else alone. Patterns would be used heavily in the definition of the function.
Consider, for example, the following expression.
test = {{1, 2}, Graphics[{
Point[{{-1, 0}, {1, 0}}],
Line[{{-1, 0}, {1, 0}}]},
Frame -> True,
PlotRange -> {{-1, 1}, {-0.5, 0.5}}]};
Let's suppose that we want to rotate every ordered pair that we see in the first argument of Graphics about the origin through the angle Pi/4, while leaving other points alone. The following function does this.
Clear[f];
f[{x_?NumericQ, y_?NumericQ}] := If[flag === True,
RotationMatrix[Pi/4].{x, y}, {x, y}];
f[Graphics[primitives_, rest___]] := Block[{flag = True},
Graphics[f[primitives], rest]];
f[x_?AtomQ] := x;
f[x_] := f /# x;
Now we check
f[test]

I am probably misunderstanding you, but, if I do understand correctly you want to match all expressions with head List which have the property that, going upwards in the expression tree, we'll never meet a Graphics. I m not sure how to do this in one pass, but if you are willing to match twice, you can do something like
lst = {randhead[5], {1, 2, {3, 5}}, Graphics[Line[{{1, 2}, {3, 4}}]]};
Cases[#, _List] &#Cases[#, Except#Graphics[___]] &#lst
(*
----> {{1, 2, {3, 5}}}
*)
which first selects elements so that the Head isn't Graphics (this is done by Cases[#, Except#Graphics[___]] &, which returns {randhead[5], {1, 2, {3, 5}}}), then selects those with Head List from the returned list. Note that I've added some more stuff to lst.
But presumably you knew this and were after a single pattern to do the job?

Related

How to fix syntax to nest functions in mathematica?

I wanted to try to make a rule to do norm squared integrals. For example, instead of the following:
Integrate[ Conjugate[Exp[-\[Beta] Abs[x]]] Exp[-\[Beta] Abs[x]],
{x, -Infinity, Infinity}]
I tried creating a function to do so, but require the function to take a function:
Clear[complexNorm, g, x]
complexNorm[ g_[ x_ ] ] := Integrate[ Conjugate[g[x]] * g[x],
{x, -Infinity, Infinity}]
v = complexNorm[ Exp[ - \[Beta] Abs[x]]] // Trace
Mathematica doesn't have any trouble doing the first integral, but the final result of the trace when my helper function is used, shows just:
complexNorm[E^(-\[Beta] Abs[x])]
with no evaluation of the desired integral?
The syntax closely follows an example I found in http://www.mathprogramming-intro.org/download/MathProgrammingIntro.pdf [page 155], but it doesn't work for me.
The reason why your expression doesn't evaluate to what you expect is because complexNorm is expecting a pattern of the form f_[x_]. It returned what you put in because it couldn't pattern match what you gave it. If you still want to use your function, you can modify it to the following:
complexNorm[g_] := Integrate[ Conjugate[g] * g, {x, -Infinity, Infinity}]
Notice that you're just matching with anything now. Then, you just call it as complexNorm[expr]. This requires expr to have x in it somewhere though, or you'll get all kinds of funny business.
Also, can't you just use Abs[x]^2 for the norm squared? Abs[x] usually gives you a result of the form Sqrt[Conjugate[x] x].
That way you can just write:
complexNorm[g_] := Integrate[Abs[g]^2, {x, -Infinity, Infinity}]
Since you're doing quantum mechanics, you may find the following some nice syntatic sugar to use:
\[LeftAngleBracket] f_ \[RightAngleBracket] :=
Integrate[Abs[f]^2, {x, -\[Infinity], \[Infinity]}]
That way you can write your expectation values exactly as you would expect them.

Getting Indices from Mathematica's Select

How can I get the indices of a selection rather than the values. I.e.
list={3->4, 5->2, 1->1, 5->8, 3->2};
Select[list, #[[1]]==5&]; (* returns {5->2, 5->8} *)
I would like something like
SelectIndices[list, #[[1]]==5&]; (* returns {2, 4} *)
EDIT: I found an answer to the immediate question above (see below), but what about sorting. Say I want to sort a list but rather than returning the sorted list, I want to return the indices in the order of the sorted list?
Ok, well, I figured out a way to do this. Mathematica uses such a different vocabulary that searching the documentation still is generally unfruitful for me (I had been searching for things like, "Element index from Mathematica Select", to no avail.)
Anyway, this seems to be the way to do this:
Position[list, 5->_];
I guess its time to read up on patterns in Mathematica.
WRT to the question remaining after your edit: How about Ordering?
In[26]:= Ordering[{c, x, b, z, h}]
Out[26]= {3, 1, 5, 2, 4}
In[28]:= {c, x, b, z, h}[[Ordering[{c, x, b, z, h}]]]
Out[28]= {b, c, h, x, z}
In[27]:= Sort[{c, x, b, z, h}]
Out[27]= {b, c, h, x, z}
I think you want Ordering:
Sort[list, #[[1]] == 5 &]
Ordering[list, All, #[[1]] == 5 &]
(*
{5->2,5->8,3->2,1->1,3->4}
{2,4,5,3,1}
*)
Sorry, I had read your question to fast.
I think your second question is about how to sort the list according to the values of the rules. The simplest way that come to mind is by using a compare function. then simply use your solution to retrieve the indices:
comp[_ -> x_, a_ -> y_] := x < y;
Position[Sort[list, comp], 5 -> _]
Hope this helps!
Without sorting or otherwise altering the list, do this:
SelectIndex[list_, fn_] := Module[{x},
x = Reap[For[i = 1, i < Length[list], i++, If[fn[list[[i]]], Sow[i], Null];]];
If[x[[1]] == {}, {}, x[[2, 1]]]]
list={ {"foo",1}, {"bar",2}};
SelectIndex[list, StringMatchQ[ #[[1]], "foo*"] &]
You can use that to extract records from a database
Lookup[list_, query_, column_: 1, resultColumns_: All] := list[[SelectIndex[list, StringMatchQ[query, #[[column]]] &], resultColumns]]
Lookup(list,"foo")

Mathematica - selectively gathering nodes in a tree

I have a tree (expression) on which I want to gather only certain types of nodes - those that follow a certain pattern. I have a simplified example below:
A = {{{{},{0.3,0.3}},{0.2,0.2}},{0.1,0.1}};
TreeForm[A, PlotRangePadding->0]
Cases[A, {x_Real, y_Real}, Infinity]
The output:
Is this a good way to do it?
If instead of {x_, y_}, if I wanted to look for {{x1_, y1_}, {x2_, y_2}}, how can I exclude expressions like {x_, y_}, which also match?
Regards
EDIT (14/07/2011)
I have found that using a head other than List will greatly aid in finding such sub-expressions without collisions.
For example, reformulating the above:
A = {{{{}, pt[0.3, 0.3]}, pt[0.2, 0.2]}, pt[0.1, 0.1]};
List ### Cases[A, _pt, Infinity]
Output:
{{0.3,0.3},{0.2,0.2},{0.1,0.1}}
About the second part of your question, ie, selecting {{a,b},{c,d}}, how about
b = {{{{}, {0.3, 0.3}}, {0.2, 0.2}}, {{0.1, 0.1}, {0.3, 0.4}}};
TreeForm[b]
Cases[b, {{a_, b_}, {c_, d_}} /; (And ## NumericQ /# {a, b, c, d}), Infinity]
(so that they do not have to be Real but any Numeric will do)?
Here is an alternative to the form acl used, that I find more readable.
b = {{{{}, {0.3, 0.3}}, {0.2, 0.2}}, {{0.1, 0.1}, {0.3, 0.4}}};
With[{p = _?NumericQ}, Cases[b, {{p, p}, {p, p}}, -1] ]

Making customized InputForm and ShortInputForm

I often wish to see the internal representation of Mathematica's graphical objects not in the FullForm but in much more readable InputForm having the ability to select parts of the code by double-clicking on it and easily copy this code to a new input Cell. But the default InputForm does not allow this since InputForm is displayed by default as a String, not as Mathematica's code. Is there a way to have InputForm displayed as Mathematica's code?
I also often wish to see a shortened version of such InputForm where all long lists of coordinates are displayed as the first coordinate followed by number of skipped coordinate values wrapped with Skeleton, all empty Lists removed and all numbers are also shortened for displaying no more than 6 digits. It would be even better to use 6 digits only for coordinates but for color directives such as Hue display only 2 significant digits. For example,
Plot[{Sin[x], .5 Sin[2 x]}, {x, 0, 2 \[Pi]},
Filling -> {1 -> {2}}] // ShortInputForm
should give:
Graphics[GraphicsComplex[{{1.28228`*^-7, 1.28228*^-7}, <<1133>>},
{{{EdgeForm[], Directive[{Opacity[0.2], Hue[0.67, 0.6, 0.6]}],
GraphicsGroup[{Polygon[{{1133, <<578>>}}]}]},
{EdgeForm[], Directive[{Opacity[0.2], Hue[0.67, 0.6, 0.6]}],
GraphicsGroup[{Polygon[{{432, <<556>>}}]}]}}, {{Hue[0.67, 0.6,
0.6], Line[{1, <<431>>}]}, {Hue[0.91, 0.6, 0.6],
Line[{432, <<701>>}]}}}], {AspectRatio -> GoldenRatio^(-1),
Axes -> True, AxesOrigin -> {0, 0},
Method -> {"AxesInFront" -> True},
PlotRange -> {{0, 2*Pi}, {-1., 1}},
PlotRangeClipping -> True,
PlotRangePadding -> {Scaled[0.02], Scaled[0.02]}}]
(note that -0.9999998592131705 is converted to -1., 1.2822827157509358*^-7 is converted to 1.28228*^-7 and Hue[0.9060679774997897, 0.6, 0.6] is converted to Hue[0.91, 0.6, 0.6]).
In this way, I wish to have the output of InputForm as Mathematica's code and also have a ShortInputForm function which will give the shortened version of this code. Can anybody help me?
As to the first part of the question, I have found one way to achieve what I want:
Plot[{Sin[x], .5 Sin[2 x]}, {x, 0, 2 \[Pi]}, Filling -> {1 -> {2}}] //
InputForm // StandardForm
UPDATE
The most recent version of the shortInputForm function can be found here.
Original post
Here is another, even better solution (compatible with Mathematica 5):
myInputForm[expr_] :=
Block[{oldContexts, output, interpretation, skeleton},
output = ToString[expr, InputForm];
oldContexts = {$Context, $ContextPath};
$Context = "myTemp`"; $ContextPath = {$Context};
output = DisplayForm#ToBoxes[ToExpression[output] /.
{myTemp`interpretation -> If[$VersionNumber >= 6,
System`Interpretation, System`First#{#} &],
myTemp`Row -> System`Row,
myTemp`skeleton -> System`Skeleton,
myTemp`sequence :> (System`Sequence ## # &)}, StandardForm];
{$Context, $ContextPath} = oldContexts; output]
shortInputForm[expr_] := myInputForm[expr /. {{} -> Sequence[],
lst : {x_ /; VectorQ[x, NumberQ], y__} /;
(MatrixQ[lst, NumberQ] && Length[lst] > 3) :>
{x /. v : {a_, b__} /; Length[v] > 3 :>
{a, interpretation[skeleton[Length[{b}]], sequence#{b}]},
interpretation[skeleton[Length[{y}]], sequence#{y}]},
lst : {x_, y__} /; VectorQ[lst, NumberQ] && Length[lst] > 3 :>
{x, interpretation[skeleton[Length[{y}]], sequence#{y}]}}]
How it works
This solution is based on simple idea: we need to block conversion of such things as Graphics, Point and others to typeset expressions in order to get them displayed in the internal form (as expressions suitable for input). Happily, if we do this, the resulting StandardForm output is found to be just formatted (two-dimensional) InputForm of the original expression. This is just what is needed!
But how to do this?
First of all, this conversion is made by FormatValues defined for Symbols like Graphics, Point etc. One can get full list of such Symbols by evaluating the following:
list = Symbol /#
Select[DeleteCases[Names["*"], "I" | "Infinity"],
ToExpression[#, InputForm,
Function[symbol, Length[FormatValues#symbol] > 0, HoldAll]] &]
My first idea was just Block all these Symbols (and it works!):
myInputForm[expr_] :=
With[{list = list}, Block[list, RawBoxes#MakeBoxes#expr]]
But this method leads to the evaluation of all these Symbols and also evaluates all FormatValues for all Symbols in the $ContextPath. I think it should be avoided.
Other way to block these FormatValues is just to remove context "System`" from the $ContextPath. But it works only if these Symbols are not resolved yet to the "System`" context. So we need first to convert our expression to String, then remove "System`" context from the $ContextPath and finally convert the string backward to the original expression. Then all new Symbols will be associated with the current $Context (and Graphics, Point etc. - too, since they are not in the $ContextPath). For preventing context shadowing conflicts and littering the "Global`" context I switch $Context to "myTemp`" which can be easily cleared if necessary.
This is how myInputForm works.
Now about shortInputForm. The idea is not just to display a shortened version of myInputForm but also preserve the ability to select and copy parts of the shortened code into new input cell and use this code as it would be the full code without abbreviations. In version 6 and higher it is possible to achieve the latter with Interpretation. For compatibility with pre-6 versions of Mathematica I have added a piece of code that removes this ability if $VersionNumber is less than 6.
The only problem that I faced when working with Interpretation is that it has no SequenceHold attribute and so we cannot simply specify Sequence as the second argument for Interpretation. But this problem can easily be avoided by wrapping sequence in List and then Applying Sequence to it:
System`Sequence ## # &
Note that I need to specify the exact context for all built-in Symbols I use because at the moment of calling them the "System`" context is not in the $ContextPath.
This ends the non-standard decisions taken me in the development of these functions. Suggestions and comments are welcome!
At this moment I have come to the following solution:
round[x_, n_] := (10^-n*Round[10^n*MantissaExponent[x]]) /.
{m_, e_} :> N[m*10^e];
ShortInputForm[expr_] := ((expr /.
{{} -> Sequence[],
lst : {x_ /; VectorQ[x, NumberQ], y__} /;
(MatrixQ[lst, NumberQ] && Length[lst] > 2) :>
{x, Skeleton[Length[{y}]]},
lst : {x_, y__} /; VectorQ[lst, NumberQ] && Length[lst] > 2 :>
{x, Skeleton[Length[{y}]]}} /.
{exp : Except[List | Point][x__] /;
VectorQ[{x}, MachineNumberQ] :>
(round[#, 2] & /# exp),
x_Real /; MachineNumberQ[x] :> round[x, 6]})
// InputForm // StandardForm)
Now:

how to apply a rule involving a hundred variables in mathematica

I have an expression which involves x1,x2,...,x100, I also have a list lst with 100 elements, how to apply the rule to this expression to achieve something like the following:
exp/.{x1->lst[[1]],x2->lst[[2]],...,x100->lst[[100]]}
Thanks!
exp /. Table[Symbol["x" <> ToString[i]] -> lst[[i]], {i, 1, 100}]
So you don't need to write X1,X2, ... X100
You can use Thread to apply the rules to each pair of expressions:
Thread[{a, b, c} -> {1, 2, 3}]
It is much simpler and more convenient to solve such tasks using indexed variables instead of generation of a list of different Symbols. In this way:
listOfRules = Array[f## :> list[[#]] &, {100}];
Short#%
=> {f[1]:>list[[1]],f[2]:>list[[2]],f[3]:>list[[3]],f[4]:>list[[4]],
<<92>>,f[97]:>list[[97]],f[98]:>list[[98]],f[99]:>list[[99]],f[100]:>list[[100]]}
If you plan to make such replacement many times, it is worth to Dispatch large list of rules:
listOfRules = Dispatch#listOfRules;
The replacement can be made as usual:
expr /. listOfRules

Resources