// File: /workspace/github_cpp_makefile_star2_O2/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:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xd28, %rsp            # imm = 0xD28
movq %rsi, %rdx
movl %edi, %esi
leaq 0x40(%rsp), %rbx
movq %rbx, %rdi
callq 0x171ec
leaq 0x158(%rsp), %rdi
movq %rbx, %rsi
callq 0x6430
leaq 0xb8(%rsp), %rbx
leaq 0x138(%rsp), %rdi
movq %rbx, %rsi
callq 0x6430
movl 0x80(%rsp), %edx
leaq 0x1f8(%rsp), %rdi
leaq 0x138(%rsp), %rsi
callq 0xcba0
leaq 0x138(%rsp), %rdi
callq 0x66d0
movsd 0x88(%rsp), %xmm0
leaq 0x1f8(%rsp), %rdi
callq 0xd9dc
movsd 0xa8(%rsp), %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x18964
leaq 0x1d8(%rsp), %r14
leaq 0x158(%rsp), %rsi
movq %r14, %rdi
callq 0x6430
movsd 0xa8(%rsp), %xmm0
leaq 0x1f8(%rsp), %rdi
pushq $0x1
popq %rdx
movq %r14, %rsi
callq 0xf618
jmp 0x18996
leaq 0x1b8(%rsp), %r14
leaq 0x158(%rsp), %rsi
movq %r14, %rdi
callq 0x6430
leaq 0x1f8(%rsp), %rdi
movsd 0x9954(%rip), %xmm0     # 0x222e0
movq %r14, %rsi
xorl %edx, %edx
callq 0xf618
movq %r14, %rdi
callq 0x66d0
cmpb $0x1, 0xf1(%rsp)
jne 0x189bd
leaq 0x1f8(%rsp), %rdi
movsd 0x7650(%rip), %xmm0     # 0x20008
callq 0x126e2
movq 0xd8(%rsp), %rdi
movq 0xe0(%rsp), %rsi
leaq 0x9e12(%rip), %rdx      # 0x227e6
callq 0x1f7e7
movq 0xe0(%rsp), %rsi
cmpq %rsi, %rax
jne 0x18a1c
pushq $0x8
popq %rdi
callq 0x6340
leaq 0x1888b(%rip), %rcx     # 0x31280
addq $0x10, %rcx
movq %rcx, (%rax)
leaq 0x1f8(%rsp), %rdi
movsd 0x75fc(%rip), %xmm0     # 0x20008
movq %rax, %rsi
callq 0xe1d0
movq 0xe0(%rsp), %rsi
movq 0xd8(%rsp), %rdi
leaq 0x9dc6(%rip), %rdx      # 0x227f1
callq 0x1f7e7
movq 0xe0(%rsp), %rsi
cmpq %rsi, %rax
jne 0x18a73
pushq $0x8
popq %rdi
callq 0x6340
leaq 0x188dc(%rip), %rcx     # 0x31328
addq $0x10, %rcx
movq %rcx, (%rax)
leaq 0x1f8(%rsp), %rdi
movsd 0x75a5(%rip), %xmm0     # 0x20008
movq %rax, %rsi
callq 0xe1d0
movq 0xe0(%rsp), %rsi
movq 0xd8(%rsp), %rdi
leaq 0x9d7a(%rip), %rdx      # 0x227fc
callq 0x150fd
movq 0xe0(%rsp), %rsi
cmpq %rsi, %rax
jne 0x18aca
pushq $0x8
popq %rdi
callq 0x6340
leaq 0x18825(%rip), %rcx     # 0x312c8
addq $0x10, %rcx
movq %rcx, (%rax)
leaq 0x1f8(%rsp), %rdi
movsd 0x754e(%rip), %xmm0     # 0x20008
movq %rax, %rsi
callq 0xe1d0
movq 0xe0(%rsp), %rsi
movq 0xd8(%rsp), %rdi
leaq 0x9d2d(%rip), %rdx      # 0x22806
callq 0x150fd
movq 0xe0(%rsp), %rsi
cmpq %rsi, %rax
jne 0x18b21
pushq $0x8
popq %rdi
callq 0x6340
leaq 0x187fe(%rip), %rcx     # 0x312f8
addq $0x10, %rcx
movq %rcx, (%rax)
leaq 0x1f8(%rsp), %rdi
movsd 0x74f7(%rip), %xmm0     # 0x20008
movq %rax, %rsi
callq 0xe1d0
movq 0xe0(%rsp), %rsi
movq 0xd8(%rsp), %rdi
leaq 0x9ce0(%rip), %rdx      # 0x22810
callq 0x150fd
movq 0xe0(%rsp), %rsi
cmpq %rsi, %rax
jne 0x18b7d
pushq $0x10
popq %rdi
callq 0x6340
movq %rax, %r14
movsd 0x74b3(%rip), %xmm0     # 0x20008
movq %rax, %rdi
callq 0xbf00
leaq 0x1f8(%rsp), %rdi
movsd 0x749b(%rip), %xmm0     # 0x20008
movq %r14, %rsi
callq 0xe1d0
movq 0xe0(%rsp), %rsi
movq 0xd8(%rsp), %rdi
leaq 0x9c7d(%rip), %rdx      # 0x22809
callq 0x152d1
cmpq 0xe0(%rsp), %rax
jne 0x18bc9
pushq $0x8
popq %rdi
callq 0x6340
leaq 0x187ae(%rip), %rcx     # 0x31358
addq $0x10, %rcx
movq %rcx, (%rax)
leaq 0x1f8(%rsp), %rdi
movsd 0x7447(%rip), %xmm0     # 0x20008
movq %rax, %rsi
callq 0xe1d0
leaq 0x18(%rsp), %rdi
leaq 0x1f8(%rsp), %rsi
callq 0x17064
movsd 0x98(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
movsd 0xa0(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
movl 0xb0(%rsp), %eax
movl 0x90(%rsp), %r12d
incl %r12d
testl %eax, %eax
cmovnel %eax, %r12d
jne 0x18d63
movsd 0x73e9(%rip), %xmm0     # 0x20008
subsd 0x8(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
pushq $0x1
popq %rbp
leaq 0x18(%rsp), %r14
movl 0x90(%rsp), %eax
incl %eax
cmpl %eax, %ebp
je 0x18d9b
movsd 0x10(%rsp), %xmm0
mulsd 0x8(%rsp), %xmm0
movq %r14, %rdi
movsd %xmm0, 0x10(%rsp)
movl $0x2710, %esi           # imm = 0x2710
callq 0x17068
testb %al, %al
je 0x18de2
movl %ebp, %eax
xorl %edx, %edx
divl %r12d
testl %edx, %edx
jne 0x18d5c
cmpb $0x1, 0xf2(%rsp)
jne 0x18d1f
leaq 0x118(%rsp), %rdi
movq %rbx, %rsi
leaq 0x9db5(%rip), %rdx      # 0x22a4f
callq 0x132d4
leaq 0x178(%rsp), %r15
movq %r15, %rdi
movl %ebp, %esi
callq 0x1a615
leaq 0x20(%rsp), %r13
movq %r13, %rdi
leaq 0x118(%rsp), %rsi
movq %r15, %rdx
callq 0x1326d
leaq 0x198(%rsp), %r15
movq %r15, %rdi
movq %r13, %rsi
leaq 0x9d78(%rip), %rdx      # 0x22a56
callq 0x1324e
leaq 0x1f8(%rsp), %rdi
movq %r15, %rsi
callq 0xf586
movq %r15, %rdi
callq 0x66d0
leaq 0x20(%rsp), %rdi
callq 0x66d0
leaq 0x178(%rsp), %rdi
callq 0x66d0
leaq 0x118(%rsp), %rdi
callq 0x66d0
movl %ebp, %esi
movq 0x192b8(%rip), %rdi     # 0x31fe0
callq 0x6270
movq %rax, %rdi
leaq 0xa143(%rip), %rsi      # 0x22e7a
callq 0x6330
movq %rax, %r15
leaq 0x1f8(%rsp), %rdi
callq 0xdc1e
movq %r15, %rdi
callq 0x6500
movq %rax, %rdi
callq 0x61d0
incl %ebp
jmp 0x18c33
movq 0x19276(%rip), %rdi     # 0x31fe0
leaq 0x9cac(%rip), %rsi      # 0x22a1d
callq 0x6330
movq %rax, %r14
leaq 0x1f8(%rsp), %rdi
callq 0xdc1e
movq %r14, %rdi
callq 0x6500
movq %rax, %rdi
callq 0x61d0
jmp 0x18c17
leaq 0x60(%rsp), %rbx
leaq 0x96a0(%rip), %rsi      # 0x22447
movq %rbx, %rdi
callq 0x134d5
testb %al, %al
je 0x18e01
leaq 0xf8(%rsp), %rdi
movq %rbx, %rsi
callq 0x6430
leaq 0x1f8(%rsp), %rdi
leaq 0xf8(%rsp), %rsi
callq 0xf586
leaq 0xf8(%rsp), %rdi
jmp 0x18e29
leaq 0x9c37(%rip), %rdi      # 0x22a20
leaq 0x9c38(%rip), %rsi      # 0x22a28
leaq 0x9c41(%rip), %rcx      # 0x22a38
movl $0xd4, %edx
callq 0x6250
leaq 0x20(%rsp), %rdi
leaq 0x1f8(%rsp), %rsi
callq 0xf06e
movq 0x19166(%rip), %rdi     # 0x31f80
leaq 0x20(%rsp), %rsi
callq 0x6320
leaq 0x20(%rsp), %rdi
callq 0x66d0
xorl %edi, %edi
callq 0x63c0
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
jmp 0x18ecd
movq %rax, %rbx
leaq 0xf8(%rsp), %rdi
jmp 0x18ecd
movq %rax, %rbx
leaq 0x198(%rsp), %rdi
callq 0x66d0
jmp 0x18e64
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0x66d0
jmp 0x18e73
movq %rax, %rbx
leaq 0x178(%rsp), %rdi
callq 0x66d0
jmp 0x18e85
movq %rax, %rbx
leaq 0x118(%rsp), %rdi
jmp 0x18ecd
jmp 0x18ed4
jmp 0x18ed4
jmp 0x18ed4
jmp 0x18ed4
jmp 0x18ed4
movq %rax, %rbx
pushq $0x10
popq %rsi
movq %r14, %rdi
callq 0x6350
jmp 0x18ed7
jmp 0x18ed4
jmp 0x18ed4
jmp 0x18ed4
jmp 0x18ed4
jmp 0x18ed4
jmp 0x18ed4
movq %rax, %rbx
leaq 0x1b8(%rsp), %rdi
jmp 0x18ecd
movq %rax, %rbx
leaq 0x1d8(%rsp), %rdi
callq 0x66d0
jmp 0x18ed7
movq %rax, %rbx
leaq 0x1f8(%rsp), %rdi
callq 0x1a654
jmp 0x18efb
movq %rax, %rbx
leaq 0x138(%rsp), %rdi
callq 0x66d0
jmp 0x18efb
movq %rax, %rbx
leaq 0x158(%rsp), %rdi
callq 0x66d0
jmp 0x18f0d
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x1a5ea
movq %rbx, %rdi
callq 0x65d0
nop