// File: /workspace/github_c_makefile_star2_O0/UCLA-StarAI[P]TrimBN/src/trim/search.c
// Function: search_best_subset
SearchResult* search_best_subset(SearchData* data, Fnf* fnf,
      SddCompilerOptions* options) {
  // Compile an unconstrained SDD
  printf("\ncreating manager..."); fflush(stdout);
  SddManager* manager = sdd_manager_create(fnf->var_count,0);
  sdd_manager_set_options(options,manager);
  printf("\ncompiling..."); fflush(stdout);
  SddNode* node = fnf_to_sdd(fnf,manager);
  char* s;  
  printf("\n sdd size               : %s \n",s=ppc(sdd_size(node))); free(s);
  printf(" sdd node count         : %s \n",s=ppc(sdd_count(node))); free(s);
  if(options->minimize_cardinality) {
    printf("\nminimizing cardinality...");
    node = sdd_minimize_cardinality(node,manager);
    printf("size = %zu / node count = %zu\n",sdd_size(node),sdd_count(node));
  }
  sdd_manager_auto_gc_and_minimize_off(manager);
  sdd_ref(node,manager);

  // Move feature variables to make a constrained SDD
  Feature* feature;
  Vtree* vtree = sdd_manager_vtree(manager);
  for (int i = data->num_features-1; i >= 0; i--) {
    feature = data->features[i];
    node = sdd_move_feature_to_pos(node, manager, feature->indicators,
                                   feature->num_indicators, 0, 1);
    // Minimize XY-constrained vtree node so far
    vtree = sdd_manager_vtree(manager);
    for (int j = 0; j < data->num_features - i; j++) {
      vtree = sdd_vtree_right(vtree);
    } // vtree now points to XY-constrained node
    sdd_ref(node,manager);
    sdd_vtree_minimize_limited(vtree,manager);
    sdd_deref(node,manager);
  }
  sdd_deref(node,manager);
  printf(" sdd size           : %s \n", s=ppc(sdd_size(node))); free(s);
  printf(" sdd node count     : %s \n", s=ppc(sdd_count(node))); free(s);

  // Search for an optimal subset using recursive helper func
  sdd_ref(node, manager);

  SearchResult* result = new_search_result(data->num_features);
  char* subset = (char*) calloc(data->num_features, sizeof(char));
  search_best_subset_aux(&node, manager, data, result, 0, subset, 0, 0);
  free(subset);

  sdd_deref(node, manager);

  sdd_manager_free(manager);
  return result;
}

