Example #1
0
static inline void instance__print_coords_to_log(
    fcs_dbm_solver_instance_t *const instance, FILE *const log_fh)
{
    const fcs_dbm_variant_type_t local_variant = instance->local_variant;
    fprintf(
        log_fh, "At %ld iterations Coords=[", instance->count_num_processed);

    const pseduo_dfs_stack_item_t *stack_item = instance->stack;
    const pseduo_dfs_stack_item_t *const end_stack_item =
        stack_item + instance->stack_depth;
    for (; stack_item <= end_stack_item; stack_item++)
    {
        fprintf(log_fh, "%d,", stack_item->next_state_idx);
    }

#if 1
    {

        fcs_state_locs_struct_t locs;
        fc_solve_init_locs(&locs);
        char state_as_string[2000];
        FCS__RENDER_STATE(
            state_as_string, &(end_stack_item->curr_state->s), &locs);
        printf("Found State=<<'STATE'\n%s\nSTATE\n\n", state_as_string);
        fflush(stdout);
    }
#endif

    fprintf(log_fh, "]\n");
}
Example #2
0
// The char * returned is malloc()ed and should be free()ed.
DLLEXPORT char *fc_solve_user_INTERNAL_delta_states_enc_and_dec(
    const fcs_dbm_variant_type local_variant GCC_UNUSED,
    const char *const init_state_s, const char *const derived_state_s)
{
    fcs_state_keyval_pair init_state, derived_state, new_derived_state;
    fcs_uchar enc_state[24];
    fcs_bit_reader bit_r;
    fcs_state_locs_struct locs;
    fc_solve_init_locs(&locs);

    DECLARE_IND_BUF_T(indirect_stacks_buffer)
    DECLARE_IND_BUF_T(derived_stacks_buffer)
    DECLARE_IND_BUF_T(new_derived_indirect_stacks_buffer)

    fc_solve_initial_user_state_to_c(init_state_s, &init_state, FREECELLS_NUM,
        STACKS_NUM, DECKS_NUM, indirect_stacks_buffer);

    fc_solve_initial_user_state_to_c(derived_state_s, &derived_state,
        FREECELLS_NUM, STACKS_NUM, DECKS_NUM, derived_stacks_buffer);

    fcs_delta_stater delta;
    fc_solve_delta_stater_init(&delta, local_variant, &(init_state.s),
        STACKS_NUM,
        FREECELLS_NUM PASS_ON_NOT_FC_ONLY(FCS_SEQ_BUILT_BY_ALTERNATE_COLOR));

    fc_solve_delta_stater_set_derived(&delta, &(derived_state.s));

    fc_solve_state_init(
        &new_derived_state, STACKS_NUM, new_derived_indirect_stacks_buffer);

    fc_solve_bit_writer bit_w;
    fc_solve_bit_writer_init(&bit_w, enc_state);
    fc_solve_delta_stater_encode_composite(&delta, &bit_w);

    fc_solve_bit_reader_init(&bit_r, enc_state);
    fc_solve_delta_stater_decode(&delta, &bit_r, &(new_derived_state.s));

    char *new_derived_as_str = SMALLOC(new_derived_as_str, 1000);
    FCS__RENDER_STATE(new_derived_as_str, &(new_derived_state.s), &locs);

    fc_solve_delta_stater_release(&delta);
    return new_derived_as_str;
}
/*
 * The char * returned is malloc()ed and should be free()ed.
 */
DLLEXPORT int fc_solve_user_INTERNAL_perform_horne_prune(
        enum fcs_dbm_variant_type_t local_variant,
        const char * init_state_str_proto,
        char * * ret_state_s
        )
{
    fcs_state_keyval_pair_t init_state;
    fcs_state_locs_struct_t locs;
    int prune_ret;

    DECLARE_IND_BUF_T(indirect_stacks_buffer)

    fc_solve_init_locs(&locs);

    fc_solve_initial_user_state_to_c(
            init_state_str_proto,
            &init_state,
            FREECELLS_NUM,
            STACKS_NUM,
            DECKS_NUM,
            indirect_stacks_buffer
            );

    {
        fcs_which_moves_bitmask_t which_no_use = {{'\0'}};
        prune_ret = horne_prune(local_variant, &init_state, &which_no_use, NULL, NULL);
    }
    *ret_state_s =
        fc_solve_state_as_string(
            &(init_state.s),
            &locs,
            FREECELLS_NUM,
            STACKS_NUM,
            DECKS_NUM,
            1,
            0,
            1
            );

    return prune_ret;
}
/*
 * The char * returned is malloc()ed and should be free()ed.
 */
