0
$\begingroup$

I am trying to write a function that builds a graph, or - better said - adds a layer of leaves to a pre-existing graph.

Basically, I hand to the function three lists. edges is the "already existing (upper) part of the tree", nodeslvl1 includes all its leaves, nodeslvl2 are the new leaves, which should stem from the ones in nodeslvl1 according to a certain rule.
The function should append the new edges of the tree to the ones already existing in the original edges. Finally, it should graph the tree.

Here's my code:

graphfrom2lists[edges_List, nodeslvl1_List, nodeslvl2_List] := 
Module[{i, l = Length[nodeslvl1[[1]]], pos},
  For[i = 1, i < Length[nodeslvl2] + 1, i++,
    pos = Position[nodeslvl1, nodeslvl2[[i,2;;l+1]]][[1,1]];
    AppendTo[edges, nodeslvl1[[pos]] -> nodeslvl2[[i]]];
    Print["edges becomes  ", edges];
  ];
 Graph[edges, VertexLabels -> "Name"]
]

When I try to run the code on an easy example (*), I get the following error:
AppendTo::rvalue: {root->{2},root->{4},root->{6}} is not a variable with a value, so its value cannot be changed. I cannot understand the meaning of it, since my list of edges has a name, it's not like doing AppendTo[{1,2,3},4]! Also, my code doesn't actually seem different from this other (properly working) one, which does the same thing, but building just the first two layers of such a tree.

graphfrom2listsbasic[nodeslvl1_List, nodeslvl2_List] := 
 Module[{edges = {}, i, j, pos},
  For[i = 1, i < Length[nodeslvl1] + 1, i++,
   AppendTo[edges, "root" -> nodeslvl1[[i]]]
   ];
  Print["edges is  ", edges];
  For[j = 1, j < Length[nodeslvl2] + 1, j++,
   pos = Position[nodeslvl1, nodeslvl2[[j, 2 ;; 2]]][[1, 1]];
   AppendTo[edges, nodeslvl1[[pos]] -> nodeslvl2[[j]]]
   ];
  Print["edges is  ", edges];
  Graph[edges, VertexLabels -> "Name"]]

So what am I missing about the AppendTo command?
Thanks in advance!

(*) Here's the example, which is expected to produce the same result with both functions:

nodes1 = {{2}, {4}, {6}};
nodes2 = {{1, 2}, {1, 4}, {3, 4}, {1, 6}, {3, 6}, {5, 6}};
edgespartial = {"root" -> {2}, "root" -> {4}, "root" -> {6}};
graphfrom2listsbasic[nodes1,nodes2]
graphfrom2lists[edgespartial, nodes1, nodes2]
$\endgroup$
  • $\begingroup$ Are you trying to create a function that will modify its argument permanently? E.g. using a simpler example, after evaluating x={1,2}; addone[x], the value of x will have changed to, say, {1,2,1}. This is how AppendTo works. The more usual way of working in Mathematica is to leave x alone and return a modified list instead, just like Append does. Both solutions are possible though. Do I understand it right that you want to use the first one? $\endgroup$ – Szabolcs Feb 11 '15 at 16:03
  • $\begingroup$ @Szabolcs: Yes, you understood correctly. I want to modify the list edges, adding the additional connections for my expanded graph. $\endgroup$ – Andrea Orta Feb 11 '15 at 16:12
  • $\begingroup$ Add e2 = edges in the first argument inside Module (Module[{e2=edges, ...},...], and change edges to e2 in the rest (AppendTo[e2,...] and Graph[e2,...]. $\endgroup$ – kglr Feb 11 '15 at 16:18
  • $\begingroup$ In that case start by reading through this up to and including "Nonstandard Evaluation" and understanding why AppendTo needs to have the HoldFirst attribute while Append doesn't. See also here. Then we can go from there. In short, f[x_]:=AppendTo[x,1]; arr={3,2}; f[arr] will evaluate as f[arr] -> AppendTo[{3,2}, 1], which causes an error. The HoldFirst ... $\endgroup$ – Szabolcs Feb 11 '15 at 16:23
  • 1
    $\begingroup$ Please see specifically: (18737) $\endgroup$ – Mr.Wizard Feb 11 '15 at 16:33