Re: copying a variable
- To: mathgroup at smc.vnet.net
- Subject: [mg92345] Re: copying a variable
- From: "Szabolcs HorvÃt" <szhorvat at gmail.com>
- Date: Sat, 27 Sep 2008 22:24:39 -0400 (EDT)
- References: <gbl303$m03$1@smc.vnet.net> <48DE179F.5090201@gmail.com>
I still don't understand completely what you are doing, but I will try
to give some suggestions below. I hope they will be useful.
On Sat, Sep 27, 2008 at 18:06, ramiro <ramiro.barrantes at uvm.edu> wrote:
> Hi Szabolcs,
>
> I just tried with expressions and it looks great. I think I was just
> treating the DownValues as a kind of hash table (inspired a bit by the
> mathematica paclets) I think this is an important step in defining how I
> will work with tree (I work with evolutionary trees in biology). So here
> are two questions as I'm afraid I'm missing mathematica tricks:
>
> 1) If I want to find out the ancestor of a node, would it be best to a) just
> traverse the tree every time (maybe the speed won't be an issue), b) do some
> combination of Position, etc. to figure it out; c) keep a separate record
> of definitions (like the one I had) of who's the ancestor and the children
> of who.
The easiest (but not necessarily fastest) way to do this is to
traverse the complete tree and use pattern matching:
Let us define an example tree to work on:
tree = "a"["b"["A", "B"], "C", "c"["d"["D"], "E"], "F"]
This is what it looks like (I'm assuming that you have Mathematica 6):
TreeForm[tree]
This function finds parents of all occurrences of a node:
allParents[tree_, node_] :=
Cases[tree, par_[___, node, ___] :> par, {0, Infinity}]
Perhaps every node has only a single occurrence, so it would be better
to stop searching as soon as we find it:
firstParent[tree_, node_] :=
First@Cases[tree, par_[___, node, ___] :> par, {0, Infinity}, 1]
This is the list of all child nodes:
In[23]:= children = Level[tree, {-1}]
Out[23]= {"A", "B", "C", "D", "E", "F"}
And these are their parents:
In[24]:= firstParent[tree, #] & /@ children
Out[24]= {"b", "b", "a", "d", "c", "a"}
If you need to find certain child nodes very frequently by their
names, you could create an index of their positions:
In[25]:= (# -> First@Position[tree, #] &) /@ children
Out[25]= {"A" -> {1, 1}, "B" -> {1, 2}, "C" -> {2}, "D" -> {3, 1, 1},
"E" -> {3, 2}, "F" -> {4}}
For a large tree we can make a dispatch table (see Dispatch) of this
list of rules for fast lookup.
Here I treated the end child nodes differently from those nodes that
can have children themselves. If they should be equivalent, then you
could work with expressions like "a"["b"[], "c"["d"[], "e"[]]]
instead.
>
> 2) What if I want to do an operation on a tree, I was thinking about reading
> the tree and then making "definitions" of children, ancestors, etc. (just
> because I am going to use those many times), then making the operation
> somehow and outputting the tree again as an expression. e.g.
>
> reroot[treeX_]:=Module[{definitions},
> definition = "read all the tree data, ancestors, children, root, etc."
> based on treeX
> .... reroot the tree
>
> make a new expression based on rerooted tree
> output expression
> ]
You can use Delete, Insert, ReplacePart, Cases, DeleteCases, Replace,
etc. to manipulate trees.
For example, ReplacePart[tree, 0 -> "x"] replaces the root of the tree with "x".
"x"[tree] attaches tree to a new root "x".
>
> Thanks for helping. Any suggestions or comments much appreciated.
>