/* * cl_propagators.c * * Created on: 09/09/2019 * Author: pedro */ #ifndef __OPENCL_VERSION__ #include #include #include "cl_propagators.h" #include "cl_aux_functions.h" #include "../utils/cl_syntax.h" #include "../constraints/all_different.h" #include "../constraints/at_least.h" #include "../constraints/at_most.h" #include "../constraints/at_most_one.h" #include "../constraints/bool2int.h" #include "../constraints/bool_and.h" #include "../constraints/bool_clause.h" #include "../constraints/bool_or.h" #include "../constraints/element.h" #include "../constraints/element_int_var.h" #include "../constraints/element_var.h" #include "../constraints/eq.h" #include "../constraints/eq_var.h" #include "../constraints/ne.h" #include "../constraints/exactly.h" #include "../constraints/exactly_var.h" #include "../constraints/le.h" #include "../constraints/linear.h" #include "../constraints/linear_lt.h" #include "../constraints/linear_ne.h" #include "../constraints/linear_var.h" #include "../constraints/lt.h" #include "../constraints/max.h" #include "../constraints/maximize.h" #include "../constraints/min.h" #include "../constraints/minimize.h" #include "../constraints/minus_eq.h" #include "../constraints/minus_ne.h" #include "../constraints/sum.h" #include "../constraints/sum_prod.h" #include "../constraints/sum_var.h" #include "../constraints/var_eq_minus.h" #include "../constraints/var_eq_minus_abs.h" #include "../constraints/var_eq_plus.h" #include "../constraints/var_eq_times.h" #else #include "../constraints/all_different.c" #include "../constraints/at_least.c" #include "../constraints/at_most.c" #include "../constraints/at_most_one.c" #include "../constraints/bool2int.c" #include "../constraints/bool_and.c" #include "../constraints/bool_clause.c" #include "../constraints/bool_or.c" #include "../constraints/element.c" #include "../constraints/element_int_var.c" #include "../constraints/element_var.c" #include "../constraints/eq.c" #include "../constraints/eq_var.c" #include "../constraints/ne.c" #include "../constraints/exactly.c" #include "../constraints/exactly_var.c" #include "../constraints/le.c" #include "../constraints/linear.c" #include "../constraints/linear_lt.c" #include "../constraints/linear_ne.c" #include "../constraints/linear_var.c" #include "../constraints/lt.c" #include "../constraints/max.c" #include "../constraints/maximize.c" #include "../constraints/min.c" #include "../constraints/minimize.c" #include "../constraints/minus_eq.c" #include "../constraints/minus_ne.c" #include "../constraints/sum.c" #include "../constraints/sum_prod.c" #include "../constraints/sum_var.c" #include "../constraints/var_eq_minus.c" #include "../constraints/var_eq_minus_abs.c" #include "../constraints/var_eq_plus.c" #include "../constraints/var_eq_times.c" #endif #include "../config.h" #include "../domains.h" #include "cl_constraints.h" #include "cl_variables.h" #include "cl_ttl.h" #if CL_D_TYPE == CL_BITMAP #include "cl_bitmaps.h" #elif CL_D_TYPE == CL_INTERVAL #include "cl_intervals.h" #endif /* * Propagate the domain of the variable with the ID prop_v_id through all the other variables on each constraint that constrain prop_v_id * Return 1 if all propagations succeed or 0 if not * vs - CSP variables * cs - CSP constraints * cs_per_v_idx - vector with all the constraints ID that constrain each variable, per variable ID order * vs_per_c_idx - vector with all constrained variables ID per constraint, per constraint ID order * c_consts - vector with all the constant values of a CSP * nodes_fail - counter for all the failed nodes * nodes_expl - counter for all the explored nodes * pruning - counter for all the propagations that prunned values * props_ok - counter for all the succeeded propagations * vs_prop_ - all CSP variables with current step values * prop_v_id - variable ID to propagate * current_cs - constraint that should be propagated for the variable with prop_v_id ID * vs_id_to_prop_ - circular vector with the ids of the variables to propagate */ CUDA_FUNC void propagate( CL_VS_MEM VARS* vs, CL_CS_MEM cl_constr* cs, CL_INTS_MEM int* cs_per_v_idx, CL_INTS_MEM int* vs_per_c_idx, #if CS_AT_LEAST == 1 || CS_AT_MOST == 1 || CS_AT_MOST_ONE == 1 || CS_EXACTLY == 1 || CS_LINEAR == 1 || CS_LINEAR_LT == 1 || CS_LINEAR_NE == 1 || CS_LINEAR_VAR == 1 || CS_ELEMENT_INT_VAR == 1 CL_INTS_MEM int* c_consts, #endif #if (CS_MAXIMIZE == 1 || CS_MINIMIZE == 1) && CL_WORK == CL_OPT __global unsigned int* val_to_opt_g, #endif #if CL_STATS == 1 __global unsigned long* nodes_fail, __global unsigned long* nodes_expl, __global unsigned long* pruning, __global unsigned long* props_ok, #endif CL_MEMORY VARS_PROP* vs_prop_, unsigned int prop_v_id, CL_MEMORY unsigned short* vs_id_to_prop_ TTL_CTR #if CL_N_DEVS > 1 , unsigned long* props_count #endif CS_IGNORE_FUNC, bool* prop_ok, __global int* terms_mem) { CL_CS_MEM cl_constr* current_cs; int i; *prop_ok = 1; #if CL_CHECK_ERRORS int l; for (l = 0; l < CL_N_VS; l++) { bool empty; #if CL_N_WORDS == 1 empty = (vs_prop_[l].prop_d == 0); #else int m; empty = 1; for (m = 0; m < CL_N_WORDS; m++) { CHECK_TTL(ttl_ctr, 115) if (vs_prop_[l].prop_d[m] != 0) { empty = 0; m = CL_N_WORDS; } } #endif if ((*prop_ok == 1 && (empty || vs_prop_[l].n_vals == 0 || vs_prop_[l].n_vals > vs_prop_[l].max + 1)) || vs_prop_[l].min > vs_prop_[l].max || vs_prop_[l].max > CL_D_MAX) { printf((__constant char *)"\n###error 71\n"); } } #endif // for statistics #if CL_STATS == 1 bool propagated; int last_prev_vs_to_prop; #endif #if CL_CHECK_ERRORS if (prop_v_id > CL_N_VS) { printf((__constant char *)"\n###error 48\n"); } #endif // iterates the constraints that constrain the variable to propagate for (i = 0; i < vs[prop_v_id].n_cs; i++) { CHECK_TTL(ttl_ctr, 28) current_cs = &cs[cs_per_v_idx[vs[prop_v_id].c_idx + convert_uint(i)]]; unsigned int kind = current_cs->kind; CL_INTS_MEM int* vs_per_c_idx_ = &vs_per_c_idx[current_cs->v_idx]; #if CL_CHECK_ERRORS if (cs_per_v_idx[vs[prop_v_id].c_idx + convert_uint(i)] > CL_N_CS) { printf((__constant char *)"\n###error 49\n"); } if (kind > 34) { printf((__constant char *)"\n###error 50\n"); } if (current_cs->v_idx > CL_N_VS_CS) { printf((__constant char *)"\n###error 52\n"); } #endif #if CS_AT_LEAST == 1 || CS_AT_MOST == 1 || CS_AT_MOST_ONE == 1 || CS_EXACTLY == 1 || CS_LINEAR == 1 || CS_LINEAR_LT == 1 || CS_LINEAR_NE == 1 || CS_LINEAR_VAR == 1 || CS_ELEMENT_INT_VAR == 1 CL_INTS_MEM int* c_consts_ = &c_consts[current_cs->const_idx]; #if CL_CHECK_ERRORS if (current_cs->v_idx > CL_N_CS_VS) { printf((__constant char *)"\n###error 53\n"); } #endif #endif #if CL_N_DEVS > 1 (*props_count)++; #endif #if CL_STATS == 1 last_prev_vs_to_prop = vs_id_to_prop_[1]; propagated = false; #endif #if CL_CS_IGNORE if (cs_ignore[current_cs->c_id] == 0) { #endif switch (kind) { #if CS_ALL_DIFFERENT == 1 case ALL_DIFFERENT: all_different_propagate(vs_per_c_idx_, vs_prop_, prop_v_id, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL TTL_CTR_V); break; #endif #if CS_AT_LEAST == 1 case AT_LEAST: at_least_propagate(vs_per_c_idx_, c_consts_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_AT_MOST == 1 case AT_MOST: at_most_propagate(vs_per_c_idx_, c_consts_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_AT_MOST_ONE == 1 case AT_MOST_ONE: at_most_one_propagate(vs_per_c_idx_, c_consts_, vs_prop_, prop_v_id, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL TTL_CTR_V); break; #endif #if CS_BOOL2INT == 1 case BOOL2INT: bool2int_propagate(vs_per_c_idx_, vs_prop_, prop_v_id, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_BOOL_AND == 1 case BOOL_AND: bool_and_propagate(vs_per_c_idx_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_BOOL_CLAUSE == 1 case BOOL_CLAUSE: bool_clause_propagate(vs_per_c_idx_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_BOOL_OR == 1 case BOOL_OR: bool_or_propagate(vs_per_c_idx_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_ELEMENT == 1 case ELEMENT: element_propagate(vs_per_c_idx_, vs_prop_, prop_v_id, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_ELEMENT_INT_VAR == 1 case ELEMENT_INT_VAR: element_int_var_propagate(vs_per_c_idx_, c_consts_, vs_prop_, prop_v_id, current_cs, vs_id_to_prop_, prop_ok, terms_mem PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_ELEMENT_VAR == 1 case ELEMENT_VAR: element_var_propagate(vs_per_c_idx_, vs_prop_, prop_v_id, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_EQ == 1 case EQ: eq_propagate(vs_per_c_idx_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_EQ_VAR == 1 case EQ_VAR: eq_var_propagate(vs_per_c_idx_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_EXACTLY == 1 case EXACTLY: exactly_propagate(vs_per_c_idx_, c_consts_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_EXACTLY_VAR == 1 case EXACTLY_VAR: exactly_var_propagate(vs_per_c_idx_, vs_prop_, prop_v_id, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_LE == 1 case LE: le_propagate(vs_per_c_idx_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_LINEAR == 1 case LINEAR: linear_propagate(vs_per_c_idx_, c_consts_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok, terms_mem PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_LINEAR_LT == 1 case LINEAR_LT: linear_lt_propagate(vs_per_c_idx_, c_consts_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok, terms_mem PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_LINEAR_NE == 1 case LINEAR_NE: linear_ne_propagate(vs_per_c_idx_, c_consts_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok, terms_mem PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_LINEAR_VAR == 1 case LINEAR_VAR: linear_var_propagate(vs_per_c_idx_, c_consts_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok, terms_mem PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_LT == 1 case LT: lt_propagate(vs_per_c_idx_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_MAX == 1 case MAX: max_propagate(vs_per_c_idx_, vs_prop_, prop_v_id, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_MAXIMIZE == 1 && CL_WORK == CL_OPT case MAXIMIZE: maximize_propagate(vs_prop_, current_cs, vs_id_to_prop_, val_to_opt_g, prop_ok PROPAGATED_CALL TTL_CTR_V); break; #endif #if CS_MIN == 1 case MIN: min_propagate(vs_per_c_idx_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_MINIMIZE == 1 && CL_WORK == CL_OPT case MINIMIZE: minimize_propagate(vs_prop_, current_cs, vs_id_to_prop_, val_to_opt_g, prop_ok PROPAGATED_CALL TTL_CTR_V); break; #endif #if CS_MINUS_EQ == 1 case MINUS_EQ: minus_eq_propagate(vs_per_c_idx_, vs_prop_, prop_v_id, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_MINUS_NE == 1 case MINUS_NE: minus_ne_propagate(vs_per_c_idx_, vs_prop_, prop_v_id, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_NE == 1 case NE: ne_propagate(vs_per_c_idx_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_SUM == 1 case SUM: sum_propagate(vs_per_c_idx_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok, terms_mem PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_SUM_PROD == 1 case SUM_PROD: sum_prod_propagate(vs_per_c_idx_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_SUM_VAR == 1 case SUM_VAR: sum_var_propagate(vs_per_c_idx_, vs_prop_, current_cs, vs_id_to_prop_, prop_ok, terms_mem PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_VAR_EQ_MINUS == 1 case VAR_EQ_MINUS: var_eq_minus_propagate(vs_per_c_idx_, vs_prop_, prop_v_id, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_VAR_EQ_MINUS_ABS == 1 case VAR_EQ_MINUS_ABS: var_eq_minus_abs_propagate(vs_per_c_idx_, vs_prop_, prop_v_id, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL TTL_CTR_V); break; #endif #if CS_VAR_EQ_PLUS == 1 case VAR_EQ_PLUS: var_eq_plus_propagate(vs_per_c_idx_, vs_prop_, prop_v_id, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif #if CS_VAR_EQ_TIMES == 1 case VAR_EQ_TIMES: var_eq_times_propagate(vs_per_c_idx_, vs_prop_, prop_v_id, current_cs, vs_id_to_prop_, prop_ok PROPAGATED_CALL CS_IGNORE_CALL TTL_CTR_V); break; #endif default: *prop_ok = 0; #if CL_CHECK_ERRORS printf((__constant char *)"\n###error 65\n"); #endif break; } #if CL_STATS == 1 if (propagated) { if (*prop_ok == 0) { (*nodes_fail)++; (*nodes_expl)++; } else { (*props_ok)++; if (last_prev_vs_to_prop != vs_id_to_prop_[1]) { (*pruning) += convert_ulong(abs(vs_id_to_prop_[1] - last_prev_vs_to_prop)); } } } #endif if (*prop_ok == 0) { i = vs[prop_v_id].n_cs; } // check if there is any variable marked for being propagated, but not listed in the list of variables to propagate #if CL_CHECK_ERRORS int k; for (l = 0; l < CL_N_VS; l++) { bool empty; #if CL_N_WORDS == 1 empty = (vs_prop_[l].prop_d == 0); #else int m; empty = 1; for (m = 0; m < CL_N_WORDS; m++) { CHECK_TTL(ttl_ctr, 115) if (vs_prop_[l].prop_d[m] != 0) { empty = 0; m = CL_N_WORDS; } } #endif if ((*prop_ok == 1 && (empty || vs_prop_[l].n_vals == 0 || vs_prop_[l].n_vals > vs_prop_[l].max + 1)) || vs_prop_[l].min > vs_prop_[l].max || vs_prop_[l].max > CL_D_MAX) { printf((__constant char *)"\n###error 70\n"); printf((__constant char *)"constraint=%d, prop_ok=%d, empty=%d, vs_prop_[l].n_vals=%u, vs_prop_[l].min=%u, vs_prop_[l].max=%u\n", kind, *prop_ok, empty, vs_prop_[l].n_vals, vs_prop_[l].min, vs_prop_[l].max); *prop_ok = 0; i = vs[prop_v_id].n_cs; } if (vs_prop_[l].to_prop == 1) { if (vs_id_to_prop_[0] <= vs_id_to_prop_[1]) { for (k = vs_id_to_prop_[0]; k < vs_id_to_prop_[1]; k++) { CHECK_TTL(ttl_ctr, 154) if (vs_id_to_prop_[k] == l) { break; } } if (k == vs_id_to_prop_[1]) { printf((__constant char *)"\n###error 66\n"); } } else { for (k = vs_id_to_prop_[0]; k < vs_id_to_prop_[CL_N_VS + 2]; k++) { CHECK_TTL(ttl_ctr, 155) if (k < CL_D_MAX + 2 && vs_id_to_prop_[k] == l) { break; } } if (k == vs_id_to_prop_[CL_N_VS + 2]) { for (k = 2; k < vs_id_to_prop_[1]; k++) { CHECK_TTL(ttl_ctr, 156) if (vs_id_to_prop_[k] == l) { break; } } } } } } #endif #if CL_CS_IGNORE } #endif } }