// File: /workspace/github_cpp_makefile_star2_O2/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 0x3bbc(%rip), %rsi      # 0x6020
leaq 0x58(%rsp), %rdi
leaq 0x6d8(%rsp), %rdx
callq 0x2bc2
leaq 0x3bb5(%rip), %rsi      # 0x6032
leaq 0x38(%rsp), %rdi
leaq 0x6d8(%rsp), %rdx
callq 0x2bc2
movabsq $0x1f4000001f4, %rax    # imm = 0x1F4000001F4
movq %rax, 0x10(%rsp)
movl $0x384, 0x18(%rsp)      # imm = 0x384
leaq 0x110(%rsp), %rdi
leaq 0x58(%rsp), %rsi
callq 0x2210
leaq 0xf0(%rsp), %rdi
leaq 0x38(%rsp), %rsi
callq 0x2210
subq $0x8, %rsp
leaq 0x2c0(%rsp), %rdi
leaq 0x118(%rsp), %rsi
leaq 0xf8(%rsp), %rdx
pushq $0x64
popq %rcx
leaq 0x18(%rsp), %r9
movsd 0x3b12(%rip), %xmm0     # 0x6008
movsd 0x3b12(%rip), %xmm1     # 0x6010
xorl %r8d, %r8d
pushq $0xa
pushq $0x3
pushq $0x1
callq 0x3232
addq $0x20, %rsp
leaq 0xf0(%rsp), %rdi
callq 0x20d0
leaq 0x110(%rsp), %rdi
callq 0x20d0
leaq 0x628(%rsp), %rdi
leaq 0x2b8(%rsp), %rsi
callq 0x2bfe
leaq 0x130(%rsp), %rdi
leaq 0x628(%rsp), %rsi
callq 0x3376
leaq 0x628(%rsp), %rdi
callq 0x334e
leaq 0x278(%rsp), %rdi
leaq 0x130(%rsp), %rsi
callq 0x2ca4
leaq 0x578(%rsp), %rdi
leaq 0x2b8(%rsp), %rsi
callq 0x2bfe
leaq 0x78(%rsp), %rdi
leaq 0x278(%rsp), %rsi
leaq 0x578(%rsp), %rdx
callq 0x45a6
leaq 0x578(%rsp), %rdi
callq 0x334e
leaq 0x278(%rsp), %rdi
callq 0x3bc8
leaq 0x238(%rsp), %rdi
leaq 0x130(%rsp), %rsi
callq 0x2ca4
leaq 0x4c8(%rsp), %rdi
leaq 0x2b8(%rsp), %rsi
callq 0x2bfe
leaq 0x78(%rsp), %rdi
leaq 0x238(%rsp), %rsi
leaq 0x4c8(%rsp), %rdx
callq 0x472c
leaq 0x4c8(%rsp), %rdi
callq 0x334e
leaq 0x238(%rsp), %rdi
callq 0x3bc8
leaq 0x6d8(%rsp), %r12
leaq 0x3bad(%rip), %r13      # 0x61d9
xorl %ebx, %ebx
cmpq $0x4, %rbx
je 0x2765
movabsq $0x2f6c65646f6d2f2e, %rax # imm = 0x2F6C65646F6D2F2E
movq %rax, 0x20(%rsp)
movw $0x57, 0x28(%rsp)
leaq 0x1(%rbx), %r15
leaq 0x170(%rsp), %r14
movq %r14, %rdi
leaq 0x39ea(%rip), %rsi      # 0x604e
leaq 0x20(%rsp), %rdx
movl %r15d, %ecx
xorl %eax, %eax
callq 0x2040
movq %r12, %rdi
movq %r14, %rsi
pushq $0x10
popq %rdx
callq 0x21d0
cmpq $0x3, %rbx
jne 0x26e4
xorl %ebx, %ebx
movq 0xa8(%rsp), %rax
movslq 0x4(%rax), %rcx
cmpq %rcx, %rbx
jge 0x2745
xorl %r14d, %r14d
movslq 0x8(%rax), %rcx
cmpq %rcx, %r14
jge 0x26d7
movq 0x18(%rax), %rax
movq (%rax,%r14,8), %rax
movsd (%rax,%rbx,8), %xmm0
movq %r12, %rdi
callq 0x2270
movq %rax, %rdi
movq %r13, %rsi
callq 0x21a0
incq %r14
movq 0xa8(%rsp), %rax
jmp 0x26a1
movq %r12, %rdi
callq 0x20e0
incq %rbx
jmp 0x2689
xorl %ebp, %ebp
movq 0xa0(%rsp), %rax
movq (%rax,%rbx,8), %rax
movslq 0x4(%rax), %rcx
cmpq %rcx, %rbp
jge 0x2745
xorl %r14d, %r14d
movslq 0x8(%rax), %rcx
cmpq %rcx, %r14
jge 0x2738
movq 0x10(%rax), %rax
movq (%rax,%r14,8), %rax
movsd (%rax,%rbp,8), %xmm0
movq %r12, %rdi
callq 0x2270
movq %rax, %rdi
movq %r13, %rsi
callq 0x21a0
incq %r14
movq 0xa0(%rsp), %rax
movq (%rax,%rbx,8), %rax
jmp 0x26fe
movq %r12, %rdi
callq 0x20e0
incq %rbp
jmp 0x26e6
movq %r12, %rdi
callq 0x2110
movq %r12, %rdi
callq 0x2220
movq %r12, %rdi
callq 0x2240
movq %r15, %rbx
jmp 0x262e
leaq 0x1f8(%rsp), %rdi
leaq 0x130(%rsp), %rsi
callq 0x2ca4
leaq 0x418(%rsp), %rdi
leaq 0x2b8(%rsp), %rsi
callq 0x2bfe
leaq 0x78(%rsp), %rdi
leaq 0x1f8(%rsp), %rsi
leaq 0x418(%rsp), %rdx
callq 0x4d70
leaq 0x418(%rsp), %rdi
callq 0x334e
leaq 0x1f8(%rsp), %rdi
callq 0x3bc8
leaq 0x3889(%rip), %rsi      # 0x6053
leaq 0x58(%rsp), %rdi
callq 0x22f0
leaq 0x388b(%rip), %rsi      # 0x6066
leaq 0x38(%rsp), %rdi
callq 0x22f0
leaq 0xd0(%rsp), %rdi
leaq 0x58(%rsp), %rsi
callq 0x2210
leaq 0xb0(%rsp), %rdi
leaq 0x38(%rsp), %rsi
callq 0x2210
subq $0x8, %rsp
leaq 0x6e0(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
leaq 0xb8(%rsp), %rdx
pushq $0x64
popq %rcx
leaq 0x18(%rsp), %r9
movsd 0x37d3(%rip), %xmm0     # 0x6008
movsd 0x37d3(%rip), %xmm1     # 0x6010
xorl %r8d, %r8d
pushq $0xa
pushq $0x3
pushq $0x1
callq 0x3232
addq $0x20, %rsp
leaq 0xb0(%rsp), %rdi
callq 0x20d0
leaq 0xd0(%rsp), %rdi
callq 0x20d0
leaq 0x368(%rsp), %rdi
leaq 0x6d8(%rsp), %rsi
callq 0x2bfe
leaq 0x170(%rsp), %rdi
leaq 0x368(%rsp), %rsi
callq 0x3376
leaq 0x368(%rsp), %rdi
callq 0x334e
xorps %xmm0, %xmm0
pushq $-0x1
popq %rbx
movq 0x672b(%rip), %r14      # 0x8fd8
leaq 0x37c5(%rip), %r15      # 0x6079
xorl %r12d, %r12d
movslq 0x170(%rsp), %rax
cmpq %rax, %r12
jge 0x29d1
movsd %xmm0, 0x30(%rsp)
movslq 0x174(%rsp), %rbp
leaq (,%rbp,8), %rdi
testq %rbp, %rbp
cmovsq %rbx, %rdi
callq 0x2030
movq %rax, %r13
imulq $0x18, %r12, %rax
addq 0x178(%rsp), %rax
testl %ebp, %ebp
movl $0x0, %ecx
cmovlel %ecx, %ebp
xorl %ecx, %ecx
cmpq %rcx, %rbp
je 0x291e
movq (%rax), %rdx
movsd (%rdx,%rcx,8), %xmm0
movsd %xmm0, (%r13,%rcx,8)
incq %rcx
jmp 0x2905
movslq 0x35c(%rsp), %rax
leaq (,%rax,8), %rdi
testq %rax, %rax
cmovsq %rbx, %rdi
callq 0x2030
movq %rax, %rbp
movq 0x190(%rsp), %rax
cvttsd2si (%rax,%r12,8), %ecx
leaq 0x78(%rsp), %rdi
movq %r13, %rsi
movq %rbp, %rdx
callq 0x55e4
movsd 0x30(%rsp), %xmm0
movapd %xmm0, %xmm1
addsd 0x36ab(%rip), %xmm1     # 0x6018
movsd %xmm1, 0x8(%rsp)
cmpl $0x1, %eax
je 0x297e
movsd %xmm0, 0x8(%rsp)
movq %r13, %rdi
callq 0x2200
movq %rbp, %rdi
callq 0x2200
movq %r14, %rdi
movl %r12d, %esi
callq 0x22a0
movq %rax, %rdi
movq %r15, %rsi
callq 0x21a0
incq %r12
cvtsi2sd %r12d, %xmm1
movsd 0x8(%rsp), %xmm0
divsd %xmm1, %xmm0
movq %rax, %rdi
callq 0x2270
movq %rax, %rdi
callq 0x20e0
movsd 0x8(%rsp), %xmm0
jmp 0x28b7
leaq 0x170(%rsp), %rdi
callq 0x3bc8
leaq 0x6d8(%rsp), %rdi
callq 0x334e
leaq 0x78(%rsp), %rdi
callq 0x57c0
leaq 0x130(%rsp), %rdi
callq 0x3bc8
leaq 0x2b8(%rsp), %rdi
callq 0x334e
leaq 0x38(%rsp), %rdi
callq 0x20d0
leaq 0x58(%rsp), %rdi
callq 0x20d0
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 0x368(%rsp), %rdi
callq 0x334e
jmp 0x2b5d
movq %rax, %rbx
jmp 0x2b5d
movq %rax, %rbx
leaq 0xb0(%rsp), %rdi
callq 0x20d0
jmp 0x2a69
movq %rax, %rbx
leaq 0xd0(%rsp), %rdi
callq 0x20d0
jmp 0x2b82
jmp 0x2b46
movq %rax, %rbx
leaq 0x418(%rsp), %rdi
callq 0x334e
jmp 0x2a95
movq %rax, %rbx
leaq 0x1f8(%rsp), %rdi
jmp 0x2abc
movq %rax, %rbx
leaq 0x4c8(%rsp), %rdi
callq 0x334e
jmp 0x2ab4
movq %rax, %rbx
leaq 0x238(%rsp), %rdi
callq 0x3bc8
jmp 0x2b82
movq %rax, %rbx
leaq 0x578(%rsp), %rdi
callq 0x334e
jmp 0x2adb
movq %rax, %rbx
leaq 0x278(%rsp), %rdi
callq 0x3bc8
jmp 0x2b8c
movq %rax, %rbx
jmp 0x2b8c
movq %rax, %rbx
leaq 0x628(%rsp), %rdi
callq 0x334e
jmp 0x2b99
movq %rax, %rbx
jmp 0x2b99
movq %rax, %rbx
leaq 0xf0(%rsp), %rdi
callq 0x20d0
jmp 0x2b27
movq %rax, %rbx
leaq 0x110(%rsp), %rdi
callq 0x20d0
jmp 0x2ba6
movq %rax, %rbx
jmp 0x2ba6
movq %rax, %rbx
jmp 0x2bb0
jmp 0x2b46
jmp 0x2b4d
jmp 0x2b4d
movq %rax, %rbx
jmp 0x2b82
jmp 0x2b72
movq %rax, %rbx
leaq 0x170(%rsp), %rdi
callq 0x3bc8
leaq 0x6d8(%rsp), %rdi
callq 0x334e
jmp 0x2b82
jmp 0x2b72
jmp 0x2b72
jmp 0x2b72
movq %rax, %rbx
leaq 0x6d8(%rsp), %rdi
callq 0x2240
leaq 0x78(%rsp), %rdi
callq 0x57c0
leaq 0x130(%rsp), %rdi
callq 0x3bc8
leaq 0x2b8(%rsp), %rdi
callq 0x334e
leaq 0x38(%rsp), %rdi
callq 0x20d0
leaq 0x58(%rsp), %rdi
callq 0x20d0
movq %rbx, %rdi
callq 0x22b0