Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ It fails on any failure not listed in `testdata/pulp_known_failures.txt`.
node bound propagation, reduced-cost fixing per incumbent, SOS1/2, one
restart inheriting cuts/fixings/probes; periodic in-tree rounds of the
globally-valid cut families with cold-restarted open nodes.
- **Threads** (`-threads N`, CBC's opportunistic parallel B&B): N workers over
a shared node heap/incumbent/pseudocosts, each with its own problem copy and
LP; warm bases cross threads factorization-free (as CBC's CoinWarmStartBasis)
and the receiver refactorizes. Serial (`N<=1`) runs the same code path
bit-identically. Tree-heavy instances scale near-linearly (8.4x at 8
threads on a 90x30 multi-knapsack); dive-dominated trees gain what CBC
gains (020: 1.3x at 4 threads vs CBC's 1.25x). In-tree cuts stay
serial-only.
- **Branching**: CBC reliability branching (pseudocosts, `numberBeforeTrust`=10,
capped strong-branch probes, `maxStrong`=5, CBC score) + strong-branch fixing.
- **Heuristics** (reduced-sub-problem first, as CBC's mini branch and bound):
Expand Down
8 changes: 7 additions & 1 deletion cmd/cbc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
// section: cuts/presolve/threads only affect performance, not the answer.
var valueOnlyFlags = map[string]bool{
"presolve": true, "gomory": true, "knapsack": true, "probing": true,
"cuts": true, "threads": true, "strong": true, "timemode": true,
"cuts": true, "strong": true, "timemode": true,
"printingoptions": true,
}

Expand Down Expand Up @@ -56,6 +56,7 @@ func run(args []string) error {
var solutionFile, mipsFile string
maximize := false
lpOnly := false
threads := 0
// GapAbs 1e-5 = CBC's default cutoff increment (CbcCutoffIncrement):
// nodes within 1e-5 of the incumbent are pruned, as real CBC does
limits := mip.Limits{GapRel: 1e-9, GapAbs: 1e-5}
Expand Down Expand Up @@ -91,6 +92,10 @@ func run(args []string) error {
if v, err := strconv.ParseFloat(next(), 64); err == nil {
limits.GapAbs = v
}
case "threads":
if v, err := strconv.Atoi(next()); err == nil {
threads = v
}
case "maxnodes":
if v, err := strconv.Atoi(next()); err == nil {
limits.MaxNodes = v
Expand Down Expand Up @@ -138,6 +143,7 @@ func run(args []string) error {
} else {
model := mip.New(p)
model.Limits = limits
model.Threads = threads
res = model.Solve()
}

Expand Down
Loading