| 
									
										
										
										
											2008-06-20 22:52:44 -04:00
										 |  |  | ! Copyright (C) 2008 William Schlieper <schlieper@unc.edu> | 
					
						
							|  |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							| 
									
										
										
										
											2009-04-17 12:14:16 -04:00
										 |  |  | USING: kernel combinators fry continuations sequences arrays | 
					
						
							|  |  |  | vectors assocs hashtables heaps namespaces ;
 | 
					
						
							| 
									
										
										
										
											2008-06-20 22:52:44 -04:00
										 |  |  | IN: graph-theory | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MIXIN: graph | 
					
						
							|  |  |  | SYMBOL: visited? | 
					
						
							|  |  |  | ERROR: end-search ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: vertices ( graph -- seq ) flushable
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: num-vertices ( graph -- n ) flushable
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: num-edges ( graph -- n ) flushable
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: adjlist ( from graph -- seq ) flushable
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: adj? ( from to graph -- ? ) flushable
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: add-blank-vertex ( index graph -- )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: delete-blank-vertex ( index graph -- )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: add-edge* ( from to graph -- )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: add-edge ( u v graph -- )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: delete-edge* ( from to graph -- )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: delete-edge ( u v graph -- )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: graph num-vertices | 
					
						
							|  |  |  |     vertices length ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: graph num-edges | 
					
						
							| 
									
										
										
										
											2009-10-29 15:34:04 -04:00
										 |  |  |    [ vertices ] [ '[ _ adjlist length ] map-sum ] bi ;
 | 
					
						
							| 
									
										
										
										
											2008-06-20 22:52:44 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: graph adjlist | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  |     [ vertices ] [ swapd '[ _ swap _ adj? ] filter ] bi ;
 | 
					
						
							| 
									
										
										
										
											2008-06-20 22:52:44 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: graph adj? | 
					
						
							|  |  |  |     swapd adjlist index >boolean ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: graph add-edge | 
					
						
							|  |  |  |     [ add-edge* ] [ swapd add-edge* ] 3bi ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: graph delete-edge | 
					
						
							|  |  |  |     [ delete-edge* ] [ swapd delete-edge* ] 3bi ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : add-blank-vertices ( seq graph -- )
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  |     '[ _ add-blank-vertex ] each ;
 | 
					
						
							| 
									
										
										
										
											2008-06-20 22:52:44 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : delete-vertex ( index graph -- )
 | 
					
						
							|  |  |  |     [ adjlist ] | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  |     [ '[ _ _ 3dup adj? [ delete-edge* ] [ 3drop ] if ] each ] | 
					
						
							| 
									
										
										
										
											2008-06-20 22:52:44 -04:00
										 |  |  |     [ delete-blank-vertex ] 2tri ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : search-wrap ( quot graph -- ? )
 | 
					
						
							|  |  |  |     [ [ graph set ] [ vertices [ f 2array ] map >hashtable visited? set ] bi
 | 
					
						
							|  |  |  |       [ t ] compose [ dup end-search? [ drop f ] [ rethrow ] if ] recover ] with-scope ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : (depth-first) ( v pre post -- )
 | 
					
						
							|  |  |  |     { [ 2drop visited? get t -rot set-at ]  | 
					
						
							|  |  |  |       [ drop call ] | 
					
						
							|  |  |  |       [ [ graph get adjlist ] 2dip
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  |         '[ dup visited? get at [ drop ] [ _ _ (depth-first) ] if ] each ] | 
					
						
							| 
									
										
										
										
											2008-06-20 22:52:44 -04:00
										 |  |  |       [ nip call ] } 3cleave ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : depth-first ( v graph pre post -- ?list ? )
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  |     '[ _ _ (depth-first) visited? get ] swap search-wrap ; inline
 | 
					
						
							| 
									
										
										
										
											2008-06-20 22:52:44 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : full-depth-first ( graph pre post tail -- ? )
 | 
					
						
							|  |  |  |     '[ [ visited? get [ nip not ] assoc-find ]  | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  |        [ drop _ _ (depth-first) @ ]  | 
					
						
							| 
									
										
										
										
											2009-02-17 20:19:49 -05:00
										 |  |  |        while 2drop ] swap search-wrap ; inline
 | 
					
						
							| 
									
										
										
										
											2008-06-20 22:52:44 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : dag? ( graph -- ? )
 | 
					
						
							|  |  |  |     V{ } clone swap [ 2dup swap push dupd
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  |                      '[ _ swap graph get adj? not ] all?  | 
					
						
							| 
									
										
										
										
											2008-06-20 22:52:44 -04:00
										 |  |  |                       [ end-search ] unless ] | 
					
						
							|  |  |  |                     [ drop dup pop* ] [ ] full-depth-first nip ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : topological-sort ( graph -- seq/f )
 | 
					
						
							|  |  |  |     dup dag? | 
					
						
							| 
									
										
										
										
											2009-04-17 12:14:16 -04:00
										 |  |  |     [ V{ } clone swap [ drop ] [ prefix ] [ ] full-depth-first drop ] | 
					
						
							| 
									
										
										
										
											2008-06-20 22:52:44 -04:00
										 |  |  |     [ drop f ] if ;
 |