File: enum_graph.pl

package info (click to toggle)
polymake 4.14-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 35,888 kB
  • sloc: cpp: 168,933; perl: 43,407; javascript: 31,575; ansic: 3,007; java: 2,654; python: 632; sh: 268; xml: 117; makefile: 61
file content (118 lines) | stat: -rw-r--r-- 3,190 bytes parent folder | download | duplicates (4)
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
####################################################################################################
#--------------------------------------------------------------------------------------------------
# This perl script provides functions for computing the 
# enumeration graph described in 
#   Sturmfels, 'Groebner Bases and Convex Polytopes'(Algorithm 5.7).
#--------------------------------------------------------------------------------------------------
####################################################################################################


#use application 'polytope';
#use application 'graph';

sub lex_sort {
    my ($vecs) = @_;
    my @vecs = map{ $vecs->[$_] } 0..$vecs->rows-1;
    my @sorted_vecs = sort{$a cmp $b} @vecs;
    return new Matrix<Rational>(\@sorted_vecs);
}

sub contained {
    my ($vec,$array_ref)=@_;
    my $is_contained=0;
    foreach (@$array_ref) {
	if ( ($vec cmp $_) == 0 ) {
	    $is_contained=1;
	}
    }
    return $is_contained;
}

sub is_greater_zero {
    my ($vec) = @_;
    my $is_greater=1;
    foreach( @$vec ) {
	if( $_ < 0 ) {
	    $is_greater=0;
	}
    }
    return $is_greater;
}

sub find_sink {
    my ($feas_sol, $groeb_elems) = @_;
    my $is_reducible=1;
    my $cur=$feas_sol;
    my $zero=new Vector<Int>(zero_vector($feas_sol->dim));
    while ($is_reducible) {
	foreach( @$groeb_elems ){
	    if( is_greater_zero($cur-$_->first) ) {
		print $cur. " -> ";
		$cur=find_sink($cur-$_->first+$_->second, $groeb_elems);
	    }
	}
	$is_reducible=0;
    }
    return $cur;
}

sub enum_graph {
    my ($feas_sol, $groeb_elems) = @_;
    my $sink = find_sink($feas_sol, $groeb_elems);
    print $sink."\n";
    my @active=($sink);
    my %passive=();
    my %nodes=();
    my $node_count=0;
    my @Coords=();

    while (@active) { #bfs queue not empty
	my $cur=shift(@active);
	push(@Coords,$cur);
	my $neighbors=new Set< Vector<Int> >();
	my $info=new Pair< Int, Set< Vector<Int> > >();
	foreach my $groeb_elem (@$groeb_elems) {
	    my $diff=$cur-$groeb_elem->second;
	    if ( is_greater_zero($diff) ) {
		my $new=$diff+$groeb_elem->first;
		$neighbors+=$new;

# FIXME: The 'contained'-function is just a bad work-around 
# because I don't know a better data structure for 'active'!
# Set does not work because I cannot ask whether a vector is contained in a set!
		if ( !exists( $passive{sprintf($new)} ) && !contained($new,\@active) ) { 
		    push(@active,$new);
		}
	    }
	}
	print $node_count.": ".$cur.": ".$neighbors."\n";
	$info->first=$node_count;
	$info->second=$neighbors;
	$passive{sprintf($cur)}=$info;
	$node_count++;
    }

    my $g=new GraphAdjacency<Directed>($node_count);
    foreach ( values %passive ) {
	my $node=$_->first;
	my @neighbors=@{$_->second};
	foreach my $neighbor (@neighbors) {
	    $g->edge(($passive{sprintf($neighbor)})->first,$node);
	}
    }
    return [(new graph::Graph<Directed>(ADJACENCY=>$g)),\@Coords];
}




################################################################################################
# End
################################################################################################



# Local Variables:
# c-basic-offset:3
# mode: perl
# End: