Tcl Library Source Code

Check-in [4cabcb175c]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment: Small fixes in the disjoint code (removed references to pairs, slight typos). Added references to data structure overview, and papers with time/complexity proofs. Fixed up dependent packages (now requiring 8.6 as well). Fixed package index of the module.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | pooryorick | kbk-refactor-disjointset
Files: files | file ages | folders
SHA3-256: 4cabcb175cfdaf56c1b9277c4a1d1c689127cababfc0b5756224f47efba1fcaa
User & Date: aku 2018-11-22 05:22:09.194
Context
2018-11-26
05:02
Integrated disjoint-set work by Kevin. Somehow I completely forgot to do this integration after doing my changes. :facepalm: Fixed. And looking at the timeline from this merge it becomes clear that I actually had the merge done locally already and then forgot to commit and sync. check-in: 74b6db9a0d user: aku tags: pooryorick
03:55
merge trunk Closed-Leaf check-in: 964a058df2 user: kbk tags: pooryorick, kbk-refactor-disjointset
2018-11-22
05:22
Small fixes in the disjoint code (removed references to pairs, slight typos). Added references to data structure overview, and papers with time/complexity proofs. Fixed up dependent packages (now requiring 8.6 as well). Fixed package index of the module. check-in: 4cabcb175c user: aku tags: pooryorick, kbk-refactor-disjointset
2018-11-20
05:56
Update version number in manual check-in: ccd844fad4 user: kbk tags: pooryorick, kbk-refactor-disjointset
Changes
Unified Diff Ignore Whitespace Patch
Changes to modules/struct/disjointset.man.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

[manpage_begin struct::disjointset n 1.1]
[keywords {disjoint set}]
[keywords {equivalence class}]
[keywords find]
[keywords {merge find}]
[keywords partition]
[keywords {partitioned set}]
[keywords union]
[moddesc   {Tcl Data Structures}]
[titledesc {Disjoint set data structure}]
[category  {Data structures}]
[require Tcl 8.6]
[require struct::disjointset [opt 1.1]]
[description]
[para]

This package provides [term {disjoint sets}]. An alternative name for
this kind of structure is [term {merge-find}].

[para]
>
|











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[vset VERSION 1.1]
[manpage_begin struct::disjointset n [vset VERSION]]
[keywords {disjoint set}]
[keywords {equivalence class}]
[keywords find]
[keywords {merge find}]
[keywords partition]
[keywords {partitioned set}]
[keywords union]
[moddesc   {Tcl Data Structures}]
[titledesc {Disjoint set data structure}]
[category  {Data structures}]
[require Tcl 8.6]
[require struct::disjointset [opt [vset VERSION]]]
[description]
[para]

This package provides [term {disjoint sets}]. An alternative name for
this kind of structure is [term {merge-find}].

[para]
Changes to modules/struct/disjointset.tcl.
1
2
3
4
5
6
7
8










9
10
11
12
13
14
15
# disjointset.tcl --
#
#  Implementation of a Disjoint Set for Tcl.
#
# Copyright (c) Google Summer of Code 2008 Alejandro Eduardo Cruz Paz
# Copyright (c) 2008 Andreas Kupries (API redesign and simplification)
# Copyright (c) 2018 by Kevin B. Kenny - reworked to a proper disjoint-sets
# data structure, added 'add-element', 'exemplars' and 'find-exemplar'.











package require Tcl 8.6

# Initialize the disjointset structure namespace. Note that any
# missing parent namespace (::struct) will be automatically created as
# well.
namespace eval ::struct::disjointset {








>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# disjointset.tcl --
#
#  Implementation of a Disjoint Set for Tcl.
#
# Copyright (c) Google Summer of Code 2008 Alejandro Eduardo Cruz Paz
# Copyright (c) 2008 Andreas Kupries (API redesign and simplification)
# Copyright (c) 2018 by Kevin B. Kenny - reworked to a proper disjoint-sets
# data structure, added 'add-element', 'exemplars' and 'find-exemplar'.

# References
#
# - General overview
#   - https://en.wikipedia.org/wiki/Disjoint-set_data_structure
#
# - Time/Complexity proofs
#   - https://dl.acm.org/citation.cfm?doid=62.2160
#   - https://dl.acm.org/citation.cfm?doid=364099.364331
#

package require Tcl 8.6

# Initialize the disjointset structure namespace. Note that any
# missing parent namespace (::struct) will be automatically created as
# well.
namespace eval ::struct::disjointset {
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

    # elements - Dictionary whose keys are all the elements in the structure,
    #            and whose values are element numbers. 
    # tree     - List indexed by element number whose members are
    #            ordered triples consisting of the element's name,
    #            the element number of the element's parent (or the element's
    #            own index if the element is a root), and the rank of
    #		 the element
    # nParts   - Number of partitions in the structure. Maintained only
    #            so that num_partitions will work.

    variable elements tree nParts

    constructor {} {
	set elements {}







|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

    # elements - Dictionary whose keys are all the elements in the structure,
    #            and whose values are element numbers. 
    # tree     - List indexed by element number whose members are
    #            ordered triples consisting of the element's name,
    #            the element number of the element's parent (or the element's
    #            own index if the element is a root), and the rank of
    #		 the element.
    # nParts   - Number of partitions in the structure. Maintained only
    #            so that num_partitions will work.

    variable elements tree nParts

    constructor {} {
	set elements {}
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
    #
    # Results:
    #	Returns a list of element names

    method exemplars {} {
	set result {}
	set n -1
	foreach pair $tree {
	    if {[lindex $pair 1] == [incr n]} {
		lappend result [lindex $pair 0]
	    }
	}
	return $result
    }

    # find --
    #
    #	Find the partition to which a given element belongs.
    #
    # Parameters:
    #	item - Item to find
    #
    # Results:
    #	Returns a list of the partition's members
    #
    # Notes:
    #	This operation takes time proportional to the total number of elements
    #	in the disjoint-sets structure. If a simple name of the partition
    #	is all that is required, use find_exemplar instead, which runs
    #	in amortized time proportional to the inverse Ackermann function of
    #	the size of the partition.

    method find {item} {
	set result {}
	# No error on a nonexistent item
	if {![dict exists $elements $item]} {
	    return {}
	}
	set pnum [my FindNum $item]
	set n -1
	foreach pair $tree {
	    if {[my FindByNum [incr n]] eq $pnum} {
		lappend result [lindex $pair 0]
	    }
	}
	return $result
    }

    # find-exemplar --
    #







|
|
|


















|











|

|







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
    #
    # Results:
    #	Returns a list of element names

    method exemplars {} {
	set result {}
	set n -1
	foreach row $tree {
	    if {[lindex $row 1] == [incr n]} {
		lappend result [lindex $row 0]
	    }
	}
	return $result
    }

    # find --
    #
    #	Find the partition to which a given element belongs.
    #
    # Parameters:
    #	item - Item to find
    #
    # Results:
    #	Returns a list of the partition's members
    #
    # Notes:
    #	This operation takes time proportional to the total number of elements
    #	in the disjoint-sets structure. If a simple name of the partition
    #	is all that is required, use "find-exemplar" instead, which runs
    #	in amortized time proportional to the inverse Ackermann function of
    #	the size of the partition.

    method find {item} {
	set result {}
	# No error on a nonexistent item
	if {![dict exists $elements $item]} {
	    return {}
	}
	set pnum [my FindNum $item]
	set n -1
	foreach row $tree {
	    if {[my FindByNum [incr n]] eq $pnum} {
		lappend result [lindex $row 0]
	    }
	}
	return $result
    }

    # find-exemplar --
    #
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
    }
    
    # partitions --
    #
    #	Enumerates the partitions of a disjoint-sets data structure
    #
    # Results:
    #	Returns a list of lists. Each list is one of the disjoint sets,
    #	and each member of the sublist is one of the elements added to
    #	the structure.

    method partitions {} {

	# Find the partition number for each element, and accumulate a list
	# per partition
	set parts {}
	dict for {element eltNo} $elements {
	    set partNo [my FindByNum $eltNo]
	    dict lappend parts $partNo $element
	}
	return [dict values $parts]
    }







|
|
|



|
|







238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
    }
    
    # partitions --
    #
    #	Enumerates the partitions of a disjoint-sets data structure
    #
    # Results:
    #	Returns a list of lists. Each list is one of the partitions
    #	in the disjoint set, and each member of the sublist is one
    #	of the elements added to the structure.

    method partitions {} {

	# Find the partition number for each element, and accumulate a
	# list per partition
	set parts {}
	dict for {element eltNo} $elements {
	    set partNo [my FindByNum $eltNo]
	    dict lappend parts $partNo $element
	}
	return [dict values $parts]
    }
368
369
370
371
372
373
374


namespace eval ::struct {
    namespace import disjointset::disjointset
    namespace export disjointset
}

package provide struct::disjointset 1.1








>
378
379
380
381
382
383
384
385

namespace eval ::struct {
    namespace import disjointset::disjointset
    namespace export disjointset
}

package provide struct::disjointset 1.1
return
Changes to modules/struct/graphops.man.
1

2
3
4
5
6
7
8
9
[comment {-*- tcl -*-}]

[manpage_begin struct::graph::op n 0.11.3]
[keywords {adjacency list}]
[keywords {adjacency matrix}]
[keywords adjacent]
[keywords {approximation algorithm}]
[keywords arc]
[keywords {articulation point}]
[keywords {augmenting network}]

>
|







1
2
3
4
5
6
7
8
9
10
[comment {-*- tcl -*-}]
[vset VERSION 0.11.3]
[manpage_begin struct::graph::op n [vset VERSION]]
[keywords {adjacency list}]
[keywords {adjacency matrix}]
[keywords adjacent]
[keywords {approximation algorithm}]
[keywords arc]
[keywords {articulation point}]
[keywords {augmenting network}]
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
[keywords {vertex cover}]
[copyright {2008 Alejandro Paz <[email protected]>}]
[copyright {2008 (docs) Andreas Kupries <[email protected]>}]
[copyright {2009 Michal Antoniewski <[email protected]>}]
[moddesc   {Tcl Data Structures}]
[titledesc {Operation for (un)directed graph objects}]
[category  {Data structures}]
[require Tcl 8.4]
[require struct::graph::op [opt 0.11.3]]
[comment {[require struct::graph [opt 2.3]]   }]
[comment {[require struct::list  [opt 1.5]]   }]
[comment {[require struct::set   [opt 2.2.3]] }]
[description]
[para]

The package described by this document, [package struct::graph::op],







|
|







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
[keywords {vertex cover}]
[copyright {2008 Alejandro Paz <[email protected]>}]
[copyright {2008 (docs) Andreas Kupries <[email protected]>}]
[copyright {2009 Michal Antoniewski <[email protected]>}]
[moddesc   {Tcl Data Structures}]
[titledesc {Operation for (un)directed graph objects}]
[category  {Data structures}]
[require Tcl 8.6]
[require struct::graph::op [opt [vset VERSION]]]
[comment {[require struct::graph [opt 2.3]]   }]
[comment {[require struct::list  [opt 1.5]]   }]
[comment {[require struct::set   [opt 2.2.3]] }]
[description]
[para]

The package described by this document, [package struct::graph::op],
Changes to modules/struct/graphops.tcl.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: graphops.tcl,v 1.19 2009/09/24 19:30:10 andreas_kupries Exp $

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.5

package require struct::disjointset ; # Used by kruskal
package require struct::prioqueue   ; # Used by kruskal, prim
package require struct::queue       ; # Used by isBipartite?, connectedComponent(Of)
package require struct::stack       ; # Used by tarjan
package require struct::graph       ; # isBridge, isCutVertex
package require struct::tree        ; # Used by BFS

# ### ### ### ######### ######### #########







|

|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: graphops.tcl,v 1.19 2009/09/24 19:30:10 andreas_kupries Exp $

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.6

package require struct::disjointset ; # Used by kruskal -- 8.6 required
package require struct::prioqueue   ; # Used by kruskal, prim
package require struct::queue       ; # Used by isBipartite?, connectedComponent(Of)
package require struct::stack       ; # Used by tarjan
package require struct::graph       ; # isBridge, isCutVertex
package require struct::tree        ; # Used by BFS

# ### ### ### ######### ######### #########
Changes to modules/struct/graphops.test.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2.0

support {
    useLocal list.tcl struct::list

    useAccel [useTcllibC] struct/tree.tcl  struct::tree
    TestAccelInit                          struct::tree







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.6
testsNeedTcltest 2.0

support {
    useLocal list.tcl struct::list

    useAccel [useTcllibC] struct/tree.tcl  struct::tree
    TestAccelInit                          struct::tree
Changes to modules/struct/pkgIndex.tcl.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22





23
if {![package vsatisfies [package provide Tcl] 8.2]} {return}
package ifneeded struct            2.1   [list source [file join $dir struct.tcl]]
package ifneeded struct            1.4   [list source [file join $dir struct1.tcl]]

package ifneeded struct::queue     1.4.5 [list source [file join $dir queue.tcl]]
package ifneeded struct::stack     1.5.3 [list source [file join $dir stack.tcl]]
package ifneeded struct::tree      2.1.2 [list source [file join $dir tree.tcl]]
package ifneeded struct::matrix    2.0.3 [list source [file join $dir matrix.tcl]]
package ifneeded struct::pool      1.2.3 [list source [file join $dir pool.tcl]]
package ifneeded struct::record    1.2.1 [list source [file join $dir record.tcl]]
package ifneeded struct::set       2.2.3 [list source [file join $dir sets.tcl]]
package ifneeded struct::disjointset 1.0 [list source [file join $dir disjointset.tcl]]
package ifneeded struct::prioqueue 1.4   [list source [file join $dir prioqueue.tcl]]
package ifneeded struct::skiplist  1.3   [list source [file join $dir skiplist.tcl]]

package ifneeded struct::graph     1.2.1 [list source [file join $dir graph1.tcl]]
package ifneeded struct::tree      1.2.2 [list source [file join $dir tree1.tcl]]
package ifneeded struct::matrix    1.2.1 [list source [file join $dir matrix1.tcl]]

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded struct::list      1.8.3  [list source [file join $dir list.tcl]]
package ifneeded struct::graph     2.4.1  [list source [file join $dir graph.tcl]]





package ifneeded struct::graph::op 0.11.3 [list source [file join $dir graphops.tcl]]











<










>
>
>
>
>

1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
if {![package vsatisfies [package provide Tcl] 8.2]} {return}
package ifneeded struct            2.1   [list source [file join $dir struct.tcl]]
package ifneeded struct            1.4   [list source [file join $dir struct1.tcl]]

package ifneeded struct::queue     1.4.5 [list source [file join $dir queue.tcl]]
package ifneeded struct::stack     1.5.3 [list source [file join $dir stack.tcl]]
package ifneeded struct::tree      2.1.2 [list source [file join $dir tree.tcl]]
package ifneeded struct::matrix    2.0.3 [list source [file join $dir matrix.tcl]]
package ifneeded struct::pool      1.2.3 [list source [file join $dir pool.tcl]]
package ifneeded struct::record    1.2.1 [list source [file join $dir record.tcl]]
package ifneeded struct::set       2.2.3 [list source [file join $dir sets.tcl]]

package ifneeded struct::prioqueue 1.4   [list source [file join $dir prioqueue.tcl]]
package ifneeded struct::skiplist  1.3   [list source [file join $dir skiplist.tcl]]

package ifneeded struct::graph     1.2.1 [list source [file join $dir graph1.tcl]]
package ifneeded struct::tree      1.2.2 [list source [file join $dir tree1.tcl]]
package ifneeded struct::matrix    1.2.1 [list source [file join $dir matrix1.tcl]]

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded struct::list      1.8.3  [list source [file join $dir list.tcl]]
package ifneeded struct::graph     2.4.1  [list source [file join $dir graph.tcl]]

if {![package vsatisfies [package provide Tcl] 8.5]} {return}

if {![package vsatisfies [package provide Tcl] 8.6]} {return}
package ifneeded struct::disjointset 1.1 [list source [file join $dir disjointset.tcl]]
package ifneeded struct::graph::op 0.11.3 [list source [file join $dir graphops.tcl]]