// File: Chrom3D[P]Chrom3D/src/Chrom3D.cpp
// Function: main
int main(int argc, char** argv) {
  Args args = parseArguments(argc,argv);
  string fileName = args.fileName;
  
  Model model(args.modelName, args.seed);
  model.setNucleusRadius(args.radius);

  if(args.occupancy > 0) {
    model.readGtrack(fileName, true, args.occupancy);
  }
  else {
    model.readGtrack(fileName, false);
  }

  //if(args.centerConstraint) {
  //  model.addCenterConstraints();
  //}
  
  if(args.nucleusConstraint) {
    model.addNucleusConstraints();
  }

  
  if( find(args.excludeMoves.begin(), args.excludeMoves.end(), "crankshaft") ==  args.excludeMoves.end()) {
    model.addRandomizer(new CrankShaftRandomizer());
  }
  if( find(args.excludeMoves.begin(), args.excludeMoves.end(), "microcrank") ==  args.excludeMoves.end()) {
    model.addRandomizer(new MicroCrankShaftRandomizer());
  }
  if( find(args.excludeMoves.begin(), args.excludeMoves.end(), "armwiggle") ==  args.excludeMoves.end()) {
    model.addRandomizer(new ArmWiggleRandomizer());
  }
  if( find(args.excludeMoves.begin(), args.excludeMoves.end(), "armrotate") ==  args.excludeMoves.end()) {
    model.addRandomizer(new ArmRotateRandomizer());
  }
  if( find(args.excludeMoves.begin(), args.excludeMoves.end(), "translate") ==  args.excludeMoves.end()) {
    model.addRandomizer(new TranslateRandomizer(1.0));
  }
  if( find(args.excludeMoves.begin(), args.excludeMoves.end(), "rotate") ==  args.excludeMoves.end()) {
    model.addRandomizer(new RotationRandomizer());
  }
  
  //model.buildHashMap();

  MCMC mcmc(model);
  bool success;
  uint Niter=args.nIter;
  double maxTemp = args.maxtemp;
  double coolRate = args.coolrate; // Number between 0 and 1, giving the rate of cooling at each step
  double temp=maxTemp;

  uint verbosity = (args.verbose == 0) ? args.nIter+1 : args.verbose;

   
  if(args.verbose != 0) {
    //cerr << "0 " << model.getLossScore(INTERACTION_INTRA) << " " << model.getLossScore(INTERACTION_INTER) << " " << model.getLossScore(PERIPHERY) << " " << model.getLossScore(CENTER) << " " << model.getLossScore(BOUNDARY) << " " << model.getLossScore(NUCLEUS) << " " << model.getLossScore(INTERACTION_DIST) << " " << model.getLossScore() << endl;
cerr << "0 " << model.getLossScore() << endl;
  }
  
  
  for(uint i=1; i!=args.nIter+1; i++) {
    temp *= (1-coolRate);
    success = mcmc.doMetropolisHastingsStep(temp); //simulated annealing when T < 1. When T = 1 that is Metropolis Hastings
    assert(success);
    if (i % verbosity == 0) {
      if(args.printStructures) {
	model.writeCMM(args.modelName + "_iter_" + to_string(i) + ".cmm");
      }
      //cerr << i << " " << model.getLossScore(INTERACTION_INTRA) << " " << model.getLossScore(INTERACTION_INTER) << " " << model.getLossScore(PERIPHERY) << " " << model.getLossScore(CENTER) << " " << model.getLossScore(INTERACTION_DIST) << " " << model.getLossScore() << endl;
      cerr << i << " " << model.getLossScore() << endl;
    }
  }

  if(args.outFile != "/dev/null") {
    model.writeCMM(args.outFile);
  }
  else {
    cout << model.getCMM();
  }

  /*
  if(args.pdbStructures)
  {
    boost::filesystem::path dir(args.modelName);
    boost::filesystem::create_directory(dir);
    model.writePDB(args.modelName);
  }
  */

  exit(EXIT_SUCCESS);
}

