CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
[SOLVED] Problem printing return value from a subroutine

 



zing
Novice

Oct 3, 2012, 7:31 PM

Post #1 of 18 (3476 views)
[SOLVED] Problem printing return value from a subroutine Can't Post

Hi all,
I have this code

Code
#This program read the triplets from file named "data" into 
#an array of array.
use strict;
use warnings;
use Data::Dumper;
use Graph;
use Graph::Subgraph;

my @S;
while (<>) {
push @S, [ split ];
}
print "-----TRIPLETS-------\n";
print Dumper \@S;
#Make a copy of @S
my @trip = map { [@$_] } @S;

# Find the number of vertices
my @L;
for my $i ( 0 .. $#S ) {
for my $j ( 0 .. $#{ $S[$i] } ) {
push (@L,$S[$i][$j]);
}
}
my %seen;
@L = grep { ! $seen{ $_ }++ } @L;
print " ----VERTICES------\n";
print Dumper \@L;


# Now lets generate the G(L)
# In order to generate the G(L) we'll extract first two columns of S into another matrix
my @GL=@S;
splice(@$_, 2, 1)
foreach @GL;
print "----EDGE LIST TO BUILD G(L)-----\n";
print Dumper \@GL;

#my %h = map { $_->[0] => $_->[1] } @S;
#print Dumper(\%h);


##### CONNECTED COMPONENTS ##########
my $g = Graph->new( undirected => 1 );

my @a;
my @b;
for (my $p = 0; $p <= 2; $p++) {
$a[$p]=$S[$p][0];
}

for (my $q = 0; $q <= 2; $q++) {
$b[$q]=$S[$q][1];
}

for (my $r = 0; $r <= 2; $r++) {
$g->add_edge($a[$r], $b[$r]);
}

my @subgraphs = $g->connected_components;
my @allgraphs;
my $V = $g->vertices;
print "Number of taxa=$V\n";


my $q=scalar @subgraphs;
print "Number of connected components ", $q , "\n";
print "First connected component: ", @{ $subgraphs[0] }, "\n";
print "First connected component element: ", $subgraphs[0][1], "\n\n";


sub induced {
my (@z)=@_;
for my $QT (\@z ){
#print Dumper $QT;
for my $triplet ( @trip ){
my %Pie;
undef @Pie{@$QT};
delete @Pie{ @$triplet };
print "@$triplet\n" if keys(%Pie) <= ( @$QT - @$triplet ) ;
return (@$triplet);
}
}}
my @C;
my $d;
my $p=$#subgraphs+1;
for ($d=$p; $d >=1; $d--)
{
print "component $d = @{ $subgraphs[$d-1] }\n";
my $qw=induced(@{ $subgraphs[$d-1] });
print "induced=$qw\n";

}

It takes in the data from data file ,the content of which is

Code
-----------DATA---------- 
b c a
a c d
d e b

---OUTPUT----

Code
----TRIPLETS------- 
$VAR1 = [
[
'b',
'c',
'a'
],
[
'a',
'c',
'd'
],
[
'd',
'e',
'b'
]
];
----VERTICES------
$VAR1 = [
'b',
'c',
'a',
'd',
'e'
];
----EDGE LIST TO BUILD G(L)-----
$VAR1 = [
[
'b',
'c'
],
[
'a',
'c'
],
[
'd',
'e'
]
];
Number of taxa=5
Number of connected components 2
First connected component: cba
First connected component element: b

component 2 = e d
induced=3
component 1 = c b a
b c a
induced=3


Problem is with the last 5 lines of the output ,it should have been this

Code
component 2 = e d 
component 1 = c b a
induced=b c a

I know the problem is there in the way the subroutine return value is saved. Please suggest me why is this happening and how to fix it.


(This post was edited by zing on Oct 8, 2012, 10:14 AM)


Laurent_R
Veteran / Moderator

Oct 4, 2012, 1:25 AM

Post #2 of 18 (3459 views)
Re: [zing] Problem printing return value from a subroutine [In reply to] Can't Post