DLLEXPORT int fc_solve_user_INTERNAL_calc_derived_states_wrapper(
        enum fcs_dbm_variant_type_t local_variant,
        const char * init_state_str_proto,
        int * const num_out_derived_states,
        fcs_derived_state_debug_t * * out_derived_states,
        const fcs_bool_t perform_horne_prune
        )
{
    fcs_state_keyval_pair_t init_state;
    fc_solve_delta_stater_t * delta;
    fcs_encoded_state_buffer_t enc_state;
    fcs_state_locs_struct_t locs;
    fcs_derived_state_t * derived_list = NULL;
    fcs_derived_state_t * derived_list_recycle_bin = NULL;
    fcs_compact_allocator_t allocator;
    fcs_meta_compact_allocator_t meta_alloc;
    int states_count = 0;
    fcs_derived_state_t * iter;
    fcs_derived_state_debug_t * debug_ret;
    int idx = 0;

    DECLARE_IND_BUF_T(indirect_stacks_buffer)

    fc_solve_initial_user_state_to_c(
            init_state_str_proto,
            &init_state,
            FREECELLS_NUM,
            STACKS_NUM,
            DECKS_NUM,
            indirect_stacks_buffer
            );

    delta = fc_solve_delta_stater_alloc(
            &(init_state.s),
            STACKS_NUM,
            FREECELLS_NUM
#ifndef FCS_FREECELL_ONLY
            , FCS_SEQ_BUILT_BY_ALTERNATE_COLOR
#endif
            );

    fcs_init_and_encode_state(
        delta,
        local_variant,
        &(init_state),
        &enc_state
        );

    fc_solve_meta_compact_allocator_init (&meta_alloc);
    fc_solve_compact_allocator_init( &allocator, &meta_alloc);

    instance_solver_thread_calc_derived_states(
        local_variant,
        &init_state,
        NULL,
        &derived_list,
        &derived_list_recycle_bin,
        &allocator,
        perform_horne_prune
    );


    iter = derived_list;

    while (iter)
    {
        states_count++;
        iter = iter->next;
    }

    *(num_out_derived_states) = states_count;


    debug_ret = SMALLOC(debug_ret, states_count);

    *(out_derived_states) = debug_ret;

    fc_solve_init_locs(&locs);

    iter = derived_list;
    while (iter)
    {
        debug_ret[idx].state_string =
        fc_solve_state_as_string(
            &(iter->state.s),
            &locs,
            FREECELLS_NUM,
            STACKS_NUM,
            DECKS_NUM,
            1,
            0,
            1
            );
        debug_ret[idx].move = iter->move;
        debug_ret[idx].core_irreversible_moves_count
            = iter->core_irreversible_moves_count;
        debug_ret[idx].num_non_reversible_moves_including_prune
            = iter->num_non_reversible_moves_including_prune;
        /* TODO : Put something meaningful there by passing it to the function. */
        debug_ret[idx].which_irreversible_moves_bitmask =
            iter->which_irreversible_moves_bitmask;
        idx++;
        iter = iter->next;
    }

    assert(idx == states_count);

    fc_solve_compact_allocator_finish(&allocator);
    fc_solve_meta_compact_allocator_finish( &meta_alloc );

    fc_solve_delta_stater_free (delta);

    return 0;
}
Example #5
0
/*
 * The char * returned is malloc()ed and should be free()ed.
 */
