#!/bin/perl

#
# This program searches the KnotDB database for knot types, then checks for the corresponding files.
#

use strict;
use warnings;
use File::Slurp;
use File::Copy;
use File::Path;
use Data::Dumper;
use Cwd;

my $cwd;
$cwd = getcwd;

require "${cwd}/bin/tightknot_common.pl";

my @nonalternating = ( "8_19", "8_20", "8_21", "9_42", "9_43", "9_44", "9_45", "9_46", "9_47", "9_48", "9_49" );
my %is_nonalternating;
for (@nonalternating) { $is_nonalternating{$_} = 1; }

# We start by loading the database.

my $DBFILE = read_file("${cwd}/knotdb/KnotDB.pl");
my %knots;
eval($DBFILE);

my $summand_writhe;
my $filename;            
my $resolution;
my $residual;
my $ropelength; 
my $writhe;
my $writhe_diff;
my $knot_type;

print "THIS VERSION ONLY TABULATES COMPOSITE KNOTS";

print "Comparing writhe of connect sums with writhe of summands...\n";
open(WRITHEREPORT,">${cwd}/data/writhe_of_connect_sums.txt");
open(WRITHESUMMARY,">${cwd}/data/writhe_of_connect_sums_summary.txt");
open(WRITHEMATHEMATICA,">${cwd}/data/writhe_of_connect_sums_alternating.dat");

my @only_alternating;
my @some_nonalternating;
my $ktype;

KTYPE: foreach $ktype (keys %knots) {

  if ($ktype !~ /vect/) { # This is a knot type

    if (defined $knots{$ktype}{summands}) {  # This is a composite knot type

      if ($knots{$ktype}{edges}/$knots{$ktype}{upperbound} > 1 && $knots{$ktype}{residual} < 0.10 && $knots{$ktype}{comp} == 1) { # which passes QC

	foreach ( @{$knots{$ktype}{summands}} ) {
	  
	  if ($is_nonalternating{$_}) { 
	    
	    push(@some_nonalternating,$ktype);
	    print ("$ktype -> nonalternating summand $_\n");
	    next KTYPE;
	    
	}
	  
	}
	
	push(@only_alternating,$ktype);

      }

    }

  }

}

print "We have ".scalar @only_alternating." connect sums with only alternating summands.\n";
print "We have ".scalar @some_nonalternating." connect sums with some nonalternating summands.\n";	

print WRITHEREPORT "ALTERNATING CONNECT SUMS\n\n";
print WRITHESUMMARY "ALTERNATING CONNECT SUMS\n\n";
print "\n\nALTERNATING DATA\n\n";

my @badguys;

foreach ( @only_alternating ) {

  $filename = $knots{$_}{filename};
  $resolution = $knots{$_}{edges}/$knots{$_}{upperbound};
  $residual = $knots{$_}{residual};
  $writhe = $knots{$_}{writhe};
  $ropelength = $knots{$_}{upperbound};
  $knot_type = $_;

  # Now we need to compute the writhes for the summands
  
  $summand_writhe = 0;
  my $summand;
  
  foreach $summand ( @{$knots{$_}{summands}} ) {
    
    if ($summand =~ /m/) {  # the mirror version should have - the writhe of the standard version
      
      $summand_writhe -= $knots{standardknottype($summand)}{writhe};
      
    } else {
      
      $summand_writhe += $knots{standardknottype($summand)}{writhe};
      
    }
    
  }
  
  $writhe_diff = 100*($writhe - $summand_writhe)/$writhe;

  if ($writhe_diff > 4 or $writhe_diff < -4) {

    print "Added $_ to badguys\n";
    push(@badguys,$_);

  }
  
  write(WRITHEREPORT);
  write(WRITHESUMMARY);
  write(WRITHEMATHEMATICA);
  
  print "\t $_: Writhe = $writhe. Summand writhes: $summand_writhe. Diff: $writhe_diff \%. \n";
  
  # Now we write out the data for each of the summands (just to provide a sanity check)
  
  foreach $summand ( @{$knots{$_}{summands}} ) {
    
    my $kt;
    $kt = standardknottype($summand);
    
    $filename = $knots{$kt}{filename};
    $resolution = $knots{$kt}{edges}/$knots{$kt}{upperbound};
    $residual = $knots{$kt}{residual};
    $writhe = $knots{$kt}{writhe};
    $ropelength = $knots{$kt}{upperbound};
    
    write(WRITHEREPORT);
    
  }
  
  print WRITHEREPORT "\n";       
  
}

