Skip to content

Commit

Permalink
Bug fix: iterative iters limit on flares.
Browse files Browse the repository at this point in the history
1. Fix a bug where using a flare-based scan while incrementally increasing
the iterations limit could have created a situation where one scan gets all
the iterations.
  • Loading branch information
shlomif committed Apr 24, 2016
1 parent c8e5877 commit 70a0a78
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 23 deletions.
7 changes: 7 additions & 0 deletions fc-solve/source/NEWS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ Shlomi Fish <shlomif@cpan.org>
:Date: 2016-01-14
:Revision: $Id$

Version 4.4.0: (DD-MMM-YYYY)
----------------------------

1. Fix a bug where using a flare-based scan while incrementally increasing
the iterations limit could have created a situation where one scan gets all
the iterations.

Version 4.2.0: (25-Mar-2016)
----------------------------

Expand Down
78 changes: 57 additions & 21 deletions fc-solve/source/lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,21 @@ typedef enum
} flares_choice_type_t;
#endif

typedef int flare_iters_quota_t;

static GCC_INLINE const flare_iters_quota_t normalize_iters_quota(
const flare_iters_quota_t i
)
{
return max(i, 0);
}

typedef struct
{
fcs_flare_item_t * flare;
flares_plan_type_t type;
int count_iters;
flare_iters_quota_t remaining_quota, initial_quota;
} flares_plan_item;

