Skip to content

subgraph of an transitive closure fails #39

@michro6ok

Description

@michro6ok

Description:

I am trying to extract a subgraph from the non-reflexive transitive closure of a directed graph.
This subgraph is defined by a set of vertices with a specific attribute.
No other modifications will be made afterwards – I am only extracting the subgraph.

Issue:

The function transitive_closure returns a Graph::TransitiveClosure object. The subgraph function calls the constructor of the graph with no parameters. The constructor of Graph::TransitiveClosure requires a graph object and fails because no parameters are passed.

I can work around this by blessing the Graph::TransitiveClosure object to a Graph before calling the subgraph function.
However, this feels like a hack, so I am asking for your help to find a better way of doing this. Would you consider supporting subgraphs of transitive closures?

How to reproduce:

perl -e 'use Graph; use Graph::TransitiveClosure; Graph->new->transitive_closure->subgraph([]);'
Use of uninitialized value $g in concatenation (.) or string at /usr/share/perl5/Graph/TransitiveClosure.pm line 17.
Graph::TransitiveClosure->new given non-Graph '' at /usr/share/perl5/Graph.pm line 7.
	Graph::__carp_confess("Graph::TransitiveClosure->new given non-Graph ''") called at /usr/share/perl5/Graph/TransitiveClosure.pm line 17
	Graph::TransitiveClosure::new(Graph::TransitiveClosure=ARRAY(0x56fd51a3ee78)) called at /usr/share/perl5/Graph.pm line 1223
	Graph::subgraph(Graph::TransitiveClosure=ARRAY(0x56fd51a3ee78), ARRAY(0x56fd515fe3e8)) called at -e line 1

A simple example script:

#!/usr/bin/perl
use strict;
use warnings;
use Graph;

my $g = Graph->new(directed => 1);
$g->add_vertex('A');
$g->add_vertex('B');
$g->add_vertex('C');
$g->add_edge('A', 'B');
$g->add_edge('B', 'C');
$g->set_vertex_attribute('A', 'green', 1);
$g->set_vertex_attribute('B', 'green', 0);
$g->set_vertex_attribute('C', 'green', 1);

my $tc = $g->transitive_closure(reflexive => 0);
print "\n[Transitive Closure]\n";
for my $v (grep {$tc->successors($_)} $tc->vertices) {
    print "$v -> ", join(', ', $tc->successors($v)), "\n"; 
}

my @vertices = grep { $g->get_vertex_attribute($_, 'green') } $g->vertices;
$tc = bless $tc, 'Graph'; #<-- this is the workaround i want to avoid
my $subg = $tc->subgraph(\@vertices);
print "\n[Subgraph]\n";
for my $v (grep {$subg->successors($_)} $subg->vertices) {
    print "$v -> ", join(', ', $subg->successors($v)), "\n";
}

The expected output is:

[Transitive Closure]
A -> C, B
B -> C

[Subgraph]
A -> C

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions