// File: szmer[P]brill/Brill-train.cpp
// Function: main
int main(int argc, char * argv[]) {
	if(argc < 3 || (argc > 3 && (argc-3) % 2 != 0)) {
    print_usage();
		return 1;
	}

  string output_file_name = string("");
  double improv_margin = 0.0;
  int max_rules = 1000;
  ofstream out;

  // Parse the arguments.
  for (int i = 3; i+1 < argc; i += 2) {
    if(strcmp(argv[i], "-o") == 0)
      output_file_name = string(argv[i+1]);
    if(strcmp(argv[i], "-m") == 0)
      improv_margin = atof(argv[i+1]);
    if(strcmp(argv[i], "-r") == 0)
      max_rules = atoi(argv[i+1]);
  }

	try {
    // Make the base corpus (containing the truth) and the tagset vector.
		Corpus base_corp = Corpus::load_file(argv[1]);
		vector<string> tagset = Corpus::load_tagset(argv[2]);

		// Tag the corpus with the baseline unigram tagger:
		Corpus old_corp = base_corp.tag_all_unigram(output_file_name != "");
    // /\ request leaving unigram table(if we intend to make a tagger file)
		double old_score = Corpus::compare_corpora(& base_corp, & old_corp);
		cout << "Unigram accuracy: " << old_score << endl;

		// Prepare a file where we will output discovered rules (btw put unigrams there).
    prepare_output_file(&out, output_file_name, &base_corp);

		RulesScoreTab tab(tagset, & base_corp);
		Corpus new_corp;
    double new_score = 10.0; // to be compared to the old score (first defined on unigrams above)
    int counter = 0;
		while(counter != max_rules && improv_margin < new_score-old_score) {

      if (counter > 0) { // some cleanup necessary, but not in the first iteration
        tab.clear(); // remove the old rules scores
        old_score = new_score;
        old_corp = new_corp;
      }

      // Try to find some useful rules.
			try { tab.examine(& old_corp); }
			catch(const char * e) { // if the program couldn't find any new good rules, just terminate
						// the loop, and rethrow any other exception
				if(strcmp(e,"No good rules found") == 0)	break;
				else	throw e;
			}

			Rule * winner = tab.get_winner();
			new_corp = winner -> transform_corp(& old_corp);

      // print the rule to the output file, if present
			if(out.is_open())
				out << winner->id << "\n";

			new_score = Corpus::compare_corpora(& base_corp, & new_corp);
			cout << (counter+1) << ". " << winner->description() << "-> " << new_score << endl;

      counter ++;
		} // generate the rules

		cout << "Final score, with " << counter << " rules: " << new_score << endl;
  } // try

  // Catch and print any errors, and exit.
	catch(const char * e) {
		cout << e << endl;
		return 1;
	}

	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x590, %rsp            # imm = 0x590
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $0x3, -0x8(%rbp)
jl 0xa9f8
cmpl $0x3, -0x8(%rbp)
jle 0xaa09
movl -0x8(%rbp), %eax
subl $0x3, %eax
movl $0x2, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
je 0xaa09
callq 0xa720
movl $0x1, -0x4(%rbp)
jmp 0xb27a
leaq -0x31(%rbp), %rdi
movq %rdi, -0x4d8(%rbp)
callq 0x34b0
movq -0x4d8(%rbp), %rdx
leaq 0xd707(%rip), %rsi      # 0x1812e
leaq -0x30(%rbp), %rdi
callq 0xb380
jmp 0xaa32
leaq -0x31(%rbp), %rdi
callq 0x3300
movq $0x0, -0x50(%rbp)
movl $0x3e8, -0x54(%rbp)     # imm = 0x3E8
leaq -0x258(%rbp), %rdi
callq 0x3460
jmp 0xaa58
movl $0x3, -0x25c(%rbp)
movl -0x25c(%rbp), %eax
addl $0x1, %eax
cmpl -0x8(%rbp), %eax
jge 0xabe0
movq -0x10(%rbp), %rax
movslq -0x25c(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0xdabc(%rip), %rsi      # 0x18546
callq 0x33c0
cmpl $0x0, %eax
jne 0xab50
movq -0x10(%rbp), %rax
movslq -0x25c(%rbp), %rcx
movq 0x8(%rax,%rcx,8), %rax
movq %rax, -0x4e8(%rbp)
leaq -0x281(%rbp), %rdi
movq %rdi, -0x4e0(%rbp)
callq 0x34b0
movq -0x4e8(%rbp), %rsi
movq -0x4e0(%rbp), %rdx
leaq -0x280(%rbp), %rdi
callq 0xb380
jmp 0xaade
leaq -0x30(%rbp), %rdi
leaq -0x280(%rbp), %rsi
callq 0x3350
leaq -0x280(%rbp), %rdi
callq 0x3548
leaq -0x281(%rbp), %rdi
callq 0x3300
jmp 0xab50
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x31(%rbp), %rdi
callq 0x3300
jmp 0xb286
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0xb26f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x281(%rbp), %rdi
callq 0x3300
jmp 0xb263
movq -0x10(%rbp), %rax
movslq -0x25c(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0xd9e3(%rip), %rsi      # 0x18549
callq 0x33c0
cmpl $0x0, %eax
jne 0xab8e
movq -0x10(%rbp), %rax
movl -0x25c(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rdi
callq 0x3370
movsd %xmm0, -0x50(%rbp)
movq -0x10(%rbp), %rax
movslq -0x25c(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0xd9a8(%rip), %rsi      # 0x1854c
callq 0x33c0
cmpl $0x0, %eax
jne 0xabca
movq -0x10(%rbp), %rax
movl -0x25c(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rdi
callq 0x3410
movl %eax, -0x54(%rbp)
jmp 0xabcc
movl -0x25c(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x25c(%rbp)
jmp 0xaa62
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
leaq -0x2d0(%rbp), %rdi
callq 0x3890
jmp 0xabf6
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rsi
leaq -0x2e8(%rbp), %rdi
callq 0x3e30
jmp 0xac0c
leaq 0xd51b(%rip), %rsi      # 0x1812e
leaq -0x30(%rbp), %rdi
callq 0xcd30
movb %al, -0x4e9(%rbp)
jmp 0xac24
movb -0x4e9(%rbp), %al
movzbl %al, %edx
andl $0x1, %edx
leaq -0x330(%rbp), %rdi
leaq -0x2d0(%rbp), %rsi
callq 0x40e0
jmp 0xac45
leaq -0x2d0(%rbp), %rdi
leaq -0x330(%rbp), %rsi
callq 0x3680
movsd %xmm0, -0x4f8(%rbp)
jmp 0xac62
movsd -0x4f8(%rbp), %xmm0
movsd %xmm0, -0x338(%rbp)
movq 0x1835f(%rip), %rdi     # 0x22fd8
leaq 0xd8cf(%rip), %rsi      # 0x1854f
callq 0x3290
movq %rax, -0x500(%rbp)
jmp 0xac8e
movq -0x500(%rbp), %rdi
movsd -0x338(%rbp), %xmm0
callq 0x34e0
movq %rax, -0x508(%rbp)
jmp 0xacab
movq -0x508(%rbp), %rdi
movq 0x182ff(%rip), %rsi     # 0x22fb8
callq 0x32e0
jmp 0xacc0
leaq -0x358(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x3110
jmp 0xacd2
leaq -0x258(%rbp), %rdi
leaq -0x358(%rbp), %rsi
leaq -0x2d0(%rbp), %rdx
callq 0xa890
jmp 0xacee
leaq -0x358(%rbp), %rdi
callq 0x3548
leaq -0x3f0(%rbp), %rdi
leaq -0x2e8(%rbp), %rsi
leaq -0x2d0(%rbp), %rdx
callq 0x6f70
jmp 0xad16
leaq -0x438(%rbp), %rdi
callq 0xb350
movsd 0xd2de(%rip), %xmm0     # 0x18008
movsd %xmm0, -0x440(%rbp)
movl $0x0, -0x444(%rbp)
movl -0x444(%rbp), %ecx
xorl %eax, %eax
cmpl -0x54(%rbp), %ecx
movb %al, -0x509(%rbp)
je 0xad71
movsd -0x50(%rbp), %xmm1
movsd -0x440(%rbp), %xmm0
subsd -0x338(%rbp), %xmm0
ucomisd %xmm1, %xmm0
seta %al
movb %al, -0x509(%rbp)
movb -0x509(%rbp), %al
testb $0x1, %al
jne 0xad80
jmp 0xb0bd
cmpl $0x0, -0x444(%rbp)
jle 0xae32
leaq -0x3f0(%rbp), %rdi
callq 0xa5b0
movsd -0x440(%rbp), %xmm0
movsd %xmm0, -0x338(%rbp)
leaq -0x330(%rbp), %rdi
leaq -0x438(%rbp), %rsi
callq 0xcd60
jmp 0xadbe
jmp 0xae32
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0xb1bf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0xb1b3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0xb1a7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0xb19b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x358(%rbp), %rdi
callq 0x3548
jmp 0xb19b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0xb183
leaq -0x3f0(%rbp), %rdi
leaq -0x330(%rbp), %rsi
callq 0x7e50
jmp 0xae47
jmp 0xaedc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
movl -0x44(%rbp), %eax
movl $0x1, %ecx
cmpl %ecx, %eax
jne 0xb183
movq -0x40(%rbp), %rdi
callq 0x30f0
movq %rax, -0x450(%rbp)
movq -0x450(%rbp), %rdi
leaq 0xd446(%rip), %rsi      # 0x182cc
callq 0x33c0
cmpl $0x0, %eax
jne 0xae9a
callq 0x3430
jmp 0xb0bd
movl $0x8, %edi
callq 0x3140
movq %rax, %rdi
movq -0x450(%rbp), %rax
movq %rax, (%rdi)
movq 0x18108(%rip), %rsi     # 0x22fc0
xorl %eax, %eax
movl %eax, %edx
callq 0x3470
jmp 0xb28f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
callq 0x3430
jmp 0xb183
leaq -0x3f0(%rbp), %rdi
callq 0xa5e0
movq %rax, -0x518(%rbp)
jmp 0xaef1
movq -0x518(%rbp), %rax
movq %rax, -0x458(%rbp)
movq -0x458(%rbp), %rsi
leaq -0x4a0(%rbp), %rdi
leaq -0x330(%rbp), %rdx
callq 0x5620
jmp 0xaf1b
leaq -0x438(%rbp), %rdi
leaq -0x4a0(%rbp), %rsi
movq %rsi, -0x528(%rbp)
callq 0xcda0
movq -0x528(%rbp), %rdi
callq 0xb7c0
leaq -0x258(%rbp), %rdi
callq 0x3220
movb %al, -0x519(%rbp)
jmp 0xaf55
movb -0x519(%rbp), %al
testb $0x1, %al
jne 0xaf61
jmp 0xaf9b
movq -0x458(%rbp), %rax
movq 0x80(%rax), %rsi
leaq -0x258(%rbp), %rdi
callq 0x3160
movq %rax, -0x530(%rbp)
jmp 0xaf84
movq -0x530(%rbp), %rdi
leaq 0xd5b2(%rip), %rsi      # 0x18544
callq 0x3290
jmp 0xaf99
jmp 0xaf9b
leaq -0x2d0(%rbp), %rdi
leaq -0x438(%rbp), %rsi
callq 0x3680
movsd %xmm0, -0x538(%rbp)
jmp 0xafb8
movsd -0x538(%rbp), %xmm0
movsd %xmm0, -0x440(%rbp)
movl -0x444(%rbp), %esi
incl %esi
movq 0x18001(%rip), %rdi     # 0x22fd8
callq 0x3490
movq %rax, -0x540(%rbp)
jmp 0xafe5
movq -0x540(%rbp), %rdi
leaq 0xd56f(%rip), %rsi      # 0x18562
callq 0x3290
movq %rax, -0x548(%rbp)
jmp 0xb001
movq -0x458(%rbp), %rsi
leaq -0x4c0(%rbp), %rdi
callq 0x50a0
jmp 0xb016
movq -0x548(%rbp), %rdi
leaq -0x4c0(%rbp), %rsi
callq 0x3270
movq %rax, -0x550(%rbp)
jmp 0xb032
movq -0x550(%rbp), %rdi
leaq 0xd525(%rip), %rsi      # 0x18565
callq 0x3290
movq %rax, -0x558(%rbp)
jmp 0xb04e
movq -0x558(%rbp), %rdi
movsd -0x440(%rbp), %xmm0
callq 0x34e0
movq %rax, -0x560(%rbp)
jmp 0xb06b
movq -0x560(%rbp), %rdi
movq 0x17f3f(%rip), %rsi     # 0x22fb8
callq 0x32e0
jmp 0xb080
leaq -0x4c0(%rbp), %rdi
callq 0x3548
movl -0x444(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x444(%rbp)
jmp 0xad3c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x4c0(%rbp), %rdi
callq 0x3548
jmp 0xb183
movq 0x17f14(%rip), %rdi     # 0x22fd8
leaq 0xd49e(%rip), %rsi      # 0x18569
callq 0x3290
movq %rax, -0x568(%rbp)
jmp 0xb0d9
movq -0x568(%rbp), %rdi
movl -0x444(%rbp), %esi
callq 0x3490
movq %rax, -0x570(%rbp)
jmp 0xb0f4
movq -0x570(%rbp), %rdi
leaq 0xd47a(%rip), %rsi      # 0x1857c
callq 0x3290
movq %rax, -0x578(%rbp)
jmp 0xb110
movq -0x578(%rbp), %rdi
movsd -0x440(%rbp), %xmm0
callq 0x34e0
movq %rax, -0x580(%rbp)
jmp 0xb12d
movq -0x580(%rbp), %rdi
movq 0x17e7d(%rip), %rsi     # 0x22fb8
callq 0x32e0
jmp 0xb142
leaq -0x438(%rbp), %rdi
callq 0xb7c0
leaq -0x3f0(%rbp), %rdi
callq 0xcde0
leaq -0x330(%rbp), %rdi
callq 0xb7c0
leaq -0x2e8(%rbp), %rdi
callq 0xb840
leaq -0x2d0(%rbp), %rdi
callq 0xb7c0
jmp 0xb23b
leaq -0x438(%rbp), %rdi
callq 0xb7c0
leaq -0x3f0(%rbp), %rdi
callq 0xcde0
leaq -0x330(%rbp), %rdi
callq 0xb7c0
leaq -0x2e8(%rbp), %rdi
callq 0xb840
leaq -0x2d0(%rbp), %rdi
callq 0xb7c0
movl -0x44(%rbp), %eax
movl $0x1, %ecx
cmpl %ecx, %eax
jne 0xb263
movq -0x40(%rbp), %rdi
callq 0x30f0
movq %rax, -0x4c8(%rbp)
movq -0x4c8(%rbp), %rsi
movq 0x17deb(%rip), %rdi     # 0x22fd8
callq 0x3290
movq %rax, -0x588(%rbp)
jmp 0xb1fb
movq -0x588(%rbp), %rdi
movq 0x17daf(%rip), %rsi     # 0x22fb8
callq 0x32e0
jmp 0xb210
movl $0x1, -0x4(%rbp)
movl $0x1, -0x4cc(%rbp)
callq 0x3430
jmp 0xb24c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
callq 0x3430
jmp 0xb263
movl $0x0, -0x4(%rbp)
movl $0x1, -0x4cc(%rbp)
leaq -0x258(%rbp), %rdi
callq 0x33e0
leaq -0x30(%rbp), %rdi
callq 0x3548
jmp 0xb27a
leaq -0x258(%rbp), %rdi
callq 0x33e0
leaq -0x30(%rbp), %rdi
callq 0x3548
jmp 0xb286
movl -0x4(%rbp), %eax
addq $0x590, %rsp            # imm = 0x590
popq %rbp
retq
movq -0x40(%rbp), %rdi
callq 0x34a0
nop