DLLEXPORT int fc_solve_user_INTERNAL_calc_derived_states_wrapper(
    fcs_dbm_variant_type_t local_variant, const char *init_state_str_proto,
    int *const num_out_derived_states,
    fcs_derived_state_debug_t **out_derived_states,
    const fcs_bool_t perform_horne_prune)
{
    fcs_state_keyval_pair_t init_state;
    fcs_encoded_state_buffer_t enc_state;
    fcs_state_locs_struct_t locs;
    fcs_derived_state_t *derived_list = NULL;
    fcs_derived_state_t *derived_list_recycle_bin = NULL;
    fcs_compact_allocator_t allocator;
    fcs_meta_compact_allocator_t meta_alloc;
    size_t states_count = 0;
    fcs_derived_state_t *iter;
    DECLARE_IND_BUF_T(indirect_stacks_buffer)

    fc_solve_initial_user_state_to_c(init_state_str_proto, &init_state,
        FREECELLS_NUM, STACKS_NUM, DECKS_NUM, indirect_stacks_buffer);

    fc_solve_delta_stater_t delta;
    fc_solve_delta_stater_init(
        &delta, &(init_state.s), STACKS_NUM, FREECELLS_NUM
#ifndef FCS_FREECELL_ONLY
        ,
        FCS_SEQ_BUILT_BY_ALTERNATE_COLOR
#endif
        );

    fcs_init_and_encode_state(&delta, local_variant, &(init_state), &enc_state);

    fc_solve_meta_compact_allocator_init(&meta_alloc);
    fc_solve_compact_allocator_init(&allocator, &meta_alloc);

    instance_solver_thread_calc_derived_states(local_variant, &init_state, NULL,
        &derived_list, &derived_list_recycle_bin, &allocator,
        perform_horne_prune);

    iter = derived_list;

    while (iter)
    {
        states_count++;
        iter = iter->next;
    }

    *(num_out_derived_states) = states_count;

    fcs_derived_state_debug_t *const debug_ret =
        SMALLOC(debug_ret, states_count);
    *(out_derived_states) = debug_ret;

    fc_solve_init_locs(&locs);

    iter = derived_list;
    size_t idx = 0;
    while (iter)
    {
        debug_ret[idx] = (typeof(debug_ret[idx])){
            .state_string = SMALLOC(debug_ret[idx].state_string, 1000),
            .move = iter->move,
            .core_irreversible_moves_count =
                iter->core_irreversible_moves_count,
            .num_non_reversible_moves_including_prune =
                iter->num_non_reversible_moves_including_prune,
            .which_irreversible_moves_bitmask =
                iter->which_irreversible_moves_bitmask};
        FCS__RENDER_STATE(debug_ret[idx].state_string, &(iter->state.s), &locs);
        /* TODO : Put something meaningful there by passing it to the function.
         */
        idx++;
        iter = iter->next;
    }

    assert(idx == states_count);

    fc_solve_compact_allocator_finish(&allocator);
    fc_solve_meta_compact_allocator_finish(&meta_alloc);

    fc_solve_delta_stater_release(&delta);

    return 0;
}

/*
 * The char * returned is malloc()ed and should be free()ed.
 */
DLLEXPORT int fc_solve_user_INTERNAL_perform_horne_prune(
    fcs_dbm_variant_type_t local_variant, const char *init_state_str_proto,
    char **ret_state_s)
{
    fcs_state_keyval_pair_t init_state;
    fcs_state_locs_struct_t locs;
    int prune_ret;

    DECLARE_IND_BUF_T(indirect_stacks_buffer)

    fc_solve_init_locs(&locs);

    fc_solve_initial_user_state_to_c(init_state_str_proto, &init_state,
        FREECELLS_NUM, STACKS_NUM, DECKS_NUM, indirect_stacks_buffer);

    prune_ret = horne_prune__simple(local_variant, &init_state);
    *ret_state_s = SMALLOC(*ret_state_s, 1000);
    FCS__RENDER_STATE(*ret_state_s, &(init_state.s), &locs);

    return prune_ret;
}
/*
 * The char * returned is malloc()ed and should be free()ed.
 */
