1// Copyright 2014 Sonia Keys
2// License MIT: http://opensource.org/licenses/MIT
3
4package graph
5
6import "github.com/soniakeys/bits"
7
8// FromList represents a rooted tree (or forest) where each node is associated
9// with a half arc identifying an arc "from" another node.
10//
11// Other terms for this data structure include "parent list",
12// "predecessor list", "in-tree", "inverse arborescence", and
13// "spaghetti stack."
14//
15// The Paths member represents the tree structure.  Leaves and MaxLen are
16// not always needed.  Where Leaves is used it serves as a bitmap where
17// Leaves.Bit(n) == 1 for each leaf n of the tree.  Where MaxLen is used it is
18// provided primarily as a convenience for functions that might want to
19// anticipate the maximum path length that would be encountered traversing
20// the tree.
21//
22// Various graph search methods use a FromList to returns search results.
23// For a start node of a search, From will be -1 and Len will be 1. For other
24// nodes reached by the search, From represents a half arc in a path back to
25// start and Len represents the number of nodes in the path.  For nodes not
26// reached by the search, From will be -1 and Len will be 0.
27//
28// A single FromList can also represent a forest.  In this case paths from
29// all leaves do not return to a single root node, but multiple root nodes.
30//
31// While a FromList generally encodes a tree or forest, it is technically
32// possible to encode a cyclic graph.  A number of FromList methods require
33// the receiver to be acyclic.  Graph methods documented to return a tree or
34// forest will never return a cyclic FromList.  In other cases however,
35// where a FromList is not known to by cyclic, the Cyclic method can be
36// useful to validate the acyclic property.
37type FromList struct {
38	Paths  []PathEnd // tree representation
39	Leaves bits.Bits // leaves of tree
40	MaxLen int       // length of longest path, max of all PathEnd.Len values
41}
42
43// PathEnd associates a half arc and a path length.
44//
45// A PathEnd list is an element type of FromList.
46type PathEnd struct {
47	From NI  // a "from" half arc, the node the arc comes from
48	Len  int // number of nodes in path from start
49}
50
51/* NewFromList could be confusing now with bits also needing allocation.
52maybe best to not have this function.  Maybe a more useful new would be
53one that took a PathEnd slice and intitialized everything including roots
54and max len.  Maybe its time for a separate []PathEnd type when that's
55all that's needed.  (and reconsider the name PathEnd)
56*/
57
58// NewFromList creates a FromList object of given order.
59//
60// The Paths member is allocated to the specified order n but other members
61// are left as zero values.
62func NewFromList(n int) FromList {
63	return FromList{Paths: make([]PathEnd, n)}
64}
65
66// BoundsOk validates the "from" values in the list.
67//
68// Negative values are allowed as they indicate root nodes.
69//
70// BoundsOk returns true when all from values are less than len(t).
71// Otherwise it returns false and a node with a from value >= len(t).
72func (f FromList) BoundsOk() (ok bool, n NI) {
73	for n, e := range f.Paths {
74		if int(e.From) >= len(f.Paths) {
75			return false, NI(n)
76		}
77	}
78	return true, -1
79}
80
81// CommonStart returns the common start node of minimal paths to a and b.
82//
83// It returns -1 if a and b cannot be traced back to a common node.
84//
85// The method relies on populated PathEnd.Len members.  Use RecalcLen if
86// the Len members are not known to be present and correct.
87func (f FromList) CommonStart(a, b NI) NI {
88	p := f.Paths
89	if p[a].Len < p[b].Len {
90		a, b = b, a
91	}
92	for bl := p[b].Len; p[a].Len > bl; {
93		a = p[a].From
94		if a < 0 {
95			return -1
96		}
97	}
98	for a != b {
99		a = p[a].From
100		if a < 0 {
101			return -1
102		}
103		b = p[b].From
104	}
105	return a
106}
107
108// Cyclic determines if f contains a cycle, a non-empty path from a node
109// back to itself.
110//
111// Cyclic returns true if g contains at least one cycle.  It also returns
112// an example of a node involved in a cycle.
113//
114// Cyclic returns (false, -1) in the normal case where f is acyclic.
115// Note that the bool is not an "ok" return.  A cyclic FromList is usually
116// not okay.
117func (f FromList) Cyclic() (cyclic bool, n NI) {
118	p := f.Paths
119	vis := bits.New(len(p))
120	for i := range p {
121		path := bits.New(len(p))
122		for n := i; vis.Bit(n) == 0; {
123			vis.SetBit(n, 1)
124			path.SetBit(n, 1)
125			if n = int(p[n].From); n < 0 {
126				break
127			}
128			if path.Bit(n) == 1 {
129				return true, NI(n)
130			}
131		}
132	}
133	return false, -1
134}
135
136// IsolatedNodeBits returns a bitmap of isolated nodes in receiver graph f.
137//
138// An isolated node is one with no arcs going to or from it.
139func (f FromList) IsolatedNodes() (iso bits.Bits) {
140	p := f.Paths
141	iso = bits.New(len(p))
142	iso.SetAll()
143	for n, e := range p {
144		if e.From >= 0 {
145			iso.SetBit(n, 0)
146			iso.SetBit(int(e.From), 0)
147		}
148	}
149	return
150}
151
152// PathTo decodes a FromList, recovering a single path.
153//
154// The path is returned as a list of nodes where the first element will be
155// a root node and the last element will be the specified end node.
156//
157// Only the Paths member of the receiver is used.  Other members of the
158// FromList do not need to be valid, however the MaxLen member can be useful
159// for allocating argument p.
160//
161// Argument p can provide the result slice.  If p has capacity for the result
162// it will be used, otherwise a new slice is created for the result.
163//
164// See also function PathTo.
165func (f FromList) PathTo(end NI, p []NI) []NI {
166	return PathTo(f.Paths, end, p)
167}
168
169// PathTo decodes a single path from a PathEnd list.
170//
171// A PathEnd list is the main data representation in a FromList.  See FromList.
172//
173// PathTo returns a list of nodes where the first element will be
174// a root node and the last element will be the specified end node.
175//
176// Argument p can provide the result slice.  If p has capacity for the result
177// it will be used, otherwise a new slice is created for the result.
178//
179// See also method FromList.PathTo.
180func PathTo(paths []PathEnd, end NI, p []NI) []NI {
181	n := paths[end].Len
182	if n == 0 {
183		return p[:0]
184	}
185	if cap(p) >= n {
186		p = p[:n]
187	} else {
188		p = make([]NI, n)
189	}
190	for {
191		n--
192		p[n] = end
193		if n == 0 {
194			return p
195		}
196		end = paths[end].From
197	}
198}
199
200// PathToLabeled decodes a FromList, recovering a single path.
201//
202// The start of the returned path will be a root node of the FromList.
203//
204// Only the Paths member of the receiver is used.  Other members of the
205// FromList do not need to be valid, however the MaxLen member can be useful
206// for allocating argument p.
207//
208// Argument p can provide the result slice.  If p has capacity for the result
209// it will be used, otherwise a new slice is created for the result.
210//
211// See also function PathTo.
212func (f FromList) PathToLabeled(end NI, labels []LI, p []Half) LabeledPath {
213	n := f.Paths[end].Len - 1
214	if n <= 0 {
215		return LabeledPath{end, p[:0]}
216	}
217	if cap(p) >= n {
218		p = p[:n]
219	} else {
220		p = make([]Half, n)
221	}
222	for {
223		n--
224		p[n] = Half{To: end, Label: labels[end]}
225		end = f.Paths[end].From
226		if n == 0 {
227			return LabeledPath{end, p}
228		}
229	}
230}
231
232// Preorder traverses a FromList in preorder.
233//
234// Nodes are visited in order such that for any node n with from node fr,
235// fr is visited before n.  Where f represents a tree, the visit ordering
236// corresponds to a preordering, or depth first traversal of the tree.
237// Where f represents a forest, the preorderings of the trees can be
238// intermingled.
239//
240// Leaves must be set correctly first.  Use RecalcLeaves if leaves are not
241// known to be set correctly.  FromList f cannot be cyclic.
242//
243// Traversal continues while visitor function v returns true.  It terminates
244// if v returns false.  Preorder returns true if it completes without v
245// returning false.  Preorder returns false if traversal is terminated by v
246// returning false.
247func (f FromList) Preorder(v func(NI) bool) bool {
248	p := f.Paths
249	done := bits.New(len(p))
250	var df func(NI) bool
251	df = func(n NI) bool {
252		done.SetBit(int(n), 1)
253		if fr := p[n].From; fr >= 0 && done.Bit(int(fr)) == 0 {
254			df(fr)
255		}
256		return v(n)
257	}
258	for n := range f.Paths {
259		p[n].Len = 0
260	}
261	return f.Leaves.IterateOnes(func(n int) bool {
262		return df(NI(n))
263	})
264}
265
266// RecalcLeaves recomputes the Leaves member of f.
267func (f *FromList) RecalcLeaves() {
268	p := f.Paths
269	lv := &f.Leaves
270	if lv.Num != len(p) {
271		*lv = bits.New(len(p))
272	}
273	lv.SetAll()
274	for n := range f.Paths {
275		if fr := p[n].From; fr >= 0 {
276			lv.SetBit(int(fr), 0)
277		}
278	}
279}
280
281// RecalcLen recomputes Len for each path end, and recomputes MaxLen.
282//
283// RecalcLen relies on the Leaves member being valid.  If it is not known
284// to be valid, call RecalcLeaves before calling RecalcLen.
285//
286// RecalcLen will panic if the FromList is cyclic.  Use the Cyclic method
287// if needed to verify that the FromList is acyclic.
288func (f *FromList) RecalcLen() {
289	p := f.Paths
290	var setLen func(NI) int
291	setLen = func(n NI) int {
292		switch {
293		case p[n].Len > 0:
294			return p[n].Len
295		case p[n].From < 0:
296			p[n].Len = 1
297			return 1
298		}
299		l := 1 + setLen(p[n].From)
300		p[n].Len = l
301		return l
302	}
303	for n := range f.Paths {
304		p[n].Len = 0
305	}
306	f.MaxLen = 0
307	f.Leaves.IterateOnes(func(n int) bool {
308		if l := setLen(NI(n)); l > f.MaxLen {
309			f.MaxLen = l
310		}
311		return true
312	})
313}
314
315// ReRoot reorients the tree containing n to make n the root node.
316//
317// It keeps the tree connected by "reversing" the path from n to the old root.
318//
319// After ReRoot, the Leaves and Len members are invalid.
320// Call RecalcLeaves or RecalcLen as needed.
321func (f *FromList) ReRoot(n NI) {
322	p := f.Paths
323	fr := p[n].From
324	if fr < 0 {
325		return
326	}
327	p[n].From = -1
328	for {
329		ff := p[fr].From
330		p[fr].From = n
331		if ff < 0 {
332			return
333		}
334		n = fr
335		fr = ff
336	}
337}
338
339// Root finds the root of a node in a FromList.
340func (f FromList) Root(n NI) NI {
341	for p := f.Paths; ; {
342		fr := p[n].From
343		if fr < 0 {
344			return n
345		}
346		n = fr
347	}
348}
349
350// Transpose constructs the directed graph corresponding to FromList f
351// but with arcs in the opposite direction.  That is, from roots toward leaves.
352//
353// If non-nil argrument roots is passed, Transpose populates it as roots of
354// the resulting forest and returns nRoots as a count of the roots.
355//
356// The method relies only on the From member of f.Paths.  Other members of
357// the FromList are not used.
358func (f FromList) Transpose(roots *bits.Bits) (forest Directed, nRoots int) {
359	p := f.Paths
360	g := make(AdjacencyList, len(p))
361	if roots != nil {
362		nRoots = len(p)
363		if roots.Num != nRoots {
364			*roots = bits.New(nRoots)
365		}
366		roots.SetAll()
367	}
368	for i, e := range p {
369		if e.From == -1 {
370			continue
371		}
372		g[e.From] = append(g[e.From], NI(i))
373		if roots != nil && roots.Bit(i) == 1 {
374			roots.SetBit(i, 0)
375			nRoots--
376		}
377	}
378	return Directed{g}, nRoots
379}
380
381// TransposeLabeled constructs the labeled directed graph corresponding
382// to FromList f but with arcs in the opposite direction.  That is, from
383// roots toward leaves.
384//
385// The argument labels can be nil.  In this case labels are generated matching
386// the path indexes.  This corresponds to the "to", or child node.
387//
388// If labels is non-nil, it must be the same length as t.Paths and is used
389// to look up label numbers by the path index.
390//
391// If non-nil argrument roots is passed, Transpose populates it as roots of
392// the resulting forest and returns nRoots as a count of the roots.
393//
394// The method relies only on the From member of f.Paths.  Other members of
395// the FromList are not used.
396func (f FromList) TransposeLabeled(labels []LI, roots *bits.Bits) (forest LabeledDirected, nRoots int) {
397	p := f.Paths
398	g := make(LabeledAdjacencyList, len(p))
399	if roots != nil {
400		nRoots = len(p)
401		if roots.Num != nRoots {
402			*roots = bits.New(nRoots)
403		}
404		roots.SetAll()
405	}
406	for i, p := range f.Paths {
407		if p.From == -1 {
408			continue
409		}
410		l := LI(i)
411		if labels != nil {
412			l = labels[i]
413		}
414		g[p.From] = append(g[p.From], Half{NI(i), l})
415		if roots != nil && roots.Bit(i) == 1 {
416			roots.SetBit(i, 0)
417			nRoots--
418		}
419	}
420	return LabeledDirected{g}, nRoots
421}
422
423// Undirected constructs the undirected graph corresponding to FromList f.
424//
425// The resulting graph will be a tree or forest.
426//
427// If non-nil argrument roots is passed, Transpose populates it as roots of
428// the resulting forest and returns nRoots as a count of the roots.
429//
430// The method relies only on the From member of f.Paths.  Other members of
431// the FromList are not used.
432func (f FromList) Undirected(roots *bits.Bits) (forest Undirected, nRoots int) {
433	p := f.Paths
434	g := make(AdjacencyList, len(p))
435	if roots != nil {
436		nRoots = len(p)
437		if roots.Num != nRoots {
438			*roots = bits.New(nRoots)
439		}
440		roots.SetAll()
441	}
442	for i, e := range p {
443		if e.From == -1 {
444			continue
445		}
446		g[i] = append(g[i], e.From)
447		g[e.From] = append(g[e.From], NI(i))
448		if roots != nil && roots.Bit(i) == 1 {
449			roots.SetBit(i, 0)
450			nRoots--
451		}
452	}
453	return Undirected{g}, nRoots
454}
455
456// LabeledUndirected constructs the labeled undirected graph corresponding
457// to FromList f.
458//
459// The resulting graph will be a tree or forest.
460//
461// The argument labels can be nil.  In this case labels are generated matching
462// the path indexes.  This corresponds to the "to", or child node.
463//
464// If labels is non-nil, it must be the same length as t.Paths and is used
465// to look up label numbers by the path index.
466//
467// If non-nil argrument roots is passed, LabeledUndirected populates it as
468// roots of the resulting forest and returns nRoots as a count of the roots.
469//
470// The method relies only on the From member of f.Paths.  Other members of
471// the FromList are not used.
472func (f FromList) LabeledUndirected(labels []LI, roots *bits.Bits) (forest LabeledUndirected, nRoots int) {
473	p := f.Paths
474	g := make(LabeledAdjacencyList, len(p))
475	if roots != nil {
476		nRoots = len(p)
477		if roots.Num != nRoots {
478			*roots = bits.New(nRoots)
479		}
480		roots.SetAll()
481	}
482	for i, p := range f.Paths {
483		if p.From == -1 {
484			continue
485		}
486		l := LI(i)
487		if labels != nil {
488			l = labels[i]
489		}
490		g[i] = append(g[i], Half{p.From, l})
491		g[p.From] = append(g[p.From], Half{NI(i), l})
492		if roots != nil && roots.Bit(i) == 1 {
493			roots.SetBit(i, 0)
494			nRoots--
495		}
496	}
497	return LabeledUndirected{g}, nRoots
498}
499