Skip to content

Commit 591fb8d

Browse files
author
Julian Hall
committed
Merge branch 'latest' into fix-2860
2 parents 350ce51 + 8871c61 commit 591fb8d

File tree

13 files changed

+311
-403
lines changed

13 files changed

+311
-403
lines changed

highs/ipm/IpxWrapper.cpp

Lines changed: 3 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -468,106 +468,15 @@ HighsStatus solveHipo(const HighsOptions& options, HighsTimer& timer,
468468
// ipx_lps.control_ elapsed time
469469
hipo.setIpxTimerOffset(timer.read());
470470

471-
hipo::Options hipo_options{};
472-
473-
hipo_options.display = true;
474-
if (!options.output_flag | !options.log_to_console)
475-
hipo_options.display = false;
476-
477-
hipo_options.log_options = &options.log_options;
478-
479-
// Debug option is already considered through log_options.log_dev_level in
480-
// hipo::LogHighs::debug
481-
482-
hipo_options.timeless_log = options.timeless_log;
483-
hipo_options.feasibility_tol = std::min(options.primal_feasibility_tolerance,
484-
options.dual_feasibility_tolerance);
485-
hipo_options.optimality_tol = options.ipm_optimality_tolerance;
486-
hipo_options.crossover_tol = options.start_crossover_tolerance;
487-
488471
if (options.kkt_tolerance != kDefaultKktTolerance) {
489-
hipo_options.feasibility_tol = options.kkt_tolerance;
490-
hipo_options.optimality_tol = 1e-1 * options.kkt_tolerance;
491-
hipo_options.crossover_tol = 1e-1 * options.kkt_tolerance;
492472
highsLogUser(options.log_options, HighsLogType::kInfo,
493473
"IpxWrapper: feasibility_tol = %g; optimality_tol = %g; "
494474
"crossover_tol = %g\n",
495-
hipo_options.feasibility_tol, hipo_options.optimality_tol,
496-
hipo_options.crossover_tol);
497-
}
498-
499-
// hipo uses same timer as highs, so it is fine to pass the same time limit
500-
hipo_options.time_limit = options.time_limit;
501-
502-
hipo_options.max_iter =
503-
options.ipm_iteration_limit - highs_info.ipm_iteration_count;
504-
505-
if (options.run_crossover == kHighsOnString)
506-
hipo_options.crossover = hipo::kOptionCrossoverOn;
507-
else if (options.run_crossover == kHighsOffString)
508-
hipo_options.crossover = hipo::kOptionCrossoverOff;
509-
else {
510-
assert(options.run_crossover == kHighsChooseString);
511-
hipo_options.crossover = hipo::kOptionCrossoverChoose;
512-
}
513-
514-
// Potentially control if ipx is used for refinement and if it is displayed
515-
// hipo_options.refine_with_ipx = true;
516-
hipo_options.display_ipx = true;
517-
518-
// if option parallel is on, it can be refined by option hipo_parallel_type
519-
if (options.parallel == kHighsOnString) {
520-
if (options.hipo_parallel_type == kHipoTreeString)
521-
hipo_options.parallel = hipo::kOptionParallelTreeOnly;
522-
else if (options.hipo_parallel_type == kHipoNodeString)
523-
hipo_options.parallel = hipo::kOptionParallelNodeOnly;
524-
else if (options.hipo_parallel_type == kHipoBothString)
525-
hipo_options.parallel = hipo::kOptionParallelOn;
526-
else {
527-
highsLogUser(options.log_options, HighsLogType::kError,
528-
"Unknown value of option %s\n", kHipoParallelString.c_str());
529-
model_status = HighsModelStatus::kSolveError;
530-
return HighsStatus::kError;
531-
}
475+
options.kkt_tolerance, 1e-1 * options.kkt_tolerance,
476+
1e-1 * options.kkt_tolerance);
532477
}
533-
// otherwise, option hipo_parallel_type is ignored
534-
else if (options.parallel == kHighsOffString)
535-
hipo_options.parallel = hipo::kOptionParallelOff;
536-
else {
537-
assert(options.parallel == kHighsChooseString);
538-
hipo_options.parallel = hipo::kOptionParallelChoose;
539-
}
540-
541-
// Parse hipo_system option
542-
if (options.hipo_system == kHipoAugmentedString) {
543-
hipo_options.nla = hipo::kOptionNlaAugmented;
544-
} else if (options.hipo_system == kHipoNormalEqString) {
545-
hipo_options.nla = hipo::kOptionNlaNormEq;
546-
} else if (options.hipo_system == kHighsChooseString) {
547-
hipo_options.nla = hipo::kOptionNlaChoose;
548-
} else {
549-
highsLogUser(options.log_options, HighsLogType::kError,
550-
"Unknown value of option %s\n", kHipoSystemString.c_str());
551-
model_status = HighsModelStatus::kSolveError;
552-
return HighsStatus::kError;
553-
}
554-
555-
// Reordering heuristic
556-
if (options.hipo_ordering != kHipoMetisString &&
557-
options.hipo_ordering != kHipoAmdString &&
558-
options.hipo_ordering != kHipoRcmString &&
559-
options.hipo_ordering != kHighsChooseString) {
560-
highsLogUser(options.log_options, HighsLogType::kError,
561-
"Unknown value of option %s\n", kHipoOrderingString.c_str());
562-
model_status = HighsModelStatus::kSolveError;
563-
return HighsStatus::kError;
564-
}
565-
hipo_options.ordering = options.hipo_ordering;
566-
567-
// block size option
568-
hipo_options.block_size = options.hipo_block_size;
569478

