#!/usr/bin/perl -w
use strict;

my %network;

#===========================
# initial the network
$network{1}{2} = 1;
$network{2}{1} = 1;
#$network{1}{3} = 1;
#$network{3}{1} = 1;
#$network{3}{2} = 1;
#$network{2}{3} = 1;
#$network{4}{1} = 1;
#$network{1}{4} = 1;
#$network{2}{4} = 1;
#$network{4}{2} = 1;
#$network{4}{3} = 1;
#$network{3}{4} = 1;
my $lossprb = 0.1;
my $gainprb = 0.005;
my $totalnode = 2;
my $oldnode; my $newnode;
my @allpartners;

#====================================
# network growth start
my $times = 300;
foreach my $sim (1 ... $times)
{
    &Duplication;
    &InteractionLoss;
#    &AsymLoss;
#    &InteractionGain;
}
&PrintNetwork;


#========================================
# functions
sub Duplication
{
    $oldnode = int(rand($totalnode)) + 1;
    # total node + 1
    $totalnode = $totalnode + 1;
    # duplicate the chosen node's neighbers
    $newnode = $totalnode;
    
    foreach my $partner (keys %{ $network{$oldnode} })
    {
        if($network{$oldnode}{$partner} == 1)
        {
            $network{$newnode}{$partner} = 1;
            $network{$partner}{$newnode} = 1;
            push(@allpartners, $partner);
        }
    }
}

sub InteractionLoss
{
    # begin loss interactions
    foreach my $partner (@allpartners)
    {
        if(rand(1) < $lossprb)
        {
            if(rand(1) > 0.5)
            {
                # loss the interaction of newnode
                $network{$newnode}{$partner} = 0;
                $network{$partner}{$newnode} = 0;
            }
            else
            {
                # loss the interaction of oldnode
                $network{$oldnode}{$partner} = 0;
                $network{$partner}{$oldnode} = 0;
            }
        }
    }
}

sub AsymLoss
{
    # begin loss interactions
    foreach my $partner (@allpartners)
    {
        if(rand(1) < $lossprb)
        {
            # loss the interaction of newnode
            $network{$newnode}{$partner} = 0;
            $network{$partner}{$newnode} = 0;
        }
    }
}

sub InteractionGain
{
    #begin gain interactions
    foreach my $node (keys %network)
    {
        if( ((!defined($network{$node}{$newnode})) ||  ($network{$node}{$newnode} != 1))
        &&  ((defined($network{$node}{$oldnode}))  &&  ($network{$node}{$oldnode} == 1)))
        {
            if(rand(1) < $gainprb)
            {
                $network{$newnode}{$node} = 1;
                $network{$node}{$newnode} = 1;
            }
        }
        elsif( ((!defined($network{$node}{$oldnode})) ||  ($network{$node}{$oldnode} != 1))
           &&  ((defined($network{$node}{$newnode}))  &&  ($network{$node}{$newnode} == 1)))
        {
            if(rand(1) < $gainprb)
            {
                $network{$oldnode}{$node} = 1;
                $network{$node}{$oldnode} = 1;
            }
        }
        elsif( ((!defined($network{$node}{$newnode})) || ($network{$node}{$newnode} != 1))
            && ((!defined($network{$node}{$oldnode})) || ($network{$node}{$oldnode} != 1)))
        {
            if(rand(1) > 0.5)
            {
                if(rand(1) < $gainprb)
                {
                    $network{$newnode}{$node} = 1;
                    $network{$node}{$newnode} = 1;
                }
            }
            else
            {
                if(rand(1) < $gainprb)
                {
                    $network{$oldnode}{$node} = 1;
                    $network{$node}{$oldnode} = 1;
                }                
            }
        }
    }
}

sub PrintNetwork
{
    open(OUT, "> $ARGV[0]") or die $!;
    foreach my $node (keys %network)
    {
        foreach my $partner (keys %{ $network{$node} })
        {
            if($network{$node}{$partner} == 1)
            {
                print(OUT "$node\t$partner\n");
                $network{$node}{$partner} = 0;
                $network{$partner}{$node} = 0;
            }
        }
    }
}

