@@ -89,6 +89,11 @@ void problem_t<i_t, f_t>::op_problem_cstr_body(const optimization_problem_t<i_t,
8989 // If maximization problem, convert the problem
9090 if (maximize) convert_to_maximization_problem (*this );
9191 if (is_mip) {
92+ presolve_data.var_flags .resize (n_variables, handle_ptr->get_stream ());
93+ thrust::fill (handle_ptr->get_thrust_policy (),
94+ presolve_data.var_flags .begin (),
95+ presolve_data.var_flags .end (),
96+ 0 );
9297 integer_indices.resize (n_variables, handle_ptr->get_stream ());
9398 is_binary_variable.resize (n_variables, handle_ptr->get_stream ());
9499 compute_n_integer_vars ();
@@ -190,6 +195,7 @@ problem_t<i_t, f_t>::problem_t(const problem_t<i_t, f_t>& problem_)
190195 objective_name(problem_.objective_name),
191196 is_scaled_(problem_.is_scaled_),
192197 preprocess_called(problem_.preprocess_called),
198+ objective_is_integral(problem_.objective_is_integral),
193199 lp_state(problem_.lp_state),
194200 fixing_helpers(problem_.fixing_helpers, handle_ptr),
195201 vars_with_objective_coeffs(problem_.vars_with_objective_coeffs),
@@ -284,6 +290,7 @@ problem_t<i_t, f_t>::problem_t(const problem_t<i_t, f_t>& problem_, bool no_deep
284290 objective_name(problem_.objective_name),
285291 is_scaled_(problem_.is_scaled_),
286292 preprocess_called(problem_.preprocess_called),
293+ objective_is_integral(problem_.objective_is_integral),
287294 lp_state(problem_.lp_state),
288295 fixing_helpers(problem_.fixing_helpers, handle_ptr),
289296 vars_with_objective_coeffs(problem_.vars_with_objective_coeffs),
@@ -933,6 +940,8 @@ typename problem_t<i_t, f_t>::view_t problem_t<i_t, f_t>::view()
933940 v.variable_types = raft::device_span<var_t >{variable_types.data (), variable_types.size ()};
934941 v.is_binary_variable =
935942 raft::device_span<i_t >{is_binary_variable.data (), is_binary_variable.size ()};
943+ v.var_flags =
944+ raft::device_span<i_t >{presolve_data.var_flags .data (), presolve_data.var_flags .size ()};
936945 v.related_variables = raft::device_span<i_t >{related_variables.data (), related_variables.size ()};
937946 v.related_variables_offsets =
938947 raft::device_span<i_t >{related_variables_offsets.data (), related_variables_offsets.size ()};
@@ -953,6 +962,7 @@ void problem_t<i_t, f_t>::resize_variables(size_t size)
953962 variable_types.resize (size, handle_ptr->get_stream ());
954963 objective_coefficients.resize (size, handle_ptr->get_stream ());
955964 is_binary_variable.resize (size, handle_ptr->get_stream ());
965+ presolve_data.var_flags .resize (size, handle_ptr->get_stream ()); // 0 is default - no flag
956966 related_variables_offsets.resize (size, handle_ptr->get_stream ());
957967}
958968
@@ -1060,6 +1070,32 @@ void problem_t<i_t, f_t>::insert_constraints(constraints_delta_t<i_t, f_t>& h_co
10601070 combine_constraint_bounds<i_t , f_t >(*this , combined_bounds);
10611071}
10621072
1073+ template <typename i_t , typename f_t >
1074+ void problem_t <i_t , f_t >::set_implied_integers(const std::vector<i_t >& implied_integer_indices)
1075+ {
1076+ raft::common::nvtx::range fun_scope (" set_implied_integers" );
1077+ auto d_indices = cuopt::device_copy (implied_integer_indices, handle_ptr->get_stream ());
1078+ print (" implied integer indices" , d_indices);
1079+ thrust::for_each (handle_ptr->get_thrust_policy (),
1080+ d_indices.begin (),
1081+ d_indices.end (),
1082+ [var_flags = make_span (presolve_data.var_flags ),
1083+ var_types = make_span (variable_types)] __device__ (i_t idx) {
1084+ cuopt_assert (idx < var_flags.size (), " Index out of bounds" );
1085+ cuopt_assert (var_types[idx] == var_t ::CONTINUOUS, " Variable is integer" );
1086+ var_flags[idx] |= (i_t )VAR_IMPLIED_INTEGER;
1087+ });
1088+ objective_is_integral = thrust::all_of (handle_ptr->get_thrust_policy (),
1089+ thrust::make_counting_iterator (0 ),
1090+ thrust::make_counting_iterator (n_variables),
1091+ [v = view ()] __device__ (i_t var_idx) {
1092+ if (v.objective_coefficients [var_idx] == 0 ) return true ;
1093+ return v.is_integer (v.objective_coefficients [var_idx]) &&
1094+ (v.variable_types [var_idx] == var_t ::INTEGER ||
1095+ (v.var_flags [var_idx] & VAR_IMPLIED_INTEGER));
1096+ });
1097+ }
1098+
10631099template <typename i_t , typename f_t >
10641100void problem_t <i_t , f_t >::fix_given_variables(problem_t <i_t , f_t >& original_problem,
10651101 rmm::device_uvector<f_t >& assignment,
@@ -1249,6 +1285,13 @@ void problem_t<i_t, f_t>::remove_given_variables(problem_t<i_t, f_t>& original_p
12491285 original_problem.variable_types .begin (),
12501286 variable_types.begin ());
12511287 variable_types.resize (variable_map.size (), handle_ptr->get_stream ());
1288+ // keep implied-integer and other flags consistent with new variable set
1289+ thrust::gather (handle_ptr->get_thrust_policy (),
1290+ variable_map.begin (),
1291+ variable_map.end (),
1292+ original_problem.presolve_data .var_flags .begin (),
1293+ presolve_data.var_flags .begin ());
1294+ presolve_data.var_flags .resize (variable_map.size (), handle_ptr->get_stream ());
12521295 const i_t TPB = 64 ;
12531296 // compute new offsets
12541297 compute_new_offsets<i_t , f_t ><<<variable_map.size(), TPB, 0 , handle_ptr->get_stream ()>>>(
0 commit comments