:

## Representing a hierarchical table as a tree graph

Maple

In the applications I am working on, the information are often represented by hierarchical tables (that is tables where some entries can also be tables, and so on).
To help people to understand how this information is organized, I have thought to representent this hierarchical table as a tree graph.
Once this graph built, it becomes very simple to find where a "terminal leaf", that is en entry which is no longer a table, is located in the original table (by location I mean the sequence of indices for which the entry is this "terminal leaf".

The code provided here is pretension free and I do not doubt a single second  that people here will be able to improve it.
I published it for i thought other people could face the same kind of problems that I do.

 > restart
 > with(GraphTheory): interface(version);
 (1)
 > gh := proc(T)   global s, counter, types:   local  i:   if type(T, table) then     for i in [indices(T, nolist)] do       if type(T[i], table) then          s := s, op(map(u -> [i, u], [indices(T[i], nolist)] ));       else          counter := counter+1:          types   := types, _Z_||counter = whattype(T[i]);          s       := s, [i, _Z_||counter];       end if:       thisproc(T[i]):     end do:   else     return s   end if: end proc:
 > t := table([a1=[alpha=1, beta=2], a2=table([a21=2, a22=table([a221=x, a222=table([a2221={1, 2, 3}, a2222=Matrix(2, 2), a2223=u3, a2224=u4])])]), a3=table([a31=u, a32=v])]); global s, counter, types: s       := NULL: counter := 0: types   := NULL: ghres := gh(t): types := [types]:
 (2)

These 3 lines determine the set of edges of the form ['t', v], that are not been captured by procedure h.
They correspond to "first level" indices of table t (v in {a1, a2, a3} in the example above)

 > L := convert(op~(1, [ghres]), set):      R := convert(op~(2, [ghres]), set): FirstLevelEdges := map(u -> ['t', u], L union R minus R):

Complete the set of the edges, build the graph representation TG of table t and draw TG.

 > edges := convert~({ghres, FirstLevelEdges[]}, set): TG := Graph(edges): HighlightVertex(TG, Vertices(TG), white): p := DrawGraph(TG, style=tree, root='t'):

The first line is used to change the the "terminal leaves" of names  _Z_n by their type.

 > eval(t); p       := subs(types, p): enlarge := plottools:-transform((x,y) -> [3*x, y]): plots:-display(enlarge(p), size=[1000, 400]);

This procedure is used to find the "indices path" to a terminal leaf.
FindLeaf is then applied to all the terminal leaves.

 > FindLeaf := proc(TG, leaf)    local here:    here := GraphTheory:-ShortestPath(TG, 't', leaf)[1..-2]:    here := cat(convert(here[1], string), convert(here[2..-1], string)):    here := StringTools:-SubstituteAll(here, ",", "]["):    here := parse(here); end proc: # where is a2221 printf("%a\n", FindLeaf(TG, a2221));
 t[a2][a22][a222]
 >

﻿