typedef struct
Expand Down Expand Up @@ -201,12 +211,14 @@ static void iter_handler_wrapper(
for (fcs_flare_item_t * flare = instance_item->flares; flare < end_of_flares ; flare++) \
{ \

#define FLARES_LOOP_START() \
#define INSTANCES_LOOP_START() \
const_SLOT(end_of_instances_list, user); \
for (fcs_instance_item_t * instance_item = user->instances_list; instance_item < end_of_instances_list ; instance_item++)\
{ \
INSTANCE_ITEM_FLARES_LOOP_START()

#define FLARES_LOOP_START() \
INSTANCES_LOOP_START() \
INSTANCE_ITEM_FLARES_LOOP_START()

#define FLARES_LOOP_END_FLARES() \
}
Expand Down Expand Up @@ -762,6 +774,31 @@ int DLLEXPORT freecell_solver_user_solve_board(
{
return FCS_STATE_FLARES_PLAN_ERROR;
}
const_SLOT(flares_iters_factor, user);
INSTANCES_LOOP_START()
const_SLOT(num_plan_items, instance_item);
const_SLOT(plan, instance_item);
for (int i = 0; i < num_plan_items; i++)
{
flares_plan_item * item = plan + i;
switch (item->type)
{
case FLARES_PLAN_RUN_INDEFINITELY:
item->remaining_quota = item->initial_quota = -1;
break;

case FLARES_PLAN_RUN_COUNT_ITERS:
item->remaining_quota = item->initial_quota = normalize_iters_quota(
(typeof(item->initial_quota))
(flares_iters_factor * item->count_iters)
);
break;

case FLARES_PLAN_CHECKPOINT:
break;
}
}
FLARES_LOOP_END_INSTANCES()

return freecell_solver_user_resume_solution(api_instance);
}
Expand Down Expand Up @@ -964,14 +1001,7 @@ static GCC_INLINE fcs_instance_item_t * get_current_instance_item(
return (user->current_instance);
}

typedef int flare_iters_quota_t;

static GCC_INLINE const flare_iters_quota_t normalize_iters_quota(
const flare_iters_quota_t i
)
{
return max(i, 0);
}

int DLLEXPORT freecell_solver_user_resume_solution(
void * const api_instance
Expand Down Expand Up @@ -1015,8 +1045,10 @@ int DLLEXPORT freecell_solver_user_resume_solution(
}
}

const flares_plan_item * const current_plan_item =
&(instance_item->plan[instance_item->current_plan_item_idx++]);
const typeof(instance_item->current_plan_item_idx) init_current_plan_item_idx
= instance_item->current_plan_item_idx++;
flares_plan_item * const current_plan_item =
&(instance_item->plan[init_current_plan_item_idx]);


if (current_plan_item->type == FLARES_PLAN_CHECKPOINT)
Expand All @@ -1037,15 +1069,7 @@ int DLLEXPORT freecell_solver_user_resume_solution(
}

const flare_iters_quota_t flare_iters_quota =
(
(current_plan_item->type == FLARES_PLAN_RUN_INDEFINITELY)
? -1
/* (current_plan_item->type == FLARES_PLAN_RUN_COUNT_ITERS) */
: normalize_iters_quota(
(typeof(flare_iters_quota))
(user->flares_iters_factor * current_plan_item->count_iters)
)
);
current_plan_item->remaining_quota;

fcs_flare_item_t * const flare = current_plan_item->flare;
fc_solve_instance_t * const instance = &(flare->obj);
Expand Down Expand Up @@ -1180,7 +1204,14 @@ int DLLEXPORT freecell_solver_user_resume_solution(

flare->obj_stats.num_checked_states = instance->i__num_checked_states;
flare->obj_stats.num_states_in_collection = instance->num_states_in_collection;
user->iterations_board_started_at.num_checked_states += flare->obj_stats.num_checked_states - init_num_checked_states.num_checked_states;
const_AUTO(delta, flare->obj_stats.num_checked_states - init_num_checked_states.num_checked_states);
user->iterations_board_started_at.num_checked_states += delta;
if (flare_iters_quota >= 0)
{
current_plan_item->remaining_quota = normalize_iters_quota(
flare_iters_quota - delta
);
}
user->iterations_board_started_at.num_states_in_collection += flare->obj_stats.num_states_in_collection - init_num_checked_states.num_states_in_collection;
user->init_num_checked_states = flare->obj_stats;

Expand Down Expand Up @@ -1252,6 +1283,11 @@ int DLLEXPORT freecell_solver_user_resume_solution(
}
instance_item->all_plan_items_finished_so_far = 0;
}

if (instance_item->current_plan_item_idx != init_current_plan_item_idx)
{
current_plan_item->remaining_quota = current_plan_item->initial_quota;
}
} while (
(user->current_instance < end_of_instances_list) &&
(ret == FCS_STATE_IS_NOT_SOLVEABLE)
Expand Down
47 changes: 45 additions & 2 deletions fc-solve/source/t/t/several-iter-limits.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
sys.path.insert(0, os.environ['FCS_PY3_LIBDIR'])

from TAP.Simple import *
# TEST:source "$^CURRENT_DIRNAME/lib/FC_Solve/__init__.py"
# TEST:source "$^CURRENT_DIRNAME/lib-python3/FC_Solve/__init__.py"
from FC_Solve import FC_Solve

plan(11)
plan(14)

def test_resume_solution():
testname = "With RunIndef"
Expand Down Expand Up @@ -121,13 +121,56 @@ def test_num_states_in_collection_after_unsolved():
# TEST
ok (fcs.get_num_states_in_col() == 3436, "Num-states-in-collection is OK.");

def test_resume_solution_with_flares():
testname = "-l ve on iterative limiting - "

fcs = FC_Solve()

step = 1000
hard_limit = 100000
limit = step
# TEST*$input_cmd_line
fcs.input_cmd_line("video-editing", ['-l', 'video-editing',]);
fcs.limit_iterations(limit)

# MS deal No. 124
ret = fcs.solve_board(
"""7S AS 2C QS TH QD 7D
5D 8D 9D JH QH 5C JD
6D TD 5H 2S 6S TC KS
TS 4S 3D 9C 3C KD 7C
6H 5S 9H 6C KC AH
AC 4C 8S 2D QC JS
9S KH 8C 4D 7H 4H
2H 3S 8H AD 3H JC
""")

iters_count_ok = 1

while (ret == 5 and limit < hard_limit):
if (fcs.get_num_times() != limit):
iters_count_ok = 0

limit += step
fcs.limit_iterations(limit)
ret = fcs.resume_solution()

# TEST
ok (ret == 0, testname + "State was successfully solved.")

# TEST
ok (iters_count_ok == 1, testname + "Iters count was OK throughout the solution.")

def main():

test_resume_solution()

test_num_states_in_collection_after_recycle()

test_num_states_in_collection_after_unsolved()

test_resume_solution_with_flares()

#----------------------------------------------------------------------

if __name__ == "__main__":
Expand Down

0 comments on commit 70a0a78

Please sign in to comment.