// Assembly:
subq $0x68, %rsp
movq %rdi, 0x60(%rsp)
movq %rsi, 0x58(%rsp)
movq %rdx, 0x50(%rsp)
leaq 0x1f4a6(%rip), %rdi     # 0x24220
movb $0x0, %al
callq 0x20c0
movq 0x26238(%rip), %rax     # 0x2afc0
movq (%rax), %rdi
callq 0x21a0
movq 0x58(%rsp), %rax
movq (%rax), %rdi
xorl %esi, %esi
callq 0x6e10
movq %rax, 0x48(%rsp)
movq 0x50(%rsp), %rdi
movq 0x48(%rsp), %rsi
callq 0x77f0
leaq 0x1f47b(%rip), %rdi     # 0x24235
movb $0x0, %al
callq 0x20c0
movq 0x261f8(%rip), %rax     # 0x2afc0
movq (%rax), %rdi
callq 0x21a0
movq 0x58(%rsp), %rdi
movq 0x48(%rsp), %rsi
callq 0x2ba0
movq %rax, 0x40(%rsp)
movq 0x40(%rsp), %rdi
callq 0x11c20
movq %rax, %rdi
callq 0x6010
movq %rax, %rsi
movq %rsi, 0x38(%rsp)
leaq 0x1f43e(%rip), %rdi     # 0x24243
movb $0x0, %al
callq 0x20c0
movq 0x38(%rsp), %rdi
callq 0x2030
movq 0x40(%rsp), %rdi
callq 0xec50
movq %rax, %rdi
callq 0x6010
movq %rax, %rsi
movq %rsi, 0x38(%rsp)
leaq 0x1f42c(%rip), %rdi     # 0x24263
movb $0x0, %al
callq 0x20c0
movq 0x38(%rsp), %rdi
callq 0x2030
movq 0x50(%rsp), %rax
cmpl $0x0, 0x40(%rax)
je 0x4ea4
leaq 0x1f428(%rip), %rdi     # 0x24282
movb $0x0, %al
callq 0x20c0
movq 0x40(%rsp), %rdi
movq 0x48(%rsp), %rsi
callq 0xe490
movq %rax, 0x40(%rsp)
movq 0x40(%rsp), %rdi
callq 0x11c20
movq %rax, 0x8(%rsp)
movq 0x40(%rsp), %rdi
callq 0xec50
movq 0x8(%rsp), %rsi
movq %rax, %rdx
leaq 0x1f400(%rip), %rdi     # 0x2429d
movb $0x0, %al
callq 0x20c0
movq 0x48(%rsp), %rdi
callq 0x70f0
movq 0x40(%rsp), %rdi
movq 0x48(%rsp), %rsi
callq 0xa950
movq 0x48(%rsp), %rdi
callq 0x7820
movq %rax, 0x28(%rsp)
movq 0x60(%rsp), %rax
movq 0x20(%rax), %rax
subq $0x1, %rax
movl %eax, 0x24(%rsp)
cmpl $0x0, 0x24(%rsp)
jl 0x4fb8
movq 0x60(%rsp), %rax
movq 0x28(%rax), %rax
movslq 0x24(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x30(%rsp)
movq 0x40(%rsp), %rdi
movq 0x48(%rsp), %rsi
movq 0x30(%rsp), %rax
movq (%rax), %rdx
movq 0x30(%rsp), %rax
movq 0x8(%rax), %rcx
xorl %r8d, %r8d
movl $0x1, %r9d
callq 0x3b00
movq %rax, 0x40(%rsp)
movq 0x48(%rsp), %rdi
callq 0x7820
movq %rax, 0x28(%rsp)
movl $0x0, 0x20(%rsp)
movslq 0x20(%rsp), %rax
movq 0x60(%rsp), %rcx
movq 0x20(%rcx), %rcx
movslq 0x24(%rsp), %rdx
subq %rdx, %rcx
cmpq %rcx, %rax
jae 0x4f7b
movq 0x28(%rsp), %rdi
callq 0x78f0
movq %rax, 0x28(%rsp)
movl 0x20(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x20(%rsp)
jmp 0x4f44
movq 0x40(%rsp), %rdi
movq 0x48(%rsp), %rsi
callq 0xa950
movq 0x28(%rsp), %rdi
movq 0x48(%rsp), %rsi
callq 0x9180
movq 0x40(%rsp), %rdi
movq 0x48(%rsp), %rsi
callq 0xaa40
movl 0x24(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x24(%rsp)
jmp 0x4edd
movq 0x40(%rsp), %rdi
movq 0x48(%rsp), %rsi
callq 0xaa40
movq 0x40(%rsp), %rdi
callq 0x11c20
movq %rax, %rdi
callq 0x6010
movq %rax, %rsi
movq %rsi, 0x38(%rsp)
leaq 0x1f2d4(%rip), %rdi     # 0x242bc
movb $0x0, %al
callq 0x20c0
movq 0x38(%rsp), %rdi
callq 0x2030
movq 0x40(%rsp), %rdi
callq 0xec50
movq %rax, %rdi
callq 0x6010
movq %rax, %rsi
movq %rsi, 0x38(%rsp)
leaq 0x1f2bd(%rip), %rdi     # 0x242d7
movb $0x0, %al
callq 0x20c0
movq 0x38(%rsp), %rdi
callq 0x2030
movq 0x40(%rsp), %rdi
movq 0x48(%rsp), %rsi
callq 0xa950
movq 0x60(%rsp), %rax
movq 0x20(%rax), %rdi
callq 0x5e00
movq %rax, 0x18(%rsp)
movq 0x60(%rsp), %rax
movq 0x20(%rax), %rdi
movl $0x1, %esi
callq 0x2110
movq %rax, 0x10(%rsp)
movq 0x48(%rsp), %rsi
movq 0x60(%rsp), %rdx
movq 0x18(%rsp), %rcx
movq 0x10(%rsp), %r9
leaq 0x40(%rsp), %rdi
xorl %r8d, %r8d
xorps %xmm0, %xmm0
movl $0x0, (%rsp)
callq 0x4920
movq 0x10(%rsp), %rdi
callq 0x2030
movq 0x40(%rsp), %rdi
movq 0x48(%rsp), %rsi
callq 0xaa40
movq 0x48(%rsp), %rdi
callq 0x6e90
movq 0x18(%rsp), %rax
addq $0x68, %rsp
retq
nopl (%rax)