use strict; use Graph::Undirected; use Graph::Directed; my @data = qw[ xxaa bbcc ]; ## take all equalities in the data, map each item to ## a canonical (equivalent) representative. my $eq = Graph::Undirected->new; $eq->add_edge( split /=/, $_ ) for grep /=/, @data; my %canonical; for ($eq->connected_components) { my $representative = $_->[0]; for (@$_) { $canonical{$_} = $representative; } } sub canonical { exists $canonical{$_[0]} ? $canonical{$_[0]} : $_[0]; } ## take all inequalities in the data, make a dag from them ## and take the transitive closure. my $g = Graph::Directed->new; for (grep !/=/, @data) { my ($x, $y) = split /<|>/, $_; ($x,$y) = ($y,$x) if /add_edge( canonical($x), canonical($y) ); } die "Not a DAG!" unless $g->is_dag; $g = $g->transitive_closure; sub compare { my ($x,$y) = map canonical($_), @_; return 0 if $x eq $y; return 1 if $g->has_edge($x,$y); return -1 if $g->has_edge($y,$x); return 0; } my @items = qw[ aa bb cc xx yy zz ]; for my $x (@items) { for my $y (@items) { print "$x, $y: " . compare($x,$y). $/; } }