Hi,

I haven't tried to understand your full program, but I think the problem you have is probably there:


Code
my $qw=induced(@{ $subgraphs[$d-1] });


The induced subroutine returns an array (@triplet), but $qw is a scalar. If you are using an array in scalar context, you will get the number of elements of the array, rather than the elements of the array.


zing
Novice

Oct 4, 2012, 1:48 AM

Post #3 of 18 (3457 views)
Re: [Laurent_R] Problem printing return value from a subroutine [In reply to] Can't Post

Hi Laurent,
I tried this as per your suggestion:

Code
 my @qw=induced(@{ $subgraphs[$d-1] }); 
print Dumper @qw;


The output

Code
component 2 = e d 
b
c
a
Induced==$VAR1 = 'b';
$VAR2 = 'c';
$VAR3 = 'a';
component 1 = c b a
b c a
b
c
a
Induced==$VAR1 = 'b';
$VAR2 = 'c';
$VAR3 = 'a';


whereas I want this

Code
component 2 = e d 
component 1 = c b a
induced=b c a



Laurent_R
Veteran / Moderator

Oct 4, 2012, 8:39 AM

Post #4 of 18 (3431 views)
Re: [zing] Problem printing return value from a subroutine [In reply to] Can't Post

Hi,

this is probably OK, because this is the way data dumper will print it the way you use it. But if you look closely at it, it says that the variable you are dumping contains 3 variables, b, c and a, whicj is what you expect.

You should try to pass Dumper a reference to $qw.


zing
Novice

Oct 4, 2012, 8:49 AM

Post #5 of 18 (3429 views)
Re: [Laurent_R] Problem printing return value from a subroutine [In reply to] Can't Post

Laurent maybe I couldnt explain properly.Let me explain what is wanted.Consider for example component 2. It has two vertices e,d. Now I want to see if any of the rows from "DATA" is a subset of these points.Now since each of the row of "DATA" has 3 vertices/points,therefore clearly for component 2 there isnt any induced line from DATA. Therefore there should be anything to print for the subroutine "induced" for this case.

But for component 1,which has vertices as = c,a,b; the first line of "DATA" which is "b c a" gets induced.

Similarly if component=a,b,c,d ; then first two rows of DATA get induced ,as they are both the subset of the component.
So what i want now is that,I want to save this induced vertices in a variable/array etc. AS i need to do further processing on this induced part.


(This post was edited by zing on Oct 4, 2012, 9:02 AM)


BillKSmith
Veteran

Oct 4, 2012, 9:15 AM

Post #6 of 18 (3420 views)
Re: [zing] Problem printing return value from a subroutine [In reply to] Can't Post

The following changes should help

Code
for ( $d = $p; $d >= 1; $d-- ) { 
print "component $d = @{ $subgraphs[$d-1] }\n";
my @qw = induced( @{ $subgraphs[ $d - 1 ] } );
print Dumper \@qw;
}
print "induced=@qw\n";


Extraneous output seems to be comming from the subroutine induced.
Good Luck,
Bill


zing
Novice

Oct 4, 2012, 11:02 AM

Post #7 of 18 (3418 views)
Re: [BillKSmith] Problem printing return value from a subroutine [In reply to] Can't Post

Still no luck.
here's the output with the chages you suggested.

Code
component 2 = e d 
$VAR1 = [
'b',
'c',
'a'
];
component 1 = c b a
b c a
$VAR1 = [
'b',
'c',
'a'
];
induced=

Also I didnt get the logic behind keeping

Code
print "induced=@qw\n";

out of the loop. The induced content depends on the content of component,so it should be kept inside the loop.For if there are 5 components and 3 of them are capable of inducing then "keeping it outside for loop" logic wont work


BillKSmith
Veteran

Oct 4, 2012, 2:05 PM

Post #8 of 18 (3416 views)
Re: [zing] Problem printing return value from a subroutine [In reply to] Can't Post

I did not claim a complete solution. I moved one print statement out of the loop because your expected output has only one copy of that output. Are you sure that your posted expected output is correct?

