return $self->{'graph'}->edge( @_ );
}
+# Not only adds the node, but also initializes internal data
+# about the node.
sub add_node {
my $self = shift;
- return $self->{'graph'}->add_node( @_ );
+ my $node = $self->{'graph'}->add_node( @_ );
+ $self->{'identical_nodes'}->{ $node->name() } = [ $node->name() ];
+ return $node;
}
sub add_edge {
sub del_node {
my $self = shift;
+ my $node = $_[0];
+
+ # Delete this node out of any relevant transposition pool.
+ if( ref $node eq 'Graph::Easy::Node' ) {
+ $node = $node->name();
+ }
+ my @ident = $self->identical_nodes( $node );
+ if( @ident ) {
+ # Get the pool.
+ my $pool = $self->{'identical_nodes'}->{ $ident[0] };
+ foreach my $i ( 0 .. scalar(@$pool)-1 ) {
+ if( $pool->[$i] eq $node ) {
+ splice( @$pool, $i, 1 );
+ last;
+ }
+ }
+ }
+ delete $self->{'identical_nodes'}->{ $node };
+
+ # Now delete the node.
return $self->{'graph'}->del_node( @_ );
}
my $self = shift;
my( $new_start ) = @_;
if( $new_start ) {
+ # Fix the node transposition data
+ delete $self->{'identical_nodes'}->{ $new_start->name() };
+ $self->{'identical_nodes'}->{'#START#'} = [ '#START#' ];
$self->{'graph'}->rename_node( $new_start, '#START#' );
}
return $self->{'graph'}->node('#START#');
}
-sub set_identical_nodes {
- my( $self, $node_hash ) = @_;
- $self->{'identical_nodes'} = $node_hash;
+# Record that nodes A and B are really the same (transposed) node.
+# We do this by maintaining some pools of transposed nodes, and
+# we have a lookup hash so that each member of that
+sub set_identical_node {
+ my( $self, $node, $same_node ) = @_;
+ my $pool = $self->{'identical_nodes'}->{ $node };
+ my $same_pool = $self->{'identical_nodes'}->{ $same_node };
+ my %poolhash;
+ foreach ( @$pool ) {
+ $poolhash{$_} = 1;
+ }
+ foreach( @$same_pool ) {
+ push( @$pool, $_ ) unless $poolhash{$_};
+ }
+
+ $self->{'identical_nodes'}->{ $same_node } = $pool;
+}
+
+sub identical_nodes {
+ my( $self, $node ) = @_;
+ my @others = grep { $_ !~ /^$node$/ }
+ @{$self->{'identical_nodes'}->{ $node }};
+ return @others;
}
sub next_word {
return $self->{'positions'}->colocated_nodes( @_ );
}
-sub identical_nodes {
- my( $self, $node ) = @_;
- return undef unless exists $self->{'identical_nodes'} &&
- exists $self->{'identical_nodes'}->{$node};
- return $self->{'identical_nodes'}->{$node};
-}
-
sub text_of_node {
my( $self, $node_id ) = @_;
# This is the label of the given node.
my %node_id = reverse %node_name;
## Record the nodes that are marked as transposed.
- my $id_xpath = '//g:node[g:data[@key="' . $nodedata{'identity'} . '"]]';
- my $transposed_nodes = $xpc->find( $id_xpath );
- my $identical_nodes;
- foreach my $tn ( @$transposed_nodes ) {
- $identical_nodes->{ $node_name{ $tn->getAttribute('id') }} =
- $node_name{ $xpc->findvalue( './g:data[@key="'
- . $nodedata{'identity'}
- . '"]/text()', $tn ) };
+ my $tr_xpath = '//g:node[g:data[@key="' . $nodedata{'identity'} . '"]]';
+ my $transposition_nodes = $xpc->find( $tr_xpath );
+ foreach my $tn ( @$transposition_nodes ) {
+ my $id_xpath = sprintf( './g:data[@key="%s"]/text()',
+ $nodedata{'identity'} );
+ $graph->set_identical_node( $node_name{ $tn->getAttribute( 'id' ) },
+ $node_name{ $xpc->findvalue( $id_xpath,
+ $tn ) } );
}
- $graph->set_identical_nodes( $identical_nodes );
# Find the beginning and end nodes of the graph. The beginning node
is( $graph->text_for_witness( "C" ), $wit_c, "Correct path for witness C" );
# Test the transposition identifiers
-my $transposed_nodes = { 2 => 9,
- 9 => 2,
- 14 => 18,
- 15 => 17,
- 17 => 15,
- 18 => 14
+my $transposition_pools = [ [ 2, 9 ], [ 14, 18 ], [ 15, 17 ] ];
+my $transposed_nodes = { 2 => $transposition_pools->[0],
+ 9 => $transposition_pools->[0],
+ 14 => $transposition_pools->[1],
+ 15 => $transposition_pools->[2],
+ 17 => $transposition_pools->[2],
+ 18 => $transposition_pools->[1],
};
+foreach my $n ( $graph->nodes() ) {
+ $transposed_nodes->{ $n->name() } = [ $n->name() ]
+ unless exists $transposed_nodes->{ $n->name() };
+}
is_deeply( $graph->{'identical_nodes'}, $transposed_nodes, "Found the right transpositions" );
# Test turning on a node