// File: /workspace/github_cpp_makefile_star2_O3/lipiji[P]PG_DEEP/train.cpp
// Function: main
int main(int argc, const char *argv[])
{
    string ftx = "./data/test_x.txt";
    string fty = "./data/test_y.txt";
    int epoch = 100;
    int batch_size = 0;
    double gamma = 0.1; // learning rate
    int k = 1; //Contrastive Divergence k

    int hls[] = {500, 500, 900};
    int n_layers = sizeof(hls) / sizeof(hls[0]);
    int n_lables = 10;
    double lbd = 0.0002; // weight cost

    Conf conf(ftx, fty, epoch, batch_size, hls, k, gamma, n_layers, n_lables, lbd);
    Dataset data(conf);

    /*// test rbm
      RBM rbm(data.N, data.n_f, 400, NULL, NULL, NULL, lbd, 0);

      for(int i=0; i<epoch; i++)
      {
      cout << "epoch: " << i << endl;
      for(int j=0; j<data.N; j++)
      {
      double *x = new double[data.n_f];
      for(int f=0; f<data.n_f; f++)
      x[f] = data.X[j][f];
      rbm.train(x, gamma, k);
      delete[] x;


      }
      ofstream fout("./model/W1");
      for(int j=0; j<rbm.n_visible; j++)
      {
      for(int l=0; l<rbm.n_hidden; l++)
      {
      fout << rbm.W[l][j] << " ";
      }
      fout << endl;
      }
      fout << flush;
      fout.close();


      }
      */
    //test lr

    /*
       LR lr(data, conf);
       for(int i=0; i<epoch; i++)
       {
       cout << "epoch: " << i << endl;
       for(int j=0; j<data.N; j++)
       {
       double *x = new double[lr.n_features];
       for(int f=0; f<lr.n_features; f++)
       x[f] = data.X[j][f];
       int *y = new int[lr.n_labels];
       y[int(data.Y[j])] = 1;

       lr.train(x, y, gamma);
       delete[] x;
       delete[] y;
       }
       }
       for(int j=0; j<data.N; j++)
       {
       double *x = new double[lr.n_features];
       for(int f=0; f<lr.n_features; f++)
       x[f] = data.X[j][f];
       double *y = new double[lr.n_labels];

       lr.predict(x, y);
       cout <<data.Y[j]<<": ";
       for(int i=0; i<lr.n_labels; i++)
       cout <<y[i]<<" ";
       cout<<endl;
       delete[] y;
       }
       */


    DBN dbn(data, conf);
    dbn.pretrain(data, conf);
    for(int i=0; i<=n_layers; i++)
    {
        char str[] = "./model/W";
        char W_l[128];
        sprintf(W_l, "%s%d", str, (i+1));

        ofstream fout(W_l);
        if(i < n_layers)
        {
            for(int j=0; j<dbn.rbm_layers[i]->n_visible; j++)
            {
                for(int l=0; l<dbn.rbm_layers[i]->n_hidden; l++)
                {
                    fout << dbn.rbm_layers[i]->W[l][j] << " ";
                }
                fout << endl;
            }
        }
        else
        {
            for(int j=0; j<dbn.lr_layer->n_features; j++)
            {
                for(int l=0; l<dbn.lr_layer->n_labels; l++)
                {
                    fout << dbn.lr_layer->W[l][j] << " ";
                }
                fout << endl;
            }
        }

        fout << flush;
        fout.close();

    }
    dbn.finetune(data, conf);

    ftx = "./data/train_x.txt";
    fty = "./data/train_y.txt";

    Conf conf_(ftx, fty, epoch, batch_size, hls, k, gamma, n_layers, n_lables, lbd);
    Dataset data_(conf_);


    double acc_num = 0;
    for(int j=0; j<data_.N; j++)
    {
        double *x = new double[data_.n_f];
        for(int f=0; f<data_.n_f; f++)
            x[f] = data_.X[j][f];
        double *y = new double[conf.n_labels];
        int true_label = int(data_.Y[j]);

        if(dbn.predict(x, y, true_label) == 1)
            acc_num++;
        delete[] x;
        delete[] y;

        cout << j <<": Accuracy=" << acc_num/(j+1) <<endl;
    }

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x8d8, %rsp            # imm = 0x8D8
leaq 0x28(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0x4b43(%rip), %rsi      # 0x7020
leaq 0x4b4d(%rip), %rdx      # 0x7031
leaq 0x18(%rsp), %rdi
callq 0x3378
leaq 0x48(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0x4b34(%rip), %rsi      # 0x7032
leaq 0x4b3e(%rip), %rdx      # 0x7043
leaq 0x38(%rsp), %rdi
callq 0x3378
movabsq $0x1f4000001f4, %rax    # imm = 0x1F4000001F4
movq %rax, 0x58(%rsp)
movl $0x384, 0x60(%rsp)      # imm = 0x384
leaq 0xe8(%rsp), %r14
movq %r14, -0x10(%r14)
movq 0x18(%rsp), %rsi
movq 0x20(%rsp), %rdx
addq %rsi, %rdx
leaq 0xd8(%rsp), %rdi
callq 0x32e2
leaq 0xc8(%rsp), %r15
movq %r15, -0x10(%r15)
movq 0x38(%rsp), %rsi
movq 0x40(%rsp), %rdx
addq %rsi, %rdx
leaq 0xb8(%rsp), %rdi
callq 0x32e2
subq $0x8, %rsp
leaq 0x2c0(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
leaq 0xc0(%rsp), %rdx
leaq 0x60(%rsp), %r9
movsd 0x4a6d(%rip), %xmm0     # 0x7008
movsd 0x4a6d(%rip), %xmm1     # 0x7010
movl $0x64, %ecx
xorl %r8d, %r8d
pushq $0xa
pushq $0x3
pushq $0x1
callq 0x3636
addq $0x20, %rsp
movq 0xb8(%rsp), %rdi
cmpq %r15, %rdi
je 0x25d7
movq 0xc8(%rsp), %rsi
incq %rsi
callq 0x21c0
movq 0xd8(%rsp), %rdi
cmpq %r14, %rdi
je 0x25f4
movq 0xe8(%rsp), %rsi
incq %rsi
callq 0x21c0
leaq 0x828(%rsp), %rdi
leaq 0x2b8(%rsp), %rsi
callq 0x2f66
leaq 0x130(%rsp), %rdi
leaq 0x828(%rsp), %rsi
callq 0x37fa
leaq 0x828(%rsp), %rdi
callq 0x3794
leaq 0x138(%rsp), %rbx
movq -0x8(%rbx), %rax
leaq 0x1f8(%rsp), %r14
movq %rax, -0x8(%r14)
movq %r14, %rdi
movq %rbx, %rsi
callq 0x307e
leaq 0x210(%rsp), %rdi
leaq 0x150(%rsp), %r15
movq %r15, %rsi
callq 0x3118
movl 0x168(%rsp), %eax
movl %eax, 0x228(%rsp)
leaq 0x778(%rsp), %rdi
leaq 0x2b8(%rsp), %rsi
callq 0x2f66
leaq 0xf8(%rsp), %rdi
leaq 0x1f0(%rsp), %rsi
leaq 0x778(%rsp), %rdx
callq 0x4e6c
leaq 0x778(%rsp), %rdi
callq 0x3794
leaq 0x1f0(%rsp), %rdi
callq 0x4332
movq 0x130(%rsp), %rax
leaq 0x1b8(%rsp), %r14
movq %rax, -0x8(%r14)
movq %r14, %rdi
movq %rbx, %rsi
callq 0x307e
leaq 0x1d0(%rsp), %rdi
movq %r15, %rsi
callq 0x3118
movl 0x168(%rsp), %eax
movl %eax, 0x1e8(%rsp)
leaq 0x6c8(%rsp), %rdi
leaq 0x2b8(%rsp), %rsi
callq 0x2f66
leaq 0xf8(%rsp), %rdi
leaq 0x1b0(%rsp), %rsi
leaq 0x6c8(%rsp), %rdx
callq 0x5034
leaq 0x6c8(%rsp), %rdi
callq 0x3794
leaq 0x1b0(%rsp), %rdi
callq 0x4332
movq 0x7880(%rip), %rax      # 0x9fd0
movq (%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x18(%rax), %rax
movq %rax, 0x10(%rsp)
leaq 0x368(%rsp), %rbx
leaq 0x4a69(%rip), %r15      # 0x71d9
xorl %r12d, %r12d
movabsq $0x2f6c65646f6d2f2e, %rax # imm = 0x2F6C65646F6D2F2E
movq %rax, 0x68(%rsp)
movw $0x57, 0x70(%rsp)
leaq 0x1(%r12), %r14
leaq 0x230(%rsp), %r13
movq %r13, %rdi
leaq 0x48ae(%rip), %rsi      # 0x704e
leaq 0x68(%rsp), %rdx
movl %r14d, %ecx
xorl %eax, %eax
callq 0x2050
movq %rbx, %rdi
movq %r13, %rsi
movl $0x10, %edx
callq 0x21d0
cmpq $0x3, %r12
jne 0x286a
movq 0x128(%rsp), %rax
cmpl $0x0, 0x4(%rax)
jle 0x2910
xorl %r12d, %r12d
cmpl $0x0, 0x8(%rax)
jle 0x2821
xorl %r13d, %r13d
movq 0x18(%rax), %rax
movq (%rax,%r13,8), %rax
movsd (%rax,%r12,8), %xmm0
movq %rbx, %rdi
callq 0x2270
movl $0x1, %edx
movq %rax, %rdi
movq %r15, %rsi
callq 0x21e0
incq %r13
movq 0x128(%rsp), %rax
movslq 0x8(%rax), %rcx
cmpq %rcx, %r13
jl 0x27e7
movq 0x368(%rsp), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x21a0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2110
incq %r12
movq 0x128(%rsp), %rax
movslq 0x4(%rax), %rcx
cmpq %rcx, %r12
jl 0x27de
jmp 0x2910
movq 0x120(%rsp), %rax
movq (%rax,%r12,8), %rax
cmpl $0x0, 0x4(%rax)
jle 0x2910
xorl %ebp, %ebp
cmpl $0x0, 0x8(%rax)
jle 0x28c8
xorl %r13d, %r13d
movq 0x10(%rax), %rax
movq (%rax,%r13,8), %rax
movsd (%rax,%rbp,8), %xmm0
movq %rbx, %rdi
callq 0x2270
movl $0x1, %edx
movq %rax, %rdi
movq %r15, %rsi
callq 0x21e0
incq %r13
movq 0x120(%rsp), %rax
movq (%rax,%r12,8), %rax
movslq 0x8(%rax), %rcx
cmpq %rcx, %r13
jl 0x288b
movq 0x368(%rsp), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x21a0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2110
incq %rbp
movq 0x120(%rsp), %rax
movq (%rax,%r12,8), %rax
movslq 0x4(%rax), %rcx
cmpq %rcx, %rbp
jl 0x2882
movq %rbx, %rdi
callq 0x2110
movq %rbx, %rdi
callq 0x2220
movq 0x8(%rsp), %rax
movq %rax, 0x368(%rsp)
movq -0x18(%rax), %rax
movq 0x10(%rsp), %rcx
movq %rcx, 0x368(%rsp,%rax)
leaq 0x370(%rsp), %rdi
callq 0x2170
leaq 0x460(%rsp), %rdi
callq 0x20a0
movq %r14, %r12
cmpq $0x4, %r14
jne 0x2773
movq 0x130(%rsp), %rax
leaq 0x178(%rsp), %r14
movq %rax, -0x8(%r14)
movq %r14, %rdi
leaq 0x138(%rsp), %rsi
callq 0x307e
leaq 0x150(%rsp), %rsi
leaq 0x190(%rsp), %rdi
callq 0x3118
movl 0x168(%rsp), %eax
movl %eax, 0x1a8(%rsp)
leaq 0x618(%rsp), %rdi
leaq 0x2b8(%rsp), %rsi
callq 0x2f66
leaq 0xf8(%rsp), %rdi
leaq 0x170(%rsp), %rsi
leaq 0x618(%rsp), %rdx
callq 0x5836
leaq 0x618(%rsp), %rdi
callq 0x3794
leaq 0x170(%rsp), %rdi
callq 0x4332
leaq 0x18(%rsp), %rdi
movq 0x8(%rdi), %rdx
leaq 0x464b(%rip), %rcx      # 0x7053
movl $0x12, %r8d
xorl %esi, %esi
callq 0x2250
leaq 0x38(%rsp), %rdi
movq 0x8(%rdi), %rdx
leaq 0x4641(%rip), %rcx      # 0x7066
movl $0x12, %r8d
xorl %esi, %esi
callq 0x2250
leaq 0xa8(%rsp), %r14
movq %r14, -0x10(%r14)
movq 0x18(%rsp), %rsi
movq 0x20(%rsp), %rdx
addq %rsi, %rdx
leaq 0x98(%rsp), %rdi
callq 0x32e2
leaq 0x88(%rsp), %r15
movq %r15, -0x10(%r15)
movq 0x38(%rsp), %rsi
movq 0x40(%rsp), %rdx
addq %rsi, %rdx
leaq 0x78(%rsp), %rdi
callq 0x32e2
subq $0x8, %rsp
leaq 0x370(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
leaq 0x80(%rsp), %rdx
leaq 0x60(%rsp), %r9
movsd 0x4564(%rip), %xmm0     # 0x7008
movsd 0x4564(%rip), %xmm1     # 0x7010
movl $0x64, %ecx
xorl %r8d, %r8d
pushq $0xa
pushq $0x3
pushq $0x1
callq 0x3636
addq $0x20, %rsp
movq 0x78(%rsp), %rdi
cmpq %r15, %rdi
je 0x2add
movq 0x88(%rsp), %rsi
incq %rsi
callq 0x21c0
movq 0x98(%rsp), %rdi
cmpq %r14, %rdi
je 0x2afa
movq 0xa8(%rsp), %rsi
incq %rsi
callq 0x21c0
leaq 0x568(%rsp), %rdi
leaq 0x368(%rsp), %rsi
callq 0x2f66
leaq 0x230(%rsp), %rdi
leaq 0x568(%rsp), %rsi
callq 0x37fa
leaq 0x568(%rsp), %rdi
callq 0x3794
xorps %xmm0, %xmm0
xorl %ebx, %ebx
movq $-0x1, %r14
movq 0x7494(%rip), %r15      # 0x9fd8
leaq 0x452e(%rip), %r12      # 0x7079
movslq 0x230(%rsp), %rax
cmpq %rax, %rbx
jge 0x2c8b
movsd %xmm0, 0x10(%rsp)
movslq 0x234(%rsp), %rbp
leaq (,%rbp,8), %rdi
testq %rbp, %rbp
cmovsq %r14, %rdi
callq 0x2030
movq %rax, %r13
testl %ebp, %ebp
jle 0x2bab
movq 0x238(%rsp), %rax
leaq (%rbx,%rbx,2), %rcx
movq (%rax,%rcx,8), %rax
xorl %ecx, %ecx
movsd (%rax,%rcx,8), %xmm0
movsd %xmm0, (%r13,%rcx,8)
incq %rcx
cmpq %rcx, %rbp
jne 0x2b97
movslq 0x35c(%rsp), %rax
leaq (,%rax,8), %rdi
testq %rax, %rax
cmovsq %r14, %rdi
callq 0x2030
movq %rax, %rbp
movq 0x250(%rsp), %rax
cvttsd2si (%rax,%rbx,8), %ecx
leaq 0xf8(%rsp), %rdi
movq %r13, %rsi
movq %rbp, %rdx
callq 0x6278
movsd 0x10(%rsp), %xmm0
movapd %xmm0, %xmm1
addsd 0x441c(%rip), %xmm1     # 0x7018
movsd %xmm1, 0x8(%rsp)
cmpl $0x1, %eax
je 0x2c0d
movsd %xmm0, 0x8(%rsp)
movq %r13, %rdi
callq 0x2210
movq %rbp, %rdi
callq 0x2210
movq %r15, %rdi
movl %ebx, %esi
callq 0x22a0
movq %rax, %r13
movl $0xb, %edx
movq %rax, %rdi
movq %r12, %rsi
callq 0x21e0
incq %rbx
xorps %xmm1, %xmm1
cvtsi2sd %ebx, %xmm1
movsd 0x8(%rsp), %xmm0
divsd %xmm1, %xmm0
movq %r13, %rdi
callq 0x2270
movq %rax, %r13
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r13, %rdi
movl $0xa, %esi
callq 0x21a0
movsbl %al, %esi
movq %r13, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2110
movsd 0x8(%rsp), %xmm0
jmp 0x2b4b
leaq 0x230(%rsp), %rdi
callq 0x4332
leaq 0x368(%rsp), %rdi
callq 0x3794
leaq 0xf8(%rsp), %rdi
callq 0x64a2
leaq 0x130(%rsp), %rdi
callq 0x4332
leaq 0x2b8(%rsp), %rdi
callq 0x3794
movq 0x38(%rsp), %rdi
leaq 0x48(%rsp), %rax
cmpq %rax, %rdi
je 0x2ce8
movq 0x48(%rsp), %rsi
incq %rsi
callq 0x21c0
movq 0x18(%rsp), %rdi
leaq 0x28(%rsp), %rax
cmpq %rax, %rdi
je 0x2d04
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x21c0
xorl %eax, %eax
addq $0x8d8, %rsp            # imm = 0x8D8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
leaq 0x568(%rsp), %rdi
callq 0x3794
jmp 0x2eae
movq %rax, %rbx
jmp 0x2eae
movq %rax, %rbx
movq 0x78(%rsp), %rdi
cmpq %r15, %rdi
je 0x2d57
movq 0x88(%rsp), %rsi
incq %rsi
callq 0x21c0
jmp 0x2d57
movq %rax, %rbx
movq 0x98(%rsp), %rdi
cmpq %r14, %rdi
je 0x2efe
movq 0xa8(%rsp), %rsi
incq %rsi
callq 0x21c0
jmp 0x2efe
jmp 0x2e97
movq %rax, %rbx
leaq 0x618(%rsp), %rdi
callq 0x3794
jmp 0x2d97
movq %rax, %rbx
leaq 0x170(%rsp), %rdi
jmp 0x2dc0
jmp 0x2dca
movq %rax, %rbx
leaq 0x6c8(%rsp), %rdi
callq 0x3794
jmp 0x2db8
movq %rax, %rbx
leaq 0x1b0(%rsp), %rdi
callq 0x4332
jmp 0x2efe
movq %rax, %rbx
movq %r14, %rdi
callq 0x3198
jmp 0x2efe
movq %rax, %rbx
leaq 0x778(%rsp), %rdi
callq 0x3794
jmp 0x2def
movq %rax, %rbx
leaq 0x1f0(%rsp), %rdi
callq 0x4332
jmp 0x2f0b
movq %rax, %rbx
movq %r14, %rdi
callq 0x3198
jmp 0x2f0b
movq %rax, %rbx
jmp 0x2f0b
movq %rax, %rbx
leaq 0x828(%rsp), %rdi
callq 0x3794
jmp 0x2f18
movq %rax, %rbx
jmp 0x2f18
movq %rax, %rbx
movq 0xb8(%rsp), %rdi
cmpq %r15, %rdi
je 0x2e5b
movq 0xc8(%rsp), %rsi
incq %rsi
callq 0x21c0
jmp 0x2e5b
movq %rax, %rbx
movq 0xd8(%rsp), %rdi
cmpq %r14, %rdi
je 0x2f25
movq 0xe8(%rsp), %rsi
incq %rsi
callq 0x21c0
jmp 0x2f25
movq %rax, %rbx
jmp 0x2f25
movq %rax, %rbx
jmp 0x2f41
jmp 0x2e97
jmp 0x2e9e
jmp 0x2e9e
movq %rax, %rbx
jmp 0x2efe
jmp 0x2ec3
movq %rax, %rbx
leaq 0x230(%rsp), %rdi
callq 0x4332
leaq 0x368(%rsp), %rdi
callq 0x3794
jmp 0x2efe
jmp 0x2ec3
jmp 0x2ec3
jmp 0x2ec3
movq %rax, %rbx
movq 0x8(%rsp), %rax
movq %rax, 0x368(%rsp)
movq -0x18(%rax), %rax
movq 0x10(%rsp), %rcx
movq %rcx, 0x368(%rsp,%rax)
leaq 0x370(%rsp), %rdi
callq 0x2170
leaq 0x460(%rsp), %rdi
callq 0x20a0
leaq 0xf8(%rsp), %rdi
callq 0x64a2
leaq 0x130(%rsp), %rdi
callq 0x4332
leaq 0x2b8(%rsp), %rdi
callq 0x3794
movq 0x38(%rsp), %rdi
leaq 0x48(%rsp), %rax
cmpq %rax, %rdi
je 0x2f41
movq 0x48(%rsp), %rsi
incq %rsi
callq 0x21c0
leaq 0x28(%rsp), %rax
movq 0x18(%rsp), %rdi
cmpq %rax, %rdi
je 0x2f5d
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x21c0
movq %rbx, %rdi
callq 0x22b0
nop