/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* */ /* This file is part of the HiGHS linear optimization suite */ /* */ /* Available as open-source under the MIT License */ /* */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef HIGHS_MIP_SOLVER_DATA_H_ #define HIGHS_MIP_SOLVER_DATA_H_ #include #include "mip/HighsCliqueTable.h" #include "mip/HighsConflictPool.h" #include "mip/HighsCutPool.h" #include "mip/HighsDebugSol.h" #include "mip/HighsDomain.h" #include "mip/HighsImplications.h" #include "mip/HighsLpRelaxation.h" #include "mip/HighsMipWorker.h" #include "mip/HighsNodeQueue.h" #include "mip/HighsObjectiveFunction.h" #include "mip/HighsPrimalHeuristics.h" #include "mip/HighsPseudocost.h" #include "mip/HighsRedcostFixing.h" #include "mip/HighsSearch.h" #include "mip/HighsSeparation.h" #include "parallel/HighsParallel.h" #include "presolve/HighsPostsolveStack.h" #include "presolve/HighsSymmetry.h" #include "util/HighsTimer.h" struct HighsPrimaDualIntegral { double value; double prev_lb; double prev_ub; double prev_gap; double prev_time; void initialise(); }; enum MipSolutionSource : int { kSolutionSourceNone = -1, kSolutionSourceMin = kSolutionSourceNone, // kSolutionSourceInitial, // 0 kSolutionSourceBranching, // B kSolutionSourceCentralRounding, // C kSolutionSourceFeasibilityPump, // F kSolutionSourceHeuristic, // H kSolutionSourceShifting, // I kSolutionSourceFeasibilityJump, // J kSolutionSourceSubMip, // L kSolutionSourceEmptyMip, // P kSolutionSourceRandomizedRounding, // R kSolutionSourceSolveLp, // S kSolutionSourceEvaluateNode, // T kSolutionSourceUnbounded, // U kSolutionSourceUserSolution, // X kSolutionSourceHighsSolution, // Y kSolutionSourceZiRound, // Z kSolutionSourceTrivialL, // l kSolutionSourceTrivialP, // p kSolutionSourceTrivialU, // u kSolutionSourceTrivialZ, // z kSolutionSourceCleanup, kSolutionSourceCount }; struct HighsMipSolverData { HighsMipSolver& mipsolver; std::deque lps; std::deque cutpools; std::deque conflictpools; std::deque domains; std::deque pseudocosts; std::deque workers; bool parallel_lock; HighsPrimalHeuristics heuristics; HighsCliqueTable cliquetable; HighsImplications implications; HighsRedcostFixing redcostfixing; HighsObjectiveFunction objectiveFunction; presolve::HighsPostsolveStack postSolveStack; HighsPresolveStatus presolve_status; HighsLp presolvedModel; bool cliquesExtracted; bool rowMatrixSet; bool analyticCenterComputed; HighsModelStatus analyticCenterStatus; bool detectSymmetries; HighsInt numRestarts; HighsInt numRestartsRoot; HighsInt numCliqueEntriesAfterPresolve; HighsInt numCliqueEntriesAfterFirstPresolve; std::vector ARstart_; std::vector ARindex_; std::vector ARvalue_; std::vector maxAbsRowCoef; std::vector rowintegral; std::vector uplocks; std::vector downlocks; std::vector integer_cols; std::vector implint_cols; std::vector integral_cols; std::vector continuous_cols; HighsSymmetries symmetries; std::shared_ptr globalOrbits; double feastol; double epsilon; double heuristic_effort; int64_t dispfreq; std::vector analyticCenter; std::vector firstlpsol; std::vector rootlpsol; double firstlpsolobj; HighsBasis firstrootbasis; double rootlpsolobj; HighsInt numintegercols; HighsInt maxTreeSizeLog2; HighsCDouble pruned_treeweight; double avgrootlpiters; double disptime; double last_disptime; int64_t firstrootlpiters; int64_t num_nodes; int64_t num_leaves; int64_t num_leaves_before_run; int64_t num_nodes_before_run; int64_t total_repair_lp; int64_t total_repair_lp_feasible; int64_t total_repair_lp_iterations; int64_t total_lp_iterations; int64_t heuristic_lp_iterations; int64_t sepa_lp_iterations; int64_t sb_lp_iterations; int64_t total_lp_iterations_before_run; int64_t heuristic_lp_iterations_before_run; int64_t sepa_lp_iterations_before_run; int64_t sb_lp_iterations_before_run; int64_t num_disp_lines; HighsInt numImprovingSols; double lower_bound; double upper_bound; double upper_limit; double optimality_limit; std::vector incumbent; HighsNodeQueue nodequeue; HighsPrimaDualIntegral primal_dual_integral; HighsDebugSol debugSolution; HighsMipSolverData(HighsMipSolver& mipsolver); bool solutionRowFeasible(const std::vector& solution) const; HighsModelStatus feasibilityJump(); HighsModelStatus trivialHeuristics(); void startAnalyticCenterComputation( const highs::parallel::TaskGroup& taskGroup); void finishAnalyticCenterComputation( const highs::parallel::TaskGroup& taskGroup); struct SymmetryDetectionData { HighsSymmetryDetection symDetection; HighsSymmetries symmetries; double detectionTime = 0.0; }; void startSymmetryDetection(const highs::parallel::TaskGroup& taskGroup, std::unique_ptr& symData); void finishSymmetryDetection(const highs::parallel::TaskGroup& taskGroup, std::unique_ptr& symData); void updatePrimalDualIntegral(const double from_lower_bound, const double to_lower_bound, const double from_upper_bound, const double to_upper_bound, const bool check_bound_change = true, const bool check_prev_data = true); double limitsToGap(const double use_lower_bound, const double use_upper_bound, double& lb, double& ub) const; double computeNewUpperLimit(double upper_bound, double mip_abs_gap, double mip_rel_gap) const; bool moreHeuristicsAllowed() const; void removeFixedIndices(); void init(); void basisTransfer(); void checkObjIntegrality(); void runMipPresolve(const HighsInt presolve_reduction_limit); void setupDomainPropagation(); void saveReportMipSolution(const double new_upper_limit = -kHighsInf); void runSetup(); double transformNewIntegerFeasibleSolution( const std::vector& sol, const bool possibly_store_as_new_incumbent = true); double percentageInactiveIntegers() const; void performRestart(); bool checkSolution(const std::vector& solution) const; std::vector> getInfeasibleRows( const std::vector& solution) const; bool trySolution(const std::vector& solution, const int solution_source = kSolutionSourceNone); bool rootSeparationRound(HighsMipWorker& worker, HighsSeparation& sepa, HighsInt& ncuts, HighsLpRelaxation::Status& status); HighsLpRelaxation::Status evaluateRootLp(HighsMipWorker& worker); void evaluateRootNode(HighsMipWorker& worker); bool addIncumbent(const std::vector& sol, double solobj, const int solution_source, const bool print_display_line = true, const bool is_user_solution = false); const std::vector& getSolution() const; std::string solutionSourceToString(const int solution_source, const bool code = true) const; void printSolutionSourceKey() const; void printDisplayLine(const int solution_source = kSolutionSourceNone); void getRow(HighsInt row, HighsInt& rowlen, const HighsInt*& rowinds, const double*& rowvals) const { HighsInt start = ARstart_[row]; rowlen = ARstart_[row + 1] - start; rowinds = ARindex_.data() + start; rowvals = ARvalue_.data() + start; } bool checkLimits(int64_t nodeOffset = 0) const; void limitsToBounds(double& dual_bound, double& primal_bound, double& mip_rel_gap) const; void updateLowerBound(double new_lower_bound, const bool check_bound_change = true, const bool check_prev_data = true); void setCallbackDataOut(const double mipsolver_objective_value) const; bool interruptFromCallbackWithData(const int callback_type, const double mipsolver_objective_value, const std::string message = "") const; void queryExternalSolution( const double mipsolver_objective_value, const ExternalMipSolutionQueryOrigin external_solution_query_origin); HighsInt terminatorConcurrency() const; bool terminatorActive() const { return terminatorConcurrency() > 0; } HighsInt terminatorMyInstance() const; void terminatorTerminate(); bool terminatorTerminated() const; void terminatorReport() const; bool parallelLockActive() const { return (parallel_lock && hasMultipleWorkers()); } bool hasMultipleWorkers() const { return workers.size() > 1; } HighsDomain& getDomain() { return domains[0]; } HighsConflictPool& getConflictPool() { return conflictpools[0]; } HighsCutPool& getCutPool() { return cutpools[0]; } HighsLpRelaxation& getLp() { return lps[0]; } HighsPseudocost& getPseudoCost() { return pseudocosts[0]; } const HighsDomain& getDomain() const { return domains[0]; } const HighsConflictPool& getConflictPool() const { return conflictpools[0]; } const HighsCutPool& getCutPool() const { return cutpools[0]; } const HighsLpRelaxation& getLp() const { return lps[0]; } const HighsPseudocost& getPseudoCost() const { return pseudocosts[0]; } }; #endif