close WRITHEMATHEMATICA;
open (WRITHEMATHEMATICA,">${cwd}/data/nonalternating_connect_sum_wr.dat");

print WRITHEREPORT "\n\nNONALTERNATING CONNECT SUMS\n\n";
print WRITHESUMMARY "\n\nNONALTERNATING CONNECT SUMS\n\n";
print "\n\nNONALTERNATING DATA\n\n";

foreach ( @some_nonalternating ) {

  $filename = $knots{$_}{filename};
  $resolution = $knots{$_}{edges}/$knots{$_}{upperbound};
  $residual = $knots{$_}{residual};
  $writhe = $knots{$_}{writhe};
  $ropelength = $knots{$_}{upperbound};
  $knot_type = $_;
  
  # Now we need to compute the writhes for the summands
  
  $summand_writhe = 0;
  my $summand;
  
  foreach $summand ( @{$knots{$_}{summands}} ) {
    
    if ($summand =~ /m/) {  # the mirror version should have - the writhe of the standard version
      
      $summand_writhe -= $knots{standardknottype($summand)}{writhe};
      
    } else {
      
      $summand_writhe += $knots{standardknottype($summand)}{writhe};
      
    }
    
  }
  
  $writhe_diff = 100*($writhe - $summand_writhe)/$writhe;

  if ($writhe_diff > 4 or $writhe_diff < -4) {

    print "Added $_ to badguys\n";
    push(@badguys,$_);

  }
  
  write(WRITHEREPORT);
  write(WRITHESUMMARY);
  write(WRITHEMATHEMATICA);
  
  print "\t $_: Writhe = $writhe. Summand writhes: $summand_writhe. Diff: $writhe_diff \%. \n";
  
  # Now we write out the data for each of the summands (just to provide a sanity check)
  
  foreach $summand ( @{$knots{$_}{summands}} ) {
    
    my $kt;
    $kt = standardknottype($summand);
    
    $filename = $knots{$kt}{filename};
    $resolution = $knots{$kt}{edges}/$knots{$kt}{upperbound};
    $residual = $knots{$kt}{residual};
    $writhe = $knots{$kt}{writhe};
    $ropelength = $knots{$kt}{upperbound};
    
    write(WRITHEREPORT);
    
  }
  
  print WRITHEREPORT "\n";       
  
}


close(WRITHEREPORT);
close(WRITHESUMMARY);
close(WRITHEMATHEMATICA);

print "Done. Wrote report to writhe_of_connect_sums.txt, writhe_of_connect_sums_summary.txt,\n";
print "\twrithe_of_connect_sums_alternating.dat, nonalternating_connect_sum_writhe.dat\n";

print "Now computing ropelength for connect sum KNOTS.\n";

open(CSUM,">${cwd}/data/connect_sum_ropelength.dat") || die("Couldn't open ${cwd}/data/connect_sum_ropelength.dat");