It is a good idea to use Data::Dumper as a debug tool. Perhaps you should remove the dumps as soon as you are convinced that they are correct. (They can be put back in to check out changes)
Good Luck,
Bill


Laurent_R
Veteran / Moderator

Oct 4, 2012, 3:38 PM

Post #9 of 18 (3414 views)
Re: [zing] Problem printing return value from a subroutine [In reply to] Can't Post

Hi Zing,

I am traveling this week and don't have acces right now to a Perl environment, so I can't try your code. And it is too long for me to try to follow its logics manually.

But my impression is that you are expecting from Data::Dumper things that are beyond the scope of this module. Actually, I have the feeling that your program gives you what you need, but that you can't recognize it because you expect the same data in a format that is different from what Dumper provides you.


zing
Novice

Oct 4, 2012, 10:38 PM

Post #10 of 18 (3400 views)
Re: [BillKSmith] Problem printing return value from a subroutine [In reply to] Can't Post

Bill , after commenting

Code
#print Dumper @qw;

I got this
---------OUTPUT----------

Code
component 2 = e d 
component 1 = c a b
b c a


Clearly since, "b c a" is a subset of component1(c a b) therefore it gets printed. But Bill I just want to save this "b c a" in a suitable array/variable etc. As I need it for further processing.That's why I want to save this output,rather than just getting it printed.

Also there would be a case for example consider a component 3,which has these points= "a c d e". Then row 2nd and 3rd of "DATA" are a subset of these points.So for component3 I'm expecting this output

Code
component 3 = a c d e 
induced= a c d
d e b

I want to save these induced values in a suitable data structure as I need to further process them.


(This post was edited by zing on Oct 4, 2012, 11:20 PM)


Laurent_R
Veteran / Moderator

Oct 5, 2012, 3:21 AM

Post #11 of 18 (3369 views)
Re: [zing] Problem printing return value from a subroutine [In reply to] Can't Post


In Reply To
Clearly since, "b c a" is a subset of component1(c a b) therefore it gets printed. But Bill I just want to save this "b c a" in a suitable array/variable etc. As I need it for further processing.That's why I want to save this output,rather than just getting it printed.


But you have "b c a" stored in the @qw array (BTW, you should give it a more sensible name, but it is a different matter), what else do you need?


zing
Novice

Oct 5, 2012, 5:00 AM

Post #12 of 18 (3353 views)
Re: [Laurent_R] Problem printing return value from a subroutine [In reply to] Can't Post

Laurent I get that,but if you see Post #7, u'll see that that @qw gets printed even when component 2 =" e d" (But it shouldn't get printed ).
Shouldnt it be something like this then ( if I keep this line "print Dumper @qw;" uncommented)

Code
component 2 = e d  
component 1 = c b a
b c a
$VAR1 = [
'b',
'c',
'a'
];

I hope Im clear.


(This post was edited by zing on Oct 5, 2012, 5:02 AM)


zing
Novice

Oct 5, 2012, 5:26 AM

Post #13 of 18 (3348 views)
Re: [zing] Problem printing return value from a subroutine [In reply to] Can't Post

The code fails on this data

Code
---------DATA-------------- 
b c a
a c d
d e b
e f g
g d f
h i g


And the output is

Code
component 2 = e d g f 
component 1 = c a b
b c a

Which is wrong, because it should have been this

Code
component 2 = e d g f 
e f g
g d f
component 1 = c a b
b c a

Because with the vertices in component 2, we can have 4th & 5th row of DATA.
Please help on this


(This post was edited by zing on Oct 5, 2012, 5:28 AM)


zing
Novice

Oct 5, 2012, 1:29 PM

Post #14 of 18 (3326 views)
Re: [Laurent_R] Problem printing return value from a subroutine [In reply to] Can't Post

Please let me know if you need any other input from me.
Help me solve this problem


BillKSmith
Veteran

Oct 5, 2012, 4:02 PM