// Assembly:
subq $0xf28, %rsp            # imm = 0xF28
movl $0x0, 0xf24(%rsp)
movl %edi, 0xf20(%rsp)
movq %rsi, 0xf18(%rsp)
movl 0xf20(%rsp), %esi
movq 0xf18(%rsp), %rdx
leaq 0xe60(%rsp), %rdi
movq %rdi, 0xe8(%rsp)
callq 0x38c40
movq 0xe8(%rsp), %rsi
leaq 0xe40(%rsp), %rdi
callq 0x8230
jmp 0x3b8dc
leaq 0xed8(%rsp), %rsi
leaq 0x2e0(%rsp), %rdi
callq 0x8230
jmp 0x3b8f3
movl 0xea0(%rsp), %edx
leaq 0x300(%rsp), %rdi
leaq 0x2e0(%rsp), %rsi
callq 0x1b490
jmp 0x3b911
leaq 0x2e0(%rsp), %rdi
callq 0x8998
movsd 0xea8(%rsp), %xmm0
leaq 0x300(%rsp), %rdi
callq 0x1cd80
jmp 0x3b936
movsd 0xec8(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x3ba31
leaq 0x2c0(%rsp), %rdi
leaq 0xe40(%rsp), %rsi
callq 0x8230
jmp 0x3b963
movsd 0xec8(%rsp), %xmm0
leaq 0x300(%rsp), %rdi
leaq 0x2c0(%rsp), %rsi
movl $0x1, %edx
callq 0x20930
jmp 0x3b988
leaq 0x2c0(%rsp), %rdi
callq 0x8998
jmp 0x3ba9e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe38(%rsp)
movl %eax, 0xe34(%rsp)
jmp 0x3c4d9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe38(%rsp)
movl %eax, 0xe34(%rsp)
jmp 0x3c4cc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe38(%rsp)
movl %eax, 0xe34(%rsp)
leaq 0x2e0(%rsp), %rdi
callq 0x8998
jmp 0x3c4cc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe38(%rsp)
movl %eax, 0xe34(%rsp)
jmp 0x3c4bf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe38(%rsp)
movl %eax, 0xe34(%rsp)
leaq 0x2c0(%rsp), %rdi
callq 0x8998
jmp 0x3c4bf
leaq 0x2a0(%rsp), %rdi
leaq 0xe40(%rsp), %rsi
callq 0x8230
jmp 0x3ba48
leaq 0x300(%rsp), %rdi
leaq 0x2a0(%rsp), %rsi
xorl %edx, %edx
movsd 0x15a46(%rip), %xmm0    # 0x514a8
callq 0x20930
jmp 0x3ba69
leaq 0x2a0(%rsp), %rdi
callq 0x8998
jmp 0x3ba9e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe38(%rsp)
movl %eax, 0xe34(%rsp)
leaq 0x2a0(%rsp), %rdi
callq 0x8998
jmp 0x3c4bf
testb $0x1, 0xf11(%rsp)
je 0x3bac1
leaq 0x300(%rsp), %rdi
movsd 0x13550(%rip), %xmm0    # 0x4f008
callq 0x26da0
jmp 0x3babf
jmp 0x3bac1
leaq 0xef8(%rsp), %rdi
movq %rdi, 0xd8(%rsp)
callq 0x11f10
movq 0xd8(%rsp), %rdi
movq %rax, 0x290(%rsp)
callq 0x11d80
movq %rax, 0x288(%rsp)
movq 0x290(%rsp), %rdi
movq 0x288(%rsp), %rsi
leaq 0x15ed4(%rip), %rdx     # 0x519de
callq 0x3f850
movq %rax, 0xe0(%rsp)
jmp 0x3bb19
movq 0xe0(%rsp), %rax
movq %rax, 0x298(%rsp)
leaq 0xe60(%rsp), %rdi
addq $0x98, %rdi
callq 0x11d80
movq %rax, 0x280(%rsp)
leaq 0x298(%rsp), %rdi
leaq 0x280(%rsp), %rsi
callq 0x3f810
testb $0x1, %al
jne 0x3bb60
jmp 0x3bba9
movl $0x8, %edi
callq 0x8490
movq %rax, 0xd0(%rsp)
jmp 0x3bb74
movq 0xd0(%rsp), %rdi
movq $0x0, (%rdi)
callq 0x3f8b0
movq 0xd0(%rsp), %rsi
leaq 0x300(%rsp), %rdi
movsd 0x13468(%rip), %xmm0    # 0x4f008
callq 0x1df10
jmp 0x3bba7
jmp 0x3bba9
leaq 0xef8(%rsp), %rdi
movq %rdi, 0xc0(%rsp)
callq 0x11f10
movq 0xc0(%rsp), %rdi
movq %rax, 0x270(%rsp)
callq 0x11d80
movq %rax, 0x268(%rsp)
movq 0x270(%rsp), %rdi
movq 0x268(%rsp), %rsi
leaq 0x15df7(%rip), %rdx     # 0x519e9
callq 0x3f850
movq %rax, 0xc8(%rsp)
jmp 0x3bc01
movq 0xc8(%rsp), %rax
movq %rax, 0x278(%rsp)
leaq 0xe60(%rsp), %rdi
addq $0x98, %rdi
callq 0x11d80
movq %rax, 0x260(%rsp)
leaq 0x278(%rsp), %rdi
leaq 0x260(%rsp), %rsi
callq 0x3f810
testb $0x1, %al
jne 0x3bc48
jmp 0x3bc91
movl $0x8, %edi
callq 0x8490
movq %rax, 0xb8(%rsp)
jmp 0x3bc5c
movq 0xb8(%rsp), %rdi
movq $0x0, (%rdi)
callq 0x3f8e0
movq 0xb8(%rsp), %rsi
leaq 0x300(%rsp), %rdi
movsd 0x13380(%rip), %xmm0    # 0x4f008
callq 0x1df10
jmp 0x3bc8f
jmp 0x3bc91
leaq 0xef8(%rsp), %rdi
movq %rdi, 0xa8(%rsp)
callq 0x11f10
movq 0xa8(%rsp), %rdi
movq %rax, 0x250(%rsp)
callq 0x11d80
movq %rax, 0x248(%rsp)
movq 0x250(%rsp), %rdi
movq 0x248(%rsp), %rsi
leaq 0x15d1a(%rip), %rdx     # 0x519f4
callq 0x28eb0
movq %rax, 0xb0(%rsp)
jmp 0x3bce9
movq 0xb0(%rsp), %rax
movq %rax, 0x258(%rsp)
leaq 0xe60(%rsp), %rdi
addq $0x98, %rdi
callq 0x11d80
movq %rax, 0x240(%rsp)
leaq 0x258(%rsp), %rdi
leaq 0x240(%rsp), %rsi
callq 0x3f810
testb $0x1, %al
jne 0x3bd30
jmp 0x3bd79
movl $0x8, %edi
callq 0x8490
movq %rax, 0xa0(%rsp)
jmp 0x3bd44
movq 0xa0(%rsp), %rdi
movq $0x0, (%rdi)
callq 0x3f910
movq 0xa0(%rsp), %rsi
leaq 0x300(%rsp), %rdi
movsd 0x13298(%rip), %xmm0    # 0x4f008
callq 0x1df10
jmp 0x3bd77
jmp 0x3bd79
leaq 0xef8(%rsp), %rdi
movq %rdi, 0x90(%rsp)
callq 0x11f10
movq 0x90(%rsp), %rdi
movq %rax, 0x230(%rsp)
callq 0x11d80
movq %rax, 0x228(%rsp)
movq 0x230(%rsp), %rdi
movq 0x228(%rsp), %rsi
leaq 0x15c3c(%rip), %rdx     # 0x519fe
callq 0x28eb0
movq %rax, 0x98(%rsp)
jmp 0x3bdd1
movq 0x98(%rsp), %rax
movq %rax, 0x238(%rsp)
leaq 0xe60(%rsp), %rdi
addq $0x98, %rdi
callq 0x11d80
movq %rax, 0x220(%rsp)
leaq 0x238(%rsp), %rdi
leaq 0x220(%rsp), %rsi
callq 0x3f810
testb $0x1, %al
jne 0x3be18
jmp 0x3be61
movl $0x8, %edi
callq 0x8490
movq %rax, 0x88(%rsp)
jmp 0x3be2c
movq 0x88(%rsp), %rdi
movq $0x0, (%rdi)
callq 0x3f940
movq 0x88(%rsp), %rsi
leaq 0x300(%rsp), %rdi
movsd 0x131b0(%rip), %xmm0    # 0x4f008
callq 0x1df10
jmp 0x3be5f
jmp 0x3be61
leaq 0xef8(%rsp), %rdi
movq %rdi, 0x78(%rsp)
callq 0x11f10
movq 0x78(%rsp), %rdi
movq %rax, 0x210(%rsp)
callq 0x11d80
movq %rax, 0x208(%rsp)
movq 0x210(%rsp), %rdi
movq 0x208(%rsp), %rsi
leaq 0x15b64(%rip), %rdx     # 0x51a08
callq 0x28eb0
movq %rax, 0x80(%rsp)
jmp 0x3beb3
movq 0x80(%rsp), %rax
movq %rax, 0x218(%rsp)
leaq 0xe60(%rsp), %rdi
addq $0x98, %rdi
callq 0x11d80
movq %rax, 0x200(%rsp)
leaq 0x218(%rsp), %rdi
leaq 0x200(%rsp), %rsi
callq 0x3f810
testb $0x1, %al
jne 0x3befa
jmp 0x3bf65
movl $0x10, %edi
callq 0x8490
movq %rax, 0x70(%rsp)
jmp 0x3bf0b
movq 0x70(%rsp), %rdi
movsd 0x130f0(%rip), %xmm0    # 0x4f008
callq 0x19700
jmp 0x3bf1f
movq 0x70(%rsp), %rsi
leaq 0x300(%rsp), %rdi
movsd 0x130d4(%rip), %xmm0    # 0x4f008
callq 0x1df10
jmp 0x3bf3b
jmp 0x3bf65
movq 0x70(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe38(%rsp)
movl %eax, 0xe34(%rsp)
movl $0x10, %esi
callq 0x84a0
jmp 0x3c4bf
leaq 0xef8(%rsp), %rdi
movq %rdi, 0x60(%rsp)
callq 0x11f10
movq 0x60(%rsp), %rdi
movq %rax, 0x1f0(%rsp)
callq 0x11d80
movq %rax, 0x1e8(%rsp)
movq 0x1f0(%rsp), %rdi
movq 0x1e8(%rsp), %rsi
leaq 0x15a59(%rip), %rdx     # 0x51a01
callq 0x28f70
movq %rax, 0x68(%rsp)
jmp 0x3bfb4
movq 0x68(%rsp), %rax
movq %rax, 0x1f8(%rsp)
leaq 0xe60(%rsp), %rdi
addq $0x98, %rdi
callq 0x11d80
movq %rax, 0x1e0(%rsp)
leaq 0x1f8(%rsp), %rdi
leaq 0x1e0(%rsp), %rsi
callq 0x3f810
testb $0x1, %al
jne 0x3bff8
jmp 0x3c038
movl $0x8, %edi
callq 0x8490
movq %rax, 0x58(%rsp)
jmp 0x3c009
movq 0x58(%rsp), %rdi
movq $0x0, (%rdi)
callq 0x3f970
movq 0x58(%rsp), %rsi
leaq 0x300(%rsp), %rdi
movsd 0x12fd9(%rip), %xmm0    # 0x4f008
callq 0x1df10
jmp 0x3c036
jmp 0x3c038
leaq 0x1d8(%rsp), %rdi
leaq 0x300(%rsp), %rsi
callq 0x38970
jmp 0x3c04f
movl 0xeb0(%rsp), %eax
movl %eax, 0x1d0(%rsp)
movsd 0xeb8(%rsp), %xmm0
movsd %xmm0, 0x1c8(%rsp)
movsd 0xec0(%rsp), %xmm0
movsd %xmm0, 0x1c0(%rsp)
movsd 0x1c8(%rsp), %xmm0
movsd %xmm0, 0x1b8(%rsp)
cmpl $0x0, 0xed0(%rsp)
jne 0x3c0ad
movl 0xeb0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x54(%rsp)
jmp 0x3c0b8
movl 0xed0(%rsp), %eax
movl %eax, 0x54(%rsp)
movl 0x54(%rsp), %eax
movl %eax, 0x1b4(%rsp)
cmpl $0x0, 0xed0(%rsp)
je 0x3c128
movq 0x2df0c(%rip), %rdi     # 0x69fe0
leaq 0x15b3a(%rip), %rsi     # 0x51c15
callq 0x8480
movq %rax, 0x48(%rsp)
jmp 0x3c0e7
leaq 0x300(%rsp), %rdi
callq 0x1d3d0
movsd %xmm0, 0x40(%rsp)
jmp 0x3c0fc
movsd 0x40(%rsp), %xmm0
movq 0x48(%rsp), %rdi
callq 0x8910
movq %rax, 0x38(%rsp)
jmp 0x3c113
movq 0x38(%rsp), %rdi
movq 0x2de11(%rip), %rsi     # 0x69f30
callq 0x84e0
jmp 0x3c126
jmp 0x3c128
movl $0x1, 0x1b0(%rsp)
movl 0x1b0(%rsp), %eax
movl 0xeb0(%rsp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
je 0x3c3d2
movsd 0x1c0(%rsp), %xmm0
movsd 0x12eab(%rip), %xmm1    # 0x4f008
subsd %xmm0, %xmm1
movsd 0x1b8(%rsp), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, 0x1b8(%rsp)
movsd 0x1b8(%rsp), %xmm0
leaq 0x1d8(%rsp), %rdi
movl $0x2710, %esi           # imm = 0x2710
callq 0x38990
movb %al, 0x37(%rsp)
jmp 0x3c198
movb 0x37(%rsp), %al
andb $0x1, %al
movb %al, 0x1d7(%rsp)
testb $0x1, 0x1d7(%rsp)
je 0x3c1b1
jmp 0x3c1d0
leaq 0x15a60(%rip), %rdi     # 0x51c18
leaq 0x15a61(%rip), %rsi     # 0x51c20
movl $0xd4, %edx
leaq 0x15a65(%rip), %rcx     # 0x51c30
callq 0x8340
movl 0x1b0(%rsp), %eax
xorl %edx, %edx
divl 0x1b4(%rsp)
cmpl $0x0, %edx
jne 0x3c3ba
testb $0x1, 0xf12(%rsp)
je 0x3c347
leaq 0xed8(%rsp), %rsi
leaq 0x15a41(%rip), %rdx     # 0x51c47
leaq 0x150(%rsp), %rdi
callq 0x28d20
jmp 0x3c215
movl 0x1b0(%rsp), %esi
leaq 0x130(%rsp), %rdi
callq 0x3f9a0
jmp 0x3c22b
leaq 0x170(%rsp), %rdi
leaq 0x150(%rsp), %rsi
leaq 0x130(%rsp), %rdx
callq 0x28c30
jmp 0x3c24a
leaq 0x159fd(%rip), %rdx     # 0x51c4e
leaq 0x190(%rsp), %rdi
leaq 0x170(%rsp), %rsi
callq 0x28be0
jmp 0x3c268
leaq 0x300(%rsp), %rdi
leaq 0x190(%rsp), %rsi
callq 0x20850
jmp 0x3c27f
leaq 0x190(%rsp), %rdi
callq 0x8998
leaq 0x170(%rsp), %rdi
callq 0x8998
leaq 0x130(%rsp), %rdi
callq 0x8998
leaq 0x150(%rsp), %rdi
callq 0x8998
jmp 0x3c347
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe38(%rsp)
movl %eax, 0xe34(%rsp)
jmp 0x3c335
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe38(%rsp)
movl %eax, 0xe34(%rsp)
jmp 0x3c328
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe38(%rsp)
movl %eax, 0xe34(%rsp)
jmp 0x3c31b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe38(%rsp)
movl %eax, 0xe34(%rsp)
leaq 0x190(%rsp), %rdi
callq 0x8998
leaq 0x170(%rsp), %rdi
callq 0x8998
leaq 0x130(%rsp), %rdi
callq 0x8998
leaq 0x150(%rsp), %rdi
callq 0x8998
jmp 0x3c4bf
movl 0x1b0(%rsp), %esi
movq 0x2dc8b(%rip), %rdi     # 0x69fe0
callq 0x8630
movq %rax, 0x28(%rsp)
jmp 0x3c361
movq 0x28(%rsp), %rdi
leaq 0x15d05(%rip), %rsi     # 0x52072
callq 0x8480
movq %rax, 0x20(%rsp)
jmp 0x3c379
leaq 0x300(%rsp), %rdi
callq 0x1d3d0
movsd %xmm0, 0x18(%rsp)
jmp 0x3c38e
movsd 0x18(%rsp), %xmm0
movq 0x20(%rsp), %rdi
callq 0x8910
movq %rax, 0x10(%rsp)
jmp 0x3c3a5
movq 0x10(%rsp), %rdi
movq 0x2db7f(%rip), %rsi     # 0x69f30
callq 0x84e0
jmp 0x3c3b8
jmp 0x3c3ba
jmp 0x3c3bc
movl 0x1b0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1b0(%rsp)
jmp 0x3c133
leaq 0xe80(%rsp), %rdi
leaq 0x1525e(%rip), %rsi     # 0x5163f
callq 0x29480
movb %al, 0xf(%rsp)
jmp 0x3c3ec
movb 0xf(%rsp), %al
testb $0x1, %al
jne 0x3c3f6
jmp 0x3c459
leaq 0xe80(%rsp), %rsi
leaq 0x110(%rsp), %rdi
callq 0x8230
jmp 0x3c40d
leaq 0x300(%rsp), %rdi
leaq 0x110(%rsp), %rsi
callq 0x20850
jmp 0x3c424
leaq 0x110(%rsp), %rdi
callq 0x8998
jmp 0x3c4b8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe38(%rsp)
movl %eax, 0xe34(%rsp)
leaq 0x110(%rsp), %rdi
callq 0x8998
jmp 0x3c4bf
leaq 0xf0(%rsp), %rdi
leaq 0x300(%rsp), %rsi
callq 0x1fde0
jmp 0x3c470
movq 0x2db21(%rip), %rdi     # 0x69f98
leaq 0xf0(%rsp), %rsi
callq 0x8450
jmp 0x3c486
leaq 0xf0(%rsp), %rdi
callq 0x8998
jmp 0x3c4b8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe38(%rsp)
movl %eax, 0xe34(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x8998
jmp 0x3c4bf
xorl %edi, %edi
callq 0x85a0
leaq 0x300(%rsp), %rdi
callq 0x3faa0
leaq 0xe40(%rsp), %rdi
callq 0x8998
leaq 0xe60(%rsp), %rdi
callq 0x3f7c0
movq 0xe38(%rsp), %rdi
callq 0x8870
nopw %cs:(%rax,%rax)
nopl (%rax)