570-
hipo.setOptions(hipo_options);
479+
hipo.setOptions(options);
571480
hipo.setTimer(timer);
572481
hipo.setCallback(callback);
573482

highs/ipm/hipo/ipm/FactorHiGHSSolver.cpp

Lines changed: 89 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -452,10 +452,10 @@ Int FactorHiGHSSolver::chooseNla() {
452452

453453
// Decision may be forced by failures
454454
if (failure_NE && !failure_AS) {
455-
options_.nla = kOptionNlaAugmented;
455+
options_.nla = kHipoAugmentedString;
456456
log_stream << textline("Newton system:") << "AS preferred (NE failed)\n";
457457
} else if (failure_AS && !failure_NE) {
458-
options_.nla = kOptionNlaNormEq;
458+
options_.nla = kHipoNormalEqString;
459459
log_stream << textline("Newton system:") << "NE preferred (AS failed)\n";
460460
} else if (failure_AS && failure_NE) {
461461
if (overflow_AS && overflow_NE)
@@ -483,18 +483,18 @@ Int FactorHiGHSSolver::chooseNla() {
483483

484484
if (NE_much_more_expensive ||
485485
(sn_AS_larger_than_NE && AS_not_too_expensive)) {
486-
options_.nla = kOptionNlaAugmented;
486+
options_.nla = kHipoAugmentedString;
487487
log_stream << textline("Newton system:") << "AS preferred\n";
488488
} else {
489-
options_.nla = kOptionNlaNormEq;
489+
options_.nla = kHipoNormalEqString;
490490
log_stream << textline("Newton system:") << "NE preferred\n";
491491
}
492492
}
493493

494494
log_.print(log_stream);
495495

496496
if (status == kStatusOk) {
497-
if (options_.nla == kOptionNlaAugmented) {
497+
if (options_.nla == kHipoAugmentedString) {
498498
S_ = std::move(symb_AS);
499499
freeNEmemory();
500500
} else {
@@ -604,44 +604,38 @@ Int FactorHiGHSSolver::chooseOrdering(const std::vector<Int>& rows,
604604
Int FactorHiGHSSolver::setNla() {
605605
std::stringstream log_stream;
606606

607-
hipo::OptionNla nla = options_.nla;
608-
if (nla == kOptionNlaNormEq && model_.nonSeparableQp()) {
607+
if (options_.nla == kHipoNormalEqString && model_.nonSeparableQp()) {
609608
log_.printw("Normal equations not available for non-separable QP\n");
610-
nla = kOptionNlaChoose;
609+
options_.nla = kHighsChooseString;
611610
}
612611

613-
switch (nla) {
614-
case kOptionNlaAugmented: {
615-
Int status = analyseAS(S_);
616-
if (status == kStatusOverflow) {
617-
log_.printe("AS requested, integer overflow\n");
618-
return kStatusOverflow;
619-
} else if (status) {
620-
log_.printe("AS requested, failed analyse phase\n");
621-
return kStatusErrorAnalyse;
622-
}
623-
log_stream << textline("Newton system:") << "AS requested\n";
624-
break;
612+
if (options_.nla == kHipoAugmentedString) {
613+
Int status = analyseAS(S_);
614+
if (status == kStatusOverflow) {
615+
log_.printe("AS requested, integer overflow\n");
616+
return kStatusOverflow;
617+
} else if (status) {
618+
log_.printe("AS requested, failed analyse phase\n");
619+
return kStatusErrorAnalyse;
625620
}
626-
627-
case kOptionNlaNormEq: {
628-
Int status = analyseNE(S_);
629-
if (status == kStatusOverflow) {
630-
log_.printe("NE requested, integer overflow\n");
631-
return kStatusOverflow;
632-
} else if (status) {
633-
log_.printe("NE requested, failed analyse phase\n");
634-
return kStatusErrorAnalyse;
635-
}
636-
log_stream << textline("Newton system:") << "NE requested\n";
637-
break;
621+
log_stream << textline("Newton system:") << "AS requested\n";
622+
623+
} else if (options_.nla == kHipoNormalEqString) {
624+
Int status = analyseNE(S_);
625+
if (status == kStatusOverflow) {
626+
log_.printe("NE requested, integer overflow\n");
627+
return kStatusOverflow;
628+
} else if (status) {
629+
log_.printe("NE requested, failed analyse phase\n");
630+
return kStatusErrorAnalyse;
638631
}
632+
log_stream << textline("Newton system:") << "NE requested\n";
639633

640-
case kOptionNlaChoose: {
641-
if (Int status = chooseNla()) return status;
642-
break;
643-
}
644-
}
634+
} else if (options_.nla == kHighsChooseString) {
635+
if (Int status = chooseNla()) return status;
636+
637+
} else
638+
assert(1 == 0);
645639

646640
log_.print(log_stream);
647641

@@ -656,81 +650,74 @@ void FactorHiGHSSolver::setParallel() {
656650
std::stringstream log_stream;
657651
log_stream << textline("Parallelism:");
658652

659-
switch (options_.parallel) {
660-
case kOptionParallelOff:
661-
log_stream << "None requested\n";
662-
break;
663-
case kOptionParallelOn:
653+
if (options_.parallel == kHighsOffString) {
654+
log_stream << "None requested\n";
655+
} else if (options_.parallel == kHighsOnString) {
656+
if (options_.parallel_type == kHipoBothString) {
664657
parallel_tree = true;
665658
parallel_node = true;
666659
log_stream << "Full requested\n";
667-
break;
668-
case kOptionParallelChoose: {
669-
#ifdef HIPO_USES_APPLE_BLAS
670-
// Blas on Apple do not work well with parallel_node, but parallel_tree
671-
// seems to always be beneficial.
672-
parallel_node = false;
660+
} else if (options_.parallel_type == kHipoTreeString) {
673661
parallel_tree = true;
674-
#else
675-
// Otherwise, parallel_node is active because it is triggered only if the
676-
// frontal matrix is large enough anyway.
662+
log_stream << "Tree requested\n";
663+
} else if (options_.parallel_type == kHipoNodeString) {
677664
parallel_node = true;
665+
log_stream << "Node requested\n";
666+
} else
667+
assert(1 == 0);
678668

679-
// parallel_tree instead is chosen with a heuristic
680-
681-
double tree_speedup = S_.flops() / S_.critops();
682-
double sn_size = (double)S_.size() / S_.sn();
683-
684-
bool enough_sn = S_.sn() > kMinNumberSn;
685-
bool enough_flops = S_.flops() > kLargeFlopsThresh;
686-
bool speedup_is_large = tree_speedup > kLargeSpeedupThresh;
687-
bool sn_are_large = sn_size > kLargeSnThresh;
688-
bool sn_are_not_small = sn_size > kSmallSnThresh;
689-
690-
// parallel_tree is active if the supernodes are large, or if there is a
691-
// large expected speedup and the supernodes are not too small, provided
692-
// that the number of flops and supernodes is not too small.
693-
if (enough_sn && enough_flops &&
694-
(sn_are_large || (speedup_is_large && sn_are_not_small))) {
695-
parallel_tree = true;
696-
}
669+
} else if (options_.parallel == kHighsChooseString) {
670+
#ifdef HIPO_USES_APPLE_BLAS
671+
// Blas on Apple do not work well with parallel_node, but parallel_tree
672+
// seems to always be beneficial.
673+
parallel_node = false;
674+
parallel_tree = true;
675+
#else
676+
// Otherwise, parallel_node is active because it is triggered only if the
677+
// frontal matrix is large enough anyway.
678+
parallel_node = true;
679+
680+
// parallel_tree instead is chosen with a heuristic
681+
682+
double tree_speedup = S_.flops() / S_.critops();
683+
double sn_size = (double)S_.size() / S_.sn();
684+
685+
bool enough_sn = S_.sn() > kMinNumberSn;
686+
bool enough_flops = S_.flops() > kLargeFlopsThresh;
687+
bool speedup_is_large = tree_speedup > kLargeSpeedupThresh;
688+
bool sn_are_large = sn_size > kLargeSnThresh;
689+
bool sn_are_not_small = sn_size > kSmallSnThresh;
690+
691+
// parallel_tree is active if the supernodes are large, or if there is a
692+
// large expected speedup and the supernodes are not too small, provided
693+
// that the number of flops and supernodes is not too small.
694+
if (enough_sn && enough_flops &&
695+
(sn_are_large || (speedup_is_large && sn_are_not_small))) {
696+
parallel_tree = true;
697+
}
697698
#endif
698699

699-
// If serial memory is too large, switch off tree parallelism to avoid
700-
// running out of memory
701-
double num_GB = S_.storage() / 1024 / 1024 / 1024;
702-
if (num_GB > kLargeStorageGB) {
703-
parallel_tree = false;
704-
}
700+
// If serial memory is too large, switch off tree parallelism to avoid
701+
// running out of memory
702+
double num_GB = S_.storage() / 1024 / 1024 / 1024;
703+
if (num_GB > kLargeStorageGB) {
704+
parallel_tree = false;
705+
}
705706

706-
// switch off tree parallelism if depth of recursion is too large
707-
if (S_.depth() > kMaxTreeDepth) parallel_tree = false;
708-
709-
if (parallel_tree && parallel_node) {
710-
options_.parallel = kOptionParallelOn;
711-
log_stream << "Full preferred\n";
712-
} else if (parallel_tree && !parallel_node) {
713-
options_.parallel = kOptionParallelTreeOnly;
714-
log_stream << "Tree preferred\n";
715-
} else if (!parallel_tree && parallel_node) {
716-
options_.parallel = kOptionParallelNodeOnly;
717-
log_stream << "Node preferred\n";
718-
} else {
719-
options_.parallel = kOptionParallelOff;
720-
log_stream << "None preferred\n";
721-
}
707+
// switch off tree parallelism if depth of recursion is too large
708+
if (S_.depth() > kMaxTreeDepth) parallel_tree = false;
722709

723-
break;
724-
}
725-
case kOptionParallelTreeOnly:
726-
parallel_tree = true;
727-
log_stream << "Tree requested\n";
728-
break;
729-
case kOptionParallelNodeOnly:
730-
parallel_node = true;
731-
log_stream << "Node requested\n";
732-
break;
733-
}
710+
if (parallel_tree && parallel_node)
711+
log_stream << "Full preferred\n";
712+
else if (parallel_tree && !parallel_node)
713+
log_stream << "Tree preferred\n";
714+
else if (!parallel_tree && parallel_node)
715+
log_stream << "Node preferred\n";
716+
else
717+
log_stream << "None preferred\n";
718+
719+
} else
720+
assert(1 == 0);
734721

735722
log_.print(log_stream);
736723
S_.setParallel(parallel_tree, parallel_node);

highs/ipm/hipo/ipm/Info.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,6 @@ struct Info {
3333
// Number of correctors used
3434
Int correctors;
3535

36-
// Nla option used
37-
OptionNla option_nla;
38-
39-
// Parallel option used
40-
OptionParallel option_par;
41-
4236
// Total times to form matrix, factorise and solve linear systems
4337
double analyse_NE_time{};
4438
double analyse_AS_time{};

0 commit comments

Comments
 (0)