Post #15 of 18 (3323 views)
Re: [zing] Problem printing return value from a subroutine [In reply to] Can't Post

I am confused. Allow me to start over. I am unable to exactly duplicate your original problem with the following proceedure.
  • Paste your code into editor.

  • Restore newlines with perltidy

  • Change input operator to <DATA>

  • Add data to end of file[\li]
  • Install Graph module on my system[\li]
  • Remove reference to Graph::Subgraph -- not used


  • I tried Laurent's suggestion from post 2. The resultls diverge even more from those in post 3.

    Later posts bring up more issues. Let's settle the first one first. Please attach (this avoids the newline problem) a complete working copy of your script that we can both run. I have attached my script as a sample of what I need.
    Good Luck,
    Bill
    Attachments: zing_2.pl (2.16 KB)


    zing
    Novice

    Oct 6, 2012, 1:27 AM

    Post #16 of 18 (3314 views)
    Re: [BillKSmith] Problem printing return value from a subroutine [In reply to] Can't Post

    thanks for cleaning it up BillK. Let me reformulate the exact part concerned.
    Guys the problem is like to check if an array is contained inside another array.

    Code
    perl -le '@x = qw(a b c d e f); 
    @y = qw(a d f);
    $n = grep { $e = $_; not grep { $e =~ /\Q$_/i } @x } @y;
    print "Count of elements in (@y) that are NOT present in (@x) = $n"
    '
    Count of elements in (a d f) that are NOT present in (a b c d e f) = 0


    So if the count is 0, you know that @y is a subset of @x and hence you want to return it from the "induced" subroutine.
    I hope this would even clear out the mess. Now can this be incorporated as a subroutine.
    The input will be DATA taken in as an array. The second array will hold the connected components.

    Code
    ____DATA_____ 
    b c a
    a c d
    d e b
    e f g
    g d f
    h i g


    @Components

    Code
    a b c 
    a b d c
    e f d g

    So I want to see if any row of @DATA is contained inside @Components.
    So the output expected is

    Code
    component 1 = a b c 
    induced = b c a
    component = a b d c
    induced = b c a
    a c d
    component 3 = e f d g
    induced = e f g
    g d f



    (This post was edited by zing on Oct 6, 2012, 1:28 AM)


    BillKSmith
    Veteran

    Oct 8, 2012, 6:32 AM

    Post #17 of 18 (3254 views)
    Re: [zing] Problem printing return value from a subroutine [In reply to] Can't Post

    I understand that you want subroutine induced to accept one component and return the first line of DATA which is a subset of it. Return an empty array if there is none. This subroutine is called for each component. I have not yet tried to integrate this with your graph code.


    Code
    use strict; 
    use warnings;
    my @components = (
    [qw(a b c)],
    [qw(a b d c)],
    [qw(e f d g)],
    );
    my @S;
    while (<DATA>) {
    push @S, [split];
    }

    foreach my $component (@components) {
    print "component @$component\n";
    my @qw = induced ( $component, \@S );
    print "Induced = @qw\n" if @qw;
    }

    sub induced {
    my ($x, $yy) = @_;
    foreach my $y (@$yy) {
    my %seen;
    @seen{@$x} = ();
    my $n = grep {!exists $seen{$_}} @$y;
    # print "Count of elements in (@$y) that are NOT present in (@$x) = $n\n";
    return @$y if !$n;
    }
    return ();
    }
    __DATA__
    b c a
    a c d
    d e b
    e f g
    g d f
    h i g

    Good Luck,
    Bill


    zing
    Novice

    Oct 8, 2012, 10:14 AM

    Post #18 of 18 (3222 views)
    Re: [BillKSmith] Problem printing return value from a subroutine [In reply to] Can't Post

    Thanks everybody and BillK. Im marking this as solved.
    BTW I have another problem(post 72049) which uses the code from this thread.
    Please see to it if you can help me on that.

     
     


    Search for (options) Powered by Gossamer Forum v.1.2.0

    Web Applications & Managed Hosting Powered by Gossamer Threads
    Visit our Mailing List Archives