my $key;
foreach $key ( %knots ) {

  if ($key !~ /vect/) {

    if (defined($knots{$key}{summands}) and $knots{$key}{comp} == 1 and $knots{$key}{cr} <= 12) {

      #if ($knots{$key}{edges}/$knots{$key}{upperbound} > 8 && $knots{$key}{residual} < 0.01) { # which passes QC

	my $rlsum;
	$rlsum = 0;
	
	foreach ( @{$knots{$key}{summands}} ) {
	  
	  $rlsum += $knots{standardknottype($_)}{upperbound};
	  
	}

	print CSUM "$key $knots{$key}{upperbound} $rlsum ";

	foreach ( @{$knots{$key}{summands}} ) {
	  
	  print CSUM " ".$knots{standardknottype($_)}{upperbound};
	  
	}

	print CSUM "\n";
     	
      #}
      
    }

  }

}

print "Generated ${cwd}/data/connect_sum_ropelength.dat.\n";
    
close(CSUM);

print "Special report on knot types which don't add up.\n";

my @dontadd = qw( 3_1_m_#_9_48 3_1_m_#_9_45 3_1_m_#_9_42 3_1_m_#_8_20 3_1_m_#_9_43 );


print "Constructing table of knots and links with Writhes that don't add up...\n";
open (BW,">${cwd}/data/Writhe_Problems.tex") || die ("Couldn't open Writhe_Problems.tex\n");

print BW "\\begin{tabular}[t]{lrrrc}\n\\toprule\n";
print BW "Knot & \$\\Wr(K_1 \\# K_2)\$ & \$\\Wr(K_1) +\\Wr(K_2)\$ & Difference (\\%) & \\# Start Positions\\\\\n";
print BW "\\midrule\n";

my %diffs;

foreach(@badguys) {

  my $summandA;
  my $summandB;
  my $summandAwrmul;
  my $summandBwrmul;
 
  $summandA = ${$knots{$_}{summands}}[0];
  $summandB = ${$knots{$_}{summands}}[1];
    
  if ($summandA =~ /\_m/) {
	
    $summandAwrmul = -1.0;
    
  } else {
    
    $summandAwrmul = 1.0;
    
  }
  
  $summandA =~ s/\_rm//g;
  $summandA =~ s/\_m//g;
  $summandA =~ s/\_r//g;
  
  if ($summandB =~ /\_m/) {
    
    $summandBwrmul = -1.0;
    
  } else {
    
    $summandBwrmul = 1.0;
    
  }
  
  $summandB =~ s/\_rm//g; 
  $summandB =~ s/\_m//g;
  $summandB =~ s/\_r//g;
  
   $diffs{$_} = abs(100*($knots{$_}{writhe} - $summandAwrmul*$knots{$summandA}{writhe} - $summandBwrmul*$knots{$summandB}{writhe})/($knots{$_}{writhe}));

}

@badguys = sort { abs($diffs{$b}) <=> abs($diffs{$a}) } @badguys;

foreach (@badguys) {

    my $summandA;
    my $summandB;
    my $summandAwrmul;
    my $summandBwrmul;

    print("Composite knot type = $_ \n");
    
    $summandA = ${$knots{$_}{summands}}[0];
    $summandB = ${$knots{$_}{summands}}[1];
    
    if ($summandA =~ /\_m/) {
	
	$summandAwrmul = -1.0;
	
    } else {
	
	$summandAwrmul = 1.0;
	
    }
    
    $summandA =~ s/\_rm//g;
    $summandA =~ s/\_m//g;
    $summandA =~ s/\_r//g;
    
    if ($summandB =~ /\_m/) {
	
	$summandBwrmul = -1.0;
	
    } else {
	
	$summandBwrmul = 1.0;
	
    }
   
    $summandB =~ s/\_rm//g; 
    $summandB =~ s/\_m//g;
    $summandB =~ s/\_r//g;
   
    
    print("Writhe of composite: $knots{$_}{writhe} \n");
    print("Summands (normalized): $summandA $summandB \n");
    print("Writhe of summand ${$knots{$_}{summands}}[0]: ".$summandAwrmul*$knots{$summandA}{writhe}."\n");
    print("Writhe of summand ${$knots{$_}{summands}}[1]: ".$summandBwrmul*$knots{$summandB}{writhe}."\n");
    print("Writhe sum: ",$summandAwrmul*$knots{$summandA}{writhe}+$summandBwrmul*$knots{$summandB}{writhe}."\n");
    print("Number of configs attempted for composite: ".scalar @{$knots{$_}{allfiles}}."\n");
    if (defined $knots{$_}{clusters}) {
      print("Clusters for composite: @{$knots{$_}{clusters}} \n"); 
    }
    print("Number of configs attempted for ${$knots{$_}{summands}}[0]: ".scalar @{$knots{$summandA}{allfiles}}."\n");
    if (defined $knots{$summandA}{clusters}) {
      print("  Clusters: @{$knots{$summandA}{clusters}} \n"); 
    }
    print("Number of configs attempted for ${$knots{$_}{summands}}[1]: ".scalar @{$knots{$summandB}{allfiles}}."\n");
    if (defined $knots{$summandB}{clusters}) {
      print("  Clusters: @{$knots{$summandB}{clusters}} \n"); 
    }

    my $composite = $knots{$_}{tex};
    $composite =~ s/m/\^m/g;
    
    if (scalar @{$knots{$_}{summands}} == 2 and $summandB !~ /^9_4$/ and $summandB !~ /^9_33$/ and abs($knots{$_}{writhe}) > 0.1 and ${$knots{$_}{summands}}[0] !~ /^3_1_m$/ and ${$knots{$_}{summands}}[0] !~ /^5_1_m$/ and ${$knots{$_}{summands}}[0] !~ /^5_2_m$/ and  ${$knots{$_}{summands}}[0] !~ /^7_1_m$/ and ${$knots{$_}{summands}}[1] !~ /^7_7_m$/ and  ${$knots{$_}{summands}}[1] !~ /^8_13_m$/) {
   
      print BW "\$ $composite \$ & ".sprintf("%01.3f",$knots{$_}{writhe})." & ".sprintf("%01.3f",($summandAwrmul*$knots{$summandA}{writhe} + $summandBwrmul*$knots{$summandB}{writhe}))." & ".sprintf("%01.3f",$diffs{$_})." \\% & ".scalar @{$knots{$_}{allfiles}}." (",scalar @{$knots{$summandA}{allfiles}}.",".scalar @{$knots{$summandB}{allfiles}}.") \\\\ \n";

    }

    print("\n ************************************************************************** \n\n");

}

print BW "\\bottomrule\n";
print BW "\\end{tabular}\n";

close BW;

 print "Now copying files to ../rrpaper/\n";

copy("${cwd}/data/Writhe_Problems.tex","${cwd}/../rrpaper/Writhe_Problems.tex") or die("Couldn't copy Writhe_Problems.tex\n");
print "Writhe_Problems.tex -> ../rrpaper/Writhe_Problems.tex\n";

die;

format WRITHEREPORT_TOP =

     Writhe of connect sums

     Filename                            Resolution          Residual            Ropelength        Writhe       Sum of writhe of summands   Difference
     ----------------------------------  ------------------  ------------------  ----------------  -----------  -------------------------   ----------
.

format WRITHEREPORT = 
     @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  @####.############  @####.############  @###.###########  @###.###     @###.###                    @##.## 
     $filename,                          $resolution,        $residual,          $ropelength,      $writhe,     $summand_writhe,            $writhe_diff  
.

format WRITHESUMMARY_TOP =
  
     Writhe of connect sums (summary table) 

     Knot Type           Writhe      Sum of writhes of factors  Difference (%)
     ------------------- ----------- -------------------------  --------------
.

format WRITHESUMMARY =
     @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @####.####  @####.####                 @##.##
     $knot_type,         $writhe,    $summand_writhe,           $writhe_diff
.

format WRITHEMATHEMATICA =
     @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @####.####  @####.####                 @##.##
     $knot_type,         $writhe,    $summand_writhe,           $writhe_diff
.