DLLEXPORT int fc_solve_user_INTERNAL_find_fcc_start_points(
        enum fcs_dbm_variant_type_t local_variant,
        const char * init_state_str_proto,
        const int start_state_moves_count,
        const fcs_fcc_move_t * const start_state_moves,
        fcs_FCC_start_point_result_t * * out_fcc_start_points,
        long * out_num_new_positions
        )
{
    fcs_state_keyval_pair_t init_state;
    fc_solve_delta_stater_t * delta;
    fcs_encoded_state_buffer_t enc_state;
    fcs_state_locs_struct_t locs;
    int i;
    fcs_meta_compact_allocator_t meta_alloc;
    fcs_FCC_start_points_list_t start_points_list;
    dict_t * do_next_fcc_start_points_exist;
    dict_t * does_min_by_sorting_exist;
    fcs_lru_cache_t does_state_exist_in_any_FCC_cache;
    const int max_num_elements_in_cache = 1000;
    fcs_bool_t is_min_by_sorting_new;
    fcs_encoded_state_buffer_t min_by_sorting;
    fcs_fcc_moves_seq_allocator_t moves_list_allocator;
    fcs_fcc_moves_seq_t start_state_moves_seq;
    int states_count = 0;
    fcs_FCC_start_point_t * iter;
    fcs_FCC_start_point_result_t * ret;
    add_start_point_context_t add_start_point_context;
    void * tree_recycle_bin = NULL;

    fcs_compact_allocator_t moves_list_compact_alloc;

    DECLARE_IND_BUF_T(indirect_stacks_buffer)

    fc_solve_initial_user_state_to_c(
            init_state_str_proto,
            &init_state,
            FREECELLS_NUM,
            STACKS_NUM,
            DECKS_NUM,
            indirect_stacks_buffer
            );

    delta = fc_solve_delta_stater_alloc(
            &(init_state.s),
            STACKS_NUM,
            FREECELLS_NUM
#ifndef FCS_FREECELL_ONLY
            , FCS_SEQ_BUILT_BY_ALTERNATE_COLOR
#endif
            );

    fcs_init_and_encode_state(
        delta,
        local_variant,
        &(init_state),
        &enc_state
    );

    start_points_list.list = NULL;
    start_points_list.recycle_bin = NULL;
    fc_solve_meta_compact_allocator_init( &meta_alloc );
    fc_solve_compact_allocator_init(&(start_points_list.allocator), &meta_alloc);

    do_next_fcc_start_points_exist =
        fc_solve_kaz_tree_create(fc_solve_compare_encoded_states, NULL, &meta_alloc, &tree_recycle_bin);

    does_min_by_sorting_exist =
        fc_solve_kaz_tree_create(fc_solve_compare_encoded_states, NULL, &meta_alloc, &tree_recycle_bin);

    cache_init(&does_state_exist_in_any_FCC_cache, max_num_elements_in_cache, &meta_alloc);

    fc_solve_compact_allocator_init(&(moves_list_compact_alloc), &(meta_alloc));

    moves_list_allocator.recycle_bin = NULL;
    moves_list_allocator.allocator = &(moves_list_compact_alloc);

    start_state_moves_seq.count = start_state_moves_count;
    start_state_moves_seq.moves_list = NULL;
    {
        fcs_fcc_moves_list_item_t * * moves_iter = &(start_state_moves_seq.moves_list);
        for ( i=0 ; i < start_state_moves_count ; )
        {
            if (i % FCS_FCC_NUM_MOVES_IN_ITEM == 0)
            {
                *(moves_iter) = fc_solve_fcc_alloc_moves_list_item(&moves_list_allocator);
            }
            (*moves_iter)->data.s[i % FCS_FCC_NUM_MOVES_IN_ITEM] = start_state_moves[i];
            if ((++i) % FCS_FCC_NUM_MOVES_IN_ITEM == 0)
            {
                moves_iter = &((*moves_iter)->next);
            }
        }
    }

    add_start_point_context.do_next_fcc_start_points_exist = do_next_fcc_start_points_exist;
    add_start_point_context.next_start_points_list = &start_points_list;
    add_start_point_context.moves_list_allocator = &moves_list_allocator;

    perform_FCC_brfs(
        local_variant,
        &(init_state),
        enc_state,
        &start_state_moves_seq,
        fc_solve_add_start_point_in_mem,
        &add_start_point_context,
        &is_min_by_sorting_new,
        &min_by_sorting,
        does_min_by_sorting_exist,
        &does_state_exist_in_any_FCC_cache,
        out_num_new_positions,
        &moves_list_allocator,
        &meta_alloc
    );

    iter = start_points_list.list;

    while (iter)
    {
        states_count++;
        iter = iter->next;
    }

    *out_fcc_start_points = ret = SMALLOC(ret, states_count+1);

    ret[states_count].count = 0;

    fc_solve_init_locs(&locs);

    iter = start_points_list.list;
    for (i = 0; i < states_count ; i++)
    {
        fcs_state_keyval_pair_t state;
        DECLARE_IND_BUF_T(state_indirect_stacks_buffer)

        ret[i].count = iter->moves_seq.count;
        ret[i].moves = SMALLOC(ret[i].moves, ret[i].count);
        {
            int moves_idx;
            fcs_fcc_moves_list_item_t * moves_iter = iter->moves_seq.moves_list;
            for (moves_idx = 0 ; moves_idx < ret[i].count ; )
            {
                ret[i].moves[moves_idx] = moves_iter->data.s[moves_idx % FCS_FCC_NUM_MOVES_IN_ITEM];
                if ((++moves_idx) % FCS_FCC_NUM_MOVES_IN_ITEM == 0)
                {
                    moves_iter = moves_iter->next;
                }
            }
        }
        fc_solve_delta_stater_decode_into_state(delta, iter->enc_state.s, &(state), state_indirect_stacks_buffer);
        ret[i].state_as_string =
        fc_solve_state_as_string(
            &(state.s),
            &locs,
            FREECELLS_NUM,
            STACKS_NUM,
            DECKS_NUM,
            1,
            0,
            1
            );

        iter = iter->next;
    }

    fc_solve_compact_allocator_finish(&(start_points_list.allocator));
    fc_solve_compact_allocator_finish(&(moves_list_compact_alloc));

    fc_solve_delta_stater_free (delta);
    fc_solve_kaz_tree_destroy(do_next_fcc_start_points_exist);
    fc_solve_kaz_tree_destroy(does_min_by_sorting_exist);
    cache_destroy(&does_state_exist_in_any_FCC_cache);
    fc_solve_meta_compact_allocator_finish( &meta_alloc );

    return 0;
}
Example #7
0
static inline void instance_check_key(fcs_dbm_solver_thread_t *const thread,
    fcs_dbm_solver_instance_t *const instance, const int key_depth,
    fcs_encoded_state_buffer_t *const key, fcs_dbm_record_t *const parent,
    const unsigned char move GCC_UNUSED,
    const fcs_which_moves_bitmask_t *const which_irreversible_moves_bitmask
#ifdef FCS_DBM_CACHE_ONLY
    ,
    const fcs_fcc_move_t *moves_to_parent
#endif
    )
{
#ifdef DEBUG_OUT
    fcs_state_locs_struct_t locs;
    fc_solve_init_locs(&locs);
    const_AUTO(local_variant, instance->common.variant);
#endif
    const_AUTO(coll, &(instance->coll));
    {
#ifdef FCS_DBM_WITHOUT_CACHES
        fcs_dbm_record_t *token;
#else
        fcs_dbm_record_t *token = key;
#endif
#ifndef FCS_DBM_WITHOUT_CACHES
        if (cache_does_key_exist(&(coll->cache_store.cache), key))
        {
            return;
        }
#ifndef FCS_DBM_CACHE_ONLY
        else if (pre_cache_does_key_exist(&(coll->cache_store.pre_cache), key))
        {
            return;
        }
#endif
#ifndef FCS_DBM_CACHE_ONLY
        else if (fc_solve_dbm_store_does_key_exist(
                     coll->cache_store.store, key->s))
        {
            cache_insert(&(coll->cache_store.cache), key, NULL, '\0');
            return;
        }
#endif
        else
#else
        if ((token = fc_solve_dbm_store_insert_key_value(
                 coll->cache_store.store, key, parent, TRUE)))
#endif
        {
#ifdef FCS_DBM_CACHE_ONLY
            fcs_cache_key_info_t *cache_key;
#endif

#ifndef FCS_DBM_WITHOUT_CACHES
#ifndef FCS_DBM_CACHE_ONLY
            pre_cache_insert(&(coll->cache_store.pre_cache), key, parent);
#else
            cache_key = cache_insert(
                &(coll->cache_store.cache), key, moves_to_parent, move);
#endif
#endif

            if (key_depth == instance->curr_depth)
            {
                /* Now insert it into the queue. */
                fcs_lock_lock(&instance->global_lock);

                fcs_depth_multi_queue__insert(
                    &(coll->depth_queue), thread->state_depth + 1,
#ifdef FCS_DBM_WITHOUT_CACHES
                    (const fcs_offloading_queue_item_t *)(&token)
#else
                    key
#endif
                        );

                instance->common.count_of_items_in_queue++;
                instance->common.num_states_in_collection++;

                instance_debug_out_state(instance, &(token->key));

                fcs_lock_unlock(&instance->global_lock);
            }
            else
            {
                /* Handle an irreversible move */

                /* Calculate the new fingerprint to which the exit
                 * point belongs. */
                fcs_which_moves_bitmask_t new_fingerprint = {{'\0'}};
                for (size_t i = 0; i < COUNT(new_fingerprint.s); i++)
                {
                    new_fingerprint.s[i] =
                        which_irreversible_moves_bitmask->s[i] +
                        instance->fingerprint_which_irreversible_moves_bitmask
                            .s[i];
                }
                int trace_num;
                fcs_encoded_state_buffer_t *trace;
                fcs_lock_lock(&instance->fcc_exit_points_output_lock);
                /* instance->storage_lock is already locked
                 * in instance_check_multiple_keys and we should not
                 * lock it here. */
                calc_trace(token, &trace, &trace_num);
                {
                    FccEntryPointNode fcc_entry_key;
                    fcc_entry_key.kv.key.key = trace[trace_num - 1];
                    FccEntryPointNode *val_proto = RB_FIND(FccEntryPointList,
                        &(instance->fcc_entry_points), &fcc_entry_key);
                    const long location_in_file =
                        val_proto->kv.val.location_in_file;
                    fseek(instance->fingerprint_fh, location_in_file, SEEK_SET);

#ifdef HAVE_GETLINE
                    getline(&(instance->fingerprint_line),
                        &(instance->fingerprint_line_size),
                        instance->fingerprint_fh);
#else
                    fgets(instance->fingerprint_line,
                        instance->fingerprint_line_size,
                        instance->fingerprint_fh);
#endif
                    char *const moves_to_state_enc =
                        strchr(
                            strchr(instance->fingerprint_line, ' ') + 1, ' ') +
                        1;
                    char *const trailing_newline =
                        strchr(moves_to_state_enc, '\n');
                    if (trailing_newline)
                    {
                        *trailing_newline = '\0';
                    }
                    const size_t string_len = strlen(moves_to_state_enc);
                    instance_alloc_num_moves(
                        instance, ((string_len * 3) >> 2) + 20);
                    base64_decode(moves_to_state_enc, string_len,
                        ((unsigned char *)instance->moves_to_state),
                        &(instance->moves_to_state_len));
                }

                const_SLOT(moves_to_state_len, instance);
                const size_t added_moves_to_output =
                    moves_to_state_len + trace_num - 1;
                instance_alloc_num_moves(instance, added_moves_to_output);
                unsigned char *const moves_to_state = instance->moves_to_state;
                for (int i = trace_num - 1; i > 0; i--)
                {
                    moves_to_state[moves_to_state_len + trace_num - 1 - i] =
                        get_move_from_parent_to_child(instance,
                            &(thread->delta_stater), trace[i], trace[i - 1]);
                }

                const size_t new_max_enc_len =
                    ((added_moves_to_output * 4) / 3) + 20;

                if (new_max_enc_len >
                    instance->moves_base64_encoding_buffer_max_len)
                {
                    instance->moves_base64_encoding_buffer =
                        SREALLOC(instance->moves_base64_encoding_buffer,
                            new_max_enc_len);
                    instance->moves_base64_encoding_buffer_max_len =
                        new_max_enc_len;
                }

                size_t unused_output_len;
                base64_encode(moves_to_state, added_moves_to_output,
                    instance->moves_base64_encoding_buffer, &unused_output_len);
                char fingerprint_base64[100];
                char state_base64[100];
                base64_encode(new_fingerprint.s, sizeof(new_fingerprint),
                    fingerprint_base64, &unused_output_len);
                base64_encode((unsigned char *)&(*key), sizeof(*key),
                    state_base64, &unused_output_len);
                /* Output the exit point. */
                fprintf(instance->fcc_exit_points_out_fh, "%s %s %zd %s\n",
                    fingerprint_base64, state_base64, added_moves_to_output,
                    instance->moves_base64_encoding_buffer);
#ifdef DEBUG_OUT
                {
                    fcs_state_keyval_pair_t state;
                    DECLARE_IND_BUF_T(indirect_stacks_buffer)
                    fc_solve_delta_stater_decode_into_state(
                        &(thread->delta_stater), key->s, &state,
                        indirect_stacks_buffer);
                    char state_str[2000];
                    FCS__RENDER_STATE(state_str, &(state.s), &locs);
                    fprintf(stderr,
                        "Check Key: <<<\n%s\n>>>\n\n[%s %s %ld %s]\n\n",
                        state_str, fingerprint_base64, state_base64,
                        added_moves_to_output,
                        instance->moves_base64_encoding_buffer);
                }
#endif
                fflush(instance->fcc_exit_points_out_fh);

                fcs_lock_unlock(&instance->fcc_exit_points_output_lock);

                free(trace);
            }
        }
    }
Example #8
0
static void *instance_run_solver_thread(void *const void_arg)
{
    fcs_dbm_queue_item_t physical_item;
    fcs_dbm_record_t *token = NULL;
    fcs_dbm_queue_item_t *item, *prev_item;
    fcs_derived_state_t *derived_list, *derived_list_recycle_bin, *derived_iter;
    fcs_compact_allocator_t derived_list_allocator;
    fcs_state_keyval_pair_t state;
    char *base64_encoding_buffer = NULL;
#if 0
    size_t base64_encoding_buffer_max_len = 0;
#endif

#ifdef DEBUG_OUT
    fcs_state_locs_struct_t locs;
    fc_solve_init_locs(&locs);
#endif
    DECLARE_IND_BUF_T(indirect_stacks_buffer)

    const_AUTO(thread, ((thread_arg_t *)void_arg)->thread);
    const_SLOT(instance, thread);
    const_AUTO(delta_stater, &(thread->delta_stater));
    const_AUTO(local_variant, instance->common.variant);

    prev_item = item = NULL;
    int queue_num_extracted_and_processed = 0;
    fc_solve_compact_allocator_init(
        &(derived_list_allocator), &(thread->thread_meta_alloc));
    derived_list_recycle_bin = NULL;
    derived_list = NULL;
    FILE *const out_fh = instance->common.out_fh;
    TRACE("%s\n", "instance_run_solver_thread start");
    const_AUTO(coll, &(instance->coll));
#if 0
    fcs_bool_t was_start_key_reachable = instance->was_start_key_reachable;
#endif
    while (1)
    {
        /* First of all extract an item. */
        fcs_lock_lock(&instance->global_lock);

        if (prev_item)
        {
            instance->common.queue_num_extracted_and_processed--;
        }

        if (instance->common.should_terminate == DONT_TERMINATE)
        {
            if (fcs_depth_multi_queue__extract(&(coll->depth_queue),
                    &(thread->state_depth),
                    (fcs_offloading_queue_item_t *)(&token)))
            {
                physical_item.key = token->key;
                item = &physical_item;
                instance_increment(instance);
            }
            else
            {
                item = NULL;
            }

            queue_num_extracted_and_processed =
                instance->common.queue_num_extracted_and_processed;
        }
        fcs_lock_unlock(&instance->global_lock);

        if ((instance->common.should_terminate != DONT_TERMINATE) ||
            (!queue_num_extracted_and_processed))
        {
            break;
        }

        if (!item)
        {
            /* Sleep until more items become available in the
             * queue. */
            usleep(5000);
        }
        else
        {
            /* Handle item. */
            fc_solve_delta_stater_decode_into_state(
                delta_stater, item->key.s, &state, indirect_stacks_buffer);

            /* A section for debugging. */
            FCS__OUTPUT_STATE(out_fh, "", &(state.s), &locs);
#if 0
        {
            FccEntryPointNode key;
            key.kv.key.key = item->key;
            fcs_lock_lock(&instance->fcc_entry_points_lock);
            FccEntryPointNode * val_proto = RB_FIND(
                FccEntryPointList,
                &(instance->fcc_entry_points),
                &(key)
            );

            fcs_bool_t to_prune = FALSE;
            fcs_bool_t to_output = FALSE;
            if (val_proto)
            {
                val_proto->kv.val.is_reachable = TRUE;
                const int moves_count = instance->start_key_moves_count
                    + item->moves_seq.count;

                if (was_start_key_reachable)
                {
                    if (val_proto->kv.val.depth <= moves_count)
                    {
                        /* We can prune based on here. */
                        to_prune = TRUE;
                    }
                    else
                    {
                        /* We can set it to the more pessimstic move count
                         * for future trimming. */
                        to_output = !(val_proto->kv.val.was_consumed);
                        val_proto->kv.val.depth = moves_count;
                        val_proto->kv.val.was_consumed = TRUE;
                    }
                }
                else
                {
                    if (! val_proto->kv.val.was_consumed)
                    {
                        to_output = TRUE;
                        if (val_proto->kv.val.depth >= moves_count)
                        {
                            val_proto->kv.val.depth = moves_count;
                            val_proto->kv.val.was_consumed = TRUE;
                        }
                    }
                }
            }
            fcs_lock_unlock(&instance->fcc_entry_points_lock);

            if (to_output)
            {
                const size_t needed_len = ( (sizeof(key.kv.key.key)+2) << 2 ) / 3 + 20;
                if (base64_encoding_buffer_max_len < needed_len)
                {
                    base64_encoding_buffer = SREALLOC(base64_encoding_buffer, needed_len);
                    base64_encoding_buffer_max_len = needed_len;
                }

                size_t unused_output_len;

                base64_encode(
                    (unsigned char *)&(key.kv.key.key),
                    sizeof(key.kv.key.key),
                    base64_encoding_buffer,
                    &unused_output_len
                );

                fcs_lock_lock(&instance->output_lock);
                fprintf(
                    instance->consumed_states_fh,
                    "%s\n", base64_encoding_buffer
                );
                fflush(instance->consumed_states_fh);
                fcs_lock_unlock(&instance->output_lock);
            }

            if (to_prune)
            {
                continue;
            }
        }
#endif

            if (instance_solver_thread_calc_derived_states(local_variant,
                    &state, token, &derived_list, &derived_list_recycle_bin,
                    &derived_list_allocator, TRUE))
            {
                fcs_lock_lock(&instance->global_lock);
                fcs_dbm__found_solution(&(instance->common), token, item);
                fcs_lock_unlock(&instance->global_lock);
                break;
            }

            /* Encode all the states. */
            for (derived_iter = derived_list; derived_iter;
                 derived_iter = derived_iter->next)
            {
                fcs_init_and_encode_state(delta_stater, local_variant,
                    &(derived_iter->state), &(derived_iter->key));
            }

            instance_check_multiple_keys(thread, instance, &(coll->cache_store),
                &(coll->queue_meta_alloc), &derived_list, 1
#ifdef FCS_DBM_CACHE_ONLY
                ,
                item->moves_to_key
#endif
                );

            /* Now recycle the derived_list */
            while (derived_list)
            {
#define derived_list_next derived_iter
                derived_list_next = derived_list->next;
                derived_list->next = derived_list_recycle_bin;
                derived_list_recycle_bin = derived_list;
                derived_list = derived_list_next;
#undef derived_list_next
            }
            /* End handle item. */
        }
        /* End of main thread loop */
        prev_item = item;
    }

    free(base64_encoding_buffer);

    fc_solve_compact_allocator_finish(&(derived_list_allocator));

    TRACE("%s\n", "instance_run_solver_thread end");

    return NULL;
}