// File: /workspace/github_cpp_makefile_star2_O2/uclaopt[P]AsyncQVI/src/test.cc
// Function: main
int main(int argc, char** argv){
	
	/* Step 0: load parameters from makefile.(defined in util.h) */
	Params params;
	parse_input_argv(&params, argc, argv);
	params.time = get_wall_time(); 
	cout<<"iter time reward flag"<<endl;
	
	/* Step 1: choose an algorithm in makefile 
	   -algo 0 is AsyncQVI, 
	         1 is Qlearning,
			 2 is VRVI 
			 3 is VRQVI  */
	
	// policy vector
	std::vector<int> pi(params.len_state, 0.);
	pthread_barrier_init(&barrier, &attr, params.total_num_threads);
	
	 if(params.algo == 0){ // run AsyncQVI
		// state value, V[i] = max_a Q(i,a)
		std::vector<double> V(params.len_state, 0.); 
		
		// QVI object (defined in algo.h)
		QVI obj(&V, &pi, &params);
		
		// launch parallel threads
		std::vector<std::thread> mythreads;
		for (size_t i = 0; i < params.total_num_threads; i++) {
			mythreads.push_back(std::thread(asyncQVI, i, obj, &params));
		} 
		for (size_t i = 0; i < params.total_num_threads; i++) {
			mythreads[i].join();
		}
	}
	
	else if(params.algo == 1){ // run Async Q-learning
		// Q value
		std::vector<std::vector<double>> Q(params.len_state, std::vector<double>(params.len_action, 0.));
		// state value, V[i] = max_a Q(i,a)
		std::vector<double> V(params.len_state);
		
		// Qlearning object (defined in algo.h)
		Qlearning obj(&Q, &V, &pi, &params);
		
		// launch parallel threads
		std::vector<std::thread> mythreads;
		for (size_t i = 0; i < params.total_num_threads; i++) {
			mythreads.push_back(std::thread(asyncQL, i, obj, &params));
		} 
		for (size_t i = 0; i < params.total_num_threads; i++) {
			mythreads[i].join();
		}
	}
	
	else if(params.algo == 2){ // run VRVI: Variance Reduced Value Iteration..., Sidford et al. 2018
		// \tilde{x} in Alg.8 
		std::vector<std::vector<double>> x(params.len_state, std::vector<double>(params.len_action, 0.));
		// v_k in Alg.9
		std::vector<double> v_outer(params.len_state, 0.);
		// v_t in Alg.8
		std::vector<double> v_inner(params.len_state, 0.);
		
		// VRVI object (defined in algo.h)
		VRVI obj(&x, &v_outer, &v_inner, &pi, &params); 
		obj.solve();
	}
	
	else{ // run VRQVI: Near-Optimal Time and Sample Complexities..., Sidford et al. 2018
		// Q, w in Alg.1
		std::vector<std::vector<double>> Q(params.len_state, std::vector<double>(params.len_action, 0.));
		std::vector<std::vector<double>> w(params.len_state, std::vector<double>(params.len_action, 0.));		
		// v^i in Alg.2
		std::vector<double> v_outer(params.len_state, 0.);
		// v^i in Alg.1
		std::vector<double> v_inner(params.len_state, 0.);
		
		// VRQVI object (defined in algo.h)
		VRQVI obj(&Q, &w, &v_outer, &v_inner, &pi, &params); 
		obj.solve();
	}
	
	// Step 2: save results
	if(params.save){
		std::ofstream outFile("policy.txt");
		for (int i = 0; i < params.len_state; i++){
			outFile << pi[i] << "\n";
		}
		outFile.close();
	}
	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1638, %rsp           # imm = 0x1638
movq %rsi, %rdx
movl %edi, %esi
xorps %xmm0, %xmm0
movhps 0x318c(%rip), %xmm0     # xmm0 = xmm0[0,1],mem[0,1]
leaq 0xa0(%rsp), %rbx
movups %xmm0, 0x8(%rbx)
movabsq $0x3fefae147ae147ae, %rax # imm = 0x3FEFAE147AE147AE
movq %rax, 0x18(%rbx)
movabsq $0xc800000064, %rax     # imm = 0xC800000064
movq %rax, 0x20(%rbx)
movaps 0x31a5(%rip), %xmm0     # 0x6070
movups %xmm0, 0x30(%rbx)
movl $0x1, 0x40(%rbx)
movaps 0x31a3(%rip), %xmm0     # 0x6080
movups %xmm0, 0x48(%rbx)
andq $0x0, 0x70(%rbx)
xorps %xmm0, %xmm0
andq $0x0, 0x80(%rbx)
movups %xmm0, 0x58(%rbx)
andl $0x0, 0x68(%rbx)
movq %rbx, %rdi
callq 0x24ac
callq 0x2b55
movsd %xmm0, 0x78(%rbx)
movq 0x60c6(%rip), %rdi      # 0x8fd8
leaq 0x32ca(%rip), %rsi      # 0x61e3
callq 0x21a0
movq %rax, %rdi
callq 0x20a0
movslq (%rbx), %r14
leaq 0x128(%rsp), %rdx
andl $0x0, (%rdx)
leaq 0x80(%rsp), %rdi
leaq 0x50(%rsp), %rcx
movq %r14, %rsi
callq 0x3a2e
movl 0x30(%rbx), %edx
leaq 0x7605(%rip), %rdi      # 0xa558
leaq 0x7646(%rip), %rsi      # 0xa5a0
callq 0x22b0
movl 0x28(%rbx), %eax
cmpl $0x2, %eax
je 0x3157
cmpl $0x1, %eax
je 0x3041
testl %eax, %eax
jne 0x3232
leaq 0x128(%rsp), %rdx
andq $0x0, (%rdx)
leaq 0x50(%rsp), %rdi
leaq 0x30(%rsp), %rcx
movq %r14, %rsi
callq 0x3a84
leaq 0x128(%rsp), %rdi
leaq 0x50(%rsp), %rsi
leaq 0x80(%rsp), %rdx
leaq 0xa0(%rsp), %rcx
callq 0x3ada
leaq 0x30(%rsp), %r14
andq $0x0, 0x10(%r14)
xorps %xmm0, %xmm0
movaps %xmm0, (%r14)
xorl %ecx, %ecx
leaq -0x2b0(%rip), %r15      # 0x2d26
leaq 0x68(%rsp), %r12
leaq 0x10(%rsp), %r13
leaq 0x128(%rsp), %rbp
leaq 0x48(%rsp), %rbx
movq %rcx, 0x10(%rsp)
movslq 0xd0(%rsp), %rax
cmpq %rax, %rcx
jae 0x3371
leaq 0xa0(%rsp), %rax
movq %rax, 0x48(%rsp)
movq %r12, %rdi
movq %r15, %rsi
movq %r13, %rdx
movq %rbp, %rcx
movq %rbx, %r8
callq 0x3b2c
movq %r14, %rdi
movq %r12, %rsi
callq 0x5254
movq %r12, %rdi
callq 0x3bd4
movq 0x10(%rsp), %rcx
incq %rcx
jmp 0x2fed
movslq 0xa4(%rsp), %rsi
leaq 0x30(%rsp), %rdx
andq $0x0, (%rdx)
leaq 0x128(%rsp), %rdi
leaq 0x10(%rsp), %rcx
callq 0x3a84
leaq 0x50(%rsp), %rdi
leaq 0x128(%rsp), %rdx
leaq 0x68(%rsp), %rcx
movq %r14, %rsi
callq 0x3c04
leaq 0x128(%rsp), %rdi
callq 0x513e
movslq 0xa0(%rsp), %rsi
leaq 0x30(%rsp), %rdi
leaq 0x128(%rsp), %rdx
callq 0x3c5a
leaq 0x128(%rsp), %rdi
leaq 0x50(%rsp), %rsi
leaq 0x30(%rsp), %rdx
leaq 0x80(%rsp), %rcx
leaq 0xa0(%rsp), %r8
callq 0x3cac
leaq 0x10(%rsp), %r14
andq $0x0, 0x10(%r14)
xorps %xmm0, %xmm0
movaps %xmm0, (%r14)
xorl %ecx, %ecx
leaq -0x315(%rip), %r15      # 0x2dd1
leaq 0x48(%rsp), %r12
leaq 0x68(%rsp), %r13
leaq 0x128(%rsp), %rbp
leaq 0x98(%rsp), %rbx
movq %rcx, 0x68(%rsp)
movslq 0xd0(%rsp), %rax
cmpq %rax, %rcx
jae 0x339a
leaq 0xa0(%rsp), %rax
movq %rax, 0x98(%rsp)
movq %r12, %rdi
movq %r15, %rsi
movq %r13, %rdx
movq %rbp, %rcx
movq %rbx, %r8
callq 0x3d18
movq %r14, %rdi
movq %r12, %rsi
callq 0x5254
movq %r12, %rdi
callq 0x3bd4
movq 0x68(%rsp), %rcx
incq %rcx
jmp 0x3100
movslq 0xa4(%rsp), %rsi
leaq 0x30(%rsp), %rdx
andq $0x0, (%rdx)
leaq 0x128(%rsp), %rdi
leaq 0x10(%rsp), %rcx
callq 0x3a84
leaq 0x50(%rsp), %rdi
leaq 0x128(%rsp), %rdx
leaq 0x68(%rsp), %rcx
movq %r14, %rsi
callq 0x3c04
leaq 0x128(%rsp), %rbx
movq %rbx, %rdi
callq 0x513e
movslq 0xa0(%rsp), %rsi
andq $0x0, (%rbx)
leaq 0x30(%rsp), %rdi
leaq 0x128(%rsp), %rdx
leaq 0x10(%rsp), %rcx
callq 0x3a84
movslq 0xa0(%rsp), %rsi
leaq 0x128(%rsp), %rdx
andq $0x0, (%rdx)
leaq 0x10(%rsp), %rdi
leaq 0x68(%rsp), %rcx
callq 0x3a84
leaq 0x128(%rsp), %rdi
leaq 0x50(%rsp), %rsi
leaq 0x30(%rsp), %rdx
leaq 0x10(%rsp), %rcx
leaq 0x80(%rsp), %r8
leaq 0xa0(%rsp), %r9
callq 0x3de2
leaq 0x128(%rsp), %rdi
callq 0x3e60
leaq 0x10(%rsp), %rdi
callq 0x513e
jmp 0x33e3
movslq 0xa4(%rsp), %rsi
leaq 0x30(%rsp), %rdx
andq $0x0, (%rdx)
leaq 0x128(%rsp), %rdi
leaq 0x10(%rsp), %rcx
callq 0x3a84
leaq 0x50(%rsp), %rdi
leaq 0x128(%rsp), %rdx
leaq 0x68(%rsp), %rcx
movq %r14, %rsi
callq 0x3c04
leaq 0x128(%rsp), %rdi
callq 0x513e
movslq 0xa0(%rsp), %r14
movslq 0xa4(%rsp), %rsi
leaq 0x10(%rsp), %rdx
andq $0x0, (%rdx)
leaq 0x128(%rsp), %rdi
leaq 0x68(%rsp), %rcx
callq 0x3a84
leaq 0x30(%rsp), %rdi
leaq 0x128(%rsp), %rdx
leaq 0x48(%rsp), %rcx
movq %r14, %rsi
callq 0x3c04
leaq 0x128(%rsp), %r14
movq %r14, %rdi
callq 0x513e
movslq 0xa0(%rsp), %rsi
andq $0x0, (%r14)
leaq 0x10(%rsp), %rdi
leaq 0x128(%rsp), %rdx
leaq 0x68(%rsp), %rcx
callq 0x3a84
movslq 0xa0(%rsp), %rsi
leaq 0x128(%rsp), %rdx
andq $0x0, (%rdx)
leaq 0x68(%rsp), %rdi
leaq 0x48(%rsp), %rcx
callq 0x3a84
movq %rbx, (%rsp)
leaq 0x128(%rsp), %rdi
leaq 0x50(%rsp), %rsi
leaq 0x30(%rsp), %rdx
leaq 0x10(%rsp), %rcx
leaq 0x68(%rsp), %r8
leaq 0x80(%rsp), %r9
callq 0x40f2
leaq 0x128(%rsp), %rdi
callq 0x4188
leaq 0x68(%rsp), %rdi
callq 0x513e
leaq 0x10(%rsp), %rdi
callq 0x513e
leaq 0x30(%rsp), %rdi
callq 0x3dc0
jmp 0x33ed
xorl %ebx, %ebx
xorl %r14d, %r14d
cltq
cmpq %rax, %r14
jae 0x33c3
movq 0x30(%rsp), %rdi
addq %rbx, %rdi
callq 0x22f0
incq %r14
movl 0xd0(%rsp), %eax
addq $0x8, %rbx
jmp 0x3376
xorl %ebx, %ebx
xorl %r14d, %r14d
cltq
cmpq %rax, %r14
jae 0x33d9
movq 0x10(%rsp), %rdi
addq %rbx, %rdi
callq 0x22f0
incq %r14
movl 0xd0(%rsp), %eax
addq $0x8, %rbx
jmp 0x339f
leaq 0x30(%rsp), %rdi
callq 0x3be2
leaq 0x50(%rsp), %rdi
callq 0x513e
jmp 0x33f7
leaq 0x10(%rsp), %rdi
callq 0x3be2
leaq 0x30(%rsp), %rdi
callq 0x513e
leaq 0x50(%rsp), %rdi
callq 0x3dc0
cmpl $0x0, 0x108(%rsp)
je 0x3475
leaq 0x2df1(%rip), %rsi      # 0x61f9
leaq 0x128(%rsp), %rdi
pushq $0x10
popq %rdx
callq 0x21d0
xorl %r15d, %r15d
leaq 0x128(%rsp), %rbx
leaq 0x2dda(%rip), %r14      # 0x6204
movslq 0xa0(%rsp), %rax
cmpq %rax, %r15
jge 0x345b
movq 0x80(%rsp), %rax
movl (%rax,%r15,4), %esi
movq %rbx, %rdi
callq 0x2300
movq %rax, %rdi
movq %r14, %rsi
callq 0x21a0
incq %r15
jmp 0x342a
leaq 0x128(%rsp), %rdi
callq 0x2220
leaq 0x128(%rsp), %rdi
callq 0x2250
leaq 0x80(%rsp), %rdi
callq 0x5056
xorl %eax, %eax
addq $0x1638, %rsp           # imm = 0x1638
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
jmp 0x34f7
movq %rax, %rbx
jmp 0x3501
movq %rax, %rbx
leaq 0x128(%rsp), %rdi
jmp 0x3548
jmp 0x34b2
movq %rax, %rbx
jmp 0x3543
jmp 0x34be
jmp 0x34be
movq %rax, %rbx
jmp 0x354d
jmp 0x34d2
movq %rax, %rbx
jmp 0x3575
jmp 0x34d2
movq %rax, %rbx
leaq 0x128(%rsp), %rdi
jmp 0x357a
jmp 0x351e
jmp 0x351e
jmp 0x351e
jmp 0x351e
movq %rax, %rbx
leaq 0x68(%rsp), %rdi
callq 0x513e
leaq 0x10(%rsp), %rdi
callq 0x513e
leaq 0x30(%rsp), %rdi
callq 0x3dc0
jmp 0x354d
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x513e
jmp 0x3543
jmp 0x3581
movq %rax, %rbx
jmp 0x3591
jmp 0x3536
jmp 0x3568
movq %rax, %rbx
leaq 0x48(%rsp), %rdi
callq 0x3bd4
jmp 0x3539
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x3be2
leaq 0x30(%rsp), %rdi
callq 0x513e
leaq 0x50(%rsp), %rdi
callq 0x3dc0
jmp 0x3591
movq %rax, %rbx
leaq 0x68(%rsp), %rdi
callq 0x3bd4
jmp 0x356b
movq %rax, %rbx
leaq 0x30(%rsp), %rdi
callq 0x3be2
leaq 0x50(%rsp), %rdi
callq 0x513e
jmp 0x3591
movq %rax, %rbx
leaq 0x128(%rsp), %rdi
callq 0x2250
leaq 0x80(%rsp), %rdi
callq 0x5056
movq %rbx, %rdi
callq 0x2320