BioPerl

 view release on metacpan or  search on metacpan

Bio/PhyloNetwork/FactoryX.pm  view on Meta::CPAN

$numhybrids E<lt> $numleaves.

If the parameter -recurse=E<gt>1 is given, then all networks with number of hybrid
nodes less or equal to $numhybrids will be given; otherwise only those with
exactly $numhybrids hybrid nodes.

=cut

sub new {
  my ($pkg,@args)=@_;
  my $self=$pkg->SUPER::new(@args);

  my ($leavesR,$numleaves,$numhybrids)=
    $self->_rearrange([qw(LEAVES
			  NUMLEAVES
			  NUMHYBRIDS)],@args);
  my @leaves;
  if ((! defined $leavesR) && (defined $numleaves)) {
    @leaves=map {"l$_"} (1..$numleaves);
    $leavesR=\@leaves;
  }
  if (! defined $leavesR) {
    $self->throw("No leaves set neither numleaves given");
  }
  @leaves=@$leavesR;
  $self->{leaves}=$leavesR;
  $numleaves=@leaves;
  $self->{numleaves}=$numleaves;

  if (! defined $numhybrids) {
    $numhybrids=$numleaves-1;
  }
  $self->{numhybrids}=$numhybrids;
  if ($numhybrids ==0) {
    return Bio::PhyloNetwork::TreeFactoryX->new(-leaves=>\@leaves);
  }
  my $parent;
  if ($numhybrids > 1) {
    $parent=new($pkg,'-leaves'=>\@leaves,
		'-numhybrids'=>($numhybrids-1)
	       );
    my @subfactories=@{$parent->{subfactories}};
    push @subfactories,$parent;
#    print "$numhybrids : ".(scalar @subfactories);
#    print "\n";
    $self->{subfactories}=\@subfactories;
#    print "$numhybrids: ".(scalar @subfactories)."\n";
  }
  else {
    $parent=Bio::PhyloNetwork::TreeFactoryX->new(-leaves=>\@leaves);
    $self->{subfactories}=[$parent];
  }
  $self->{parent}=$parent;
  $self->update();
  $self->{found}=[];
  $self->{thrown}=0;
  $self->{hybnow}=0;
  bless($self,$pkg);
}

sub update {
  my ($self)=@_;

  if (defined $self->{oldnet}) {
    my @candidates=$self->{oldnet}->edges();
    $self->{candidates}=\@candidates;
    $self->{numcandidates}=(scalar @candidates);
    $self->{index1}=0;
    $self->{index2}=0;
  } else {
    $self->{candidates}=[];
    $self->{numcandidates}=0;
    $self->{index1}=0;
    $self->{index2}=0;
  }
}

sub next_network_repeated {
  my ($self)=@_;

  return 0 if ($self->{thrown} >= (scalar @{$self->{found}}));
  $self->{thrown}=$self->{thrown}+1;
  return $self->{found}->[$self->{thrown}-1];
}

sub next_network_new {
  my ($self)=@_;
 START:
#  print $self->{index1}.",".$self->{index2}.":".$self->{numcandidates}."\n";
  if ($self->{index1} >= $self->{numcandidates}) {
    $self->{index2}++;
    $self->{index1}=0;
  }
#  print $self->{index1}.",".$self->{index2}.":".$self->{numcandidates}."\n";
  if ($self->{index2} >= $self->{numcandidates}) {
    my $oldnet=$self->{parent}->next_network_repeated();
    if (! $oldnet) {
#      print "notoldnet\n";
      return 0;
    }
    $self->{oldnet}=$oldnet;
    $self->update();
  }
  my $u1=$self->{candidates}->[$self->{index1}]->[0];
  my $v1=$self->{candidates}->[$self->{index1}]->[1];
  my $u2=$self->{candidates}->[$self->{index2}]->[0];
  my $v2=$self->{candidates}->[$self->{index2}]->[1];
  my $lbl=$self->{numhybrids};
  if ($self->{oldnet}->is_attackable($u1,$v1,$u2,$v2)) {
    my $net=Bio::PhyloNetwork->new(-graph=>$self->{oldnet}->graph);
    $net->do_attack($u1,$v1,$u2,$v2,$lbl);
    $self->{index1}++;
    my @found=@{$self->{found}};
    foreach my $netant (@found) {
      if ($net->is_mu_isomorphic($netant) ) {
	goto START;
      }
    }
    push @found,$net;
    $self->{found}=\@found;
    return $net;



( run in 0.953 second using v1.01-cache-2.11-cpan-39bf76dae61 )