Skip to content

Commit

Permalink
backport from main: sat, graph, lp_data, glop
Browse files Browse the repository at this point in the history
  • Loading branch information
lperron committed Sep 13, 2024
1 parent ed94162 commit 701cc87
Show file tree
Hide file tree
Showing 51 changed files with 2,483 additions and 1,217 deletions.
62 changes: 60 additions & 2 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ git_repository(
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
bazel_skylib_workspace()

http_archive(
name = "bazel_features",
sha256 = "cec7fbc7bce6597cf2e83e01ddd9328a1bb057dc1a3092745238f49d3301ab5a",
strip_prefix = "bazel_features-1.12.0",
url = "https://github.com/bazel-contrib/bazel_features/releases/download/v1.12.0/bazel_features-v1.12.0.tar.gz",
)

load("@bazel_features//:deps.bzl", "bazel_features_deps")
bazel_features_deps()

## Bazel rules.
git_repository(
name = "platforms",
Expand All @@ -41,7 +51,7 @@ git_repository(

git_repository(
name = "rules_proto",
tag = "5.3.0-21.7",
tag = "6.0.0",
remote = "https://github.com/bazelbuild/rules_proto.git",
)

Expand Down Expand Up @@ -110,6 +120,12 @@ git_repository(
load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
protobuf_deps()

load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies")
rules_proto_dependencies()

load("@rules_proto//proto:toolchains.bzl", "rules_proto_toolchains")
rules_proto_toolchains()

## Solvers
http_archive(
name = "glpk",
Expand Down Expand Up @@ -147,7 +163,7 @@ cc_library(
name = 'eigen3',
srcs = [],
includes = ['.'],
hdrs = glob(['Eigen/**']),
hdrs = glob(['Eigen/**', 'unsupported/**']),
defines = ["EIGEN_MPL2_ONLY",],
visibility = ['//visibility:public'],
)
Expand Down Expand Up @@ -318,3 +334,45 @@ git_repository(
tag = "v1.8.5",
remote = "https://github.com/google/benchmark.git",
)

# Go

http_archive(
name = "io_bazel_rules_go",
sha256 = "33acc4ae0f70502db4b893c9fc1dd7a9bf998c23e7ff2c4517741d4049a976f8",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.48.0/rules_go-v0.48.0.zip",
"https://github.com/bazelbuild/rules_go/releases/download/v0.48.0/rules_go-v0.48.0.zip",
],
)

http_archive(
name = "bazel_gazelle",
sha256 = "d76bf7a60fd8b050444090dfa2837a4eaf9829e1165618ee35dceca5cbdf58d5",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.37.0/bazel-gazelle-v0.37.0.tar.gz",
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.37.0/bazel-gazelle-v0.37.0.tar.gz",
],
)

load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
load("//:deps.bzl", "go_dependencies")
# gazelle:repository_macro deps.bzl%go_dependencies
go_dependencies()

load("@io_bazel_rules_go//go:deps.bzl", "go_download_sdk", "go_register_toolchains", "go_rules_dependencies")

go_rules_dependencies()

go_download_sdk(
name = "go_sdk_linux",
version = "1.22.4",
)

go_register_toolchains()

gazelle_dependencies(
go_env = {
"GOPROXY": "https://proxy.golang.org|direct",
},
)
8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module github.com/google/or-tools

go 1.22.2

require (
github.com/golang/glog v1.2.2
google.golang.org/protobuf v1.34.2
)
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY=
github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
62 changes: 31 additions & 31 deletions ortools/base/temp_path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,44 +39,44 @@ TempPath::TempPath(absl::string_view prefix) : path_(file::TempFile(prefix)) {
}

TempPath::TempPath(absl::string_view prefix, absl::Status* status)
: path_(file::TempFile(prefix)) {
: path_(file::TempFile(prefix)) {
*status = Init(kDefaultMode);
}

TempPath::TempPath(TempPath && rhs) : path_(std::move(rhs.path_)) {}
TempPath::TempPath(TempPath&& rhs) : path_(std::move(rhs.path_)) {}

TempPath& TempPath::operator=(TempPath&& rhs) {
TempPath tmp(std::move(*this));
path_ = std::move(rhs.path_);
return *this;
}
TempPath& TempPath::operator=(TempPath&& rhs) {
TempPath tmp(std::move(*this));
path_ = std::move(rhs.path_);
return *this;
}

TempPath::~TempPath() {}
TempPath::~TempPath() {}

TempPath* TempPath::Create(Location location) {
std::string dirname;
switch (location) {
case Local:
TempPath* TempPath::Create(Location location) {
std::string dirname;
switch (location) {
case Local:
dirname = file::TempFile("");
}
if (dirname.empty()) {
return nullptr;
}
absl::Status status;
TempPath* temp_path = new TempPath(dirname, &status);
if (!status.ok()) {
delete temp_path;
return nullptr;
}
return temp_path;
}

TempPath::TempPath(const std::string& dirname, file::Options options,
absl::Status* status)
: path_(dirname) {
*status = Init(options);
if (dirname.empty()) {
return nullptr;
}

absl::Status TempPath::Init(file::Options options) {
return file::RecursivelyCreateDir(path(), options);
absl::Status status;
TempPath* temp_path = new TempPath(dirname, &status);
if (!status.ok()) {
delete temp_path;
return nullptr;
}
return temp_path;
}

TempPath::TempPath(const std::string& dirname, file::Options options,
absl::Status* status)
: path_(dirname) {
*status = Init(options);
}

absl::Status TempPath::Init(file::Options options) {
return file::RecursivelyCreateDir(path(), options);
}
136 changes: 75 additions & 61 deletions ortools/glop/markowitz.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "ortools/lp_data/lp_types.h"
#include "ortools/lp_data/lp_utils.h"
#include "ortools/lp_data/sparse.h"
#include "ortools/lp_data/sparse_column.h"

namespace operations_research {
namespace glop {
Expand Down Expand Up @@ -175,51 +176,41 @@ void Markowitz::Clear() {
permuted_lower_.Clear();
permuted_upper_.Clear();
residual_matrix_non_zero_.Clear();
col_by_degree_.Clear();
examined_col_.clear();
num_fp_operations_ = 0;
is_col_by_degree_initialized_ = false;
}

namespace {
struct MatrixEntry {
RowIndex row;
ColIndex col;
Fractional coefficient;
MatrixEntry(RowIndex r, ColIndex c, Fractional coeff)
: row(r), col(c), coefficient(coeff) {}
bool operator<(const MatrixEntry& o) const {
return (row == o.row) ? col < o.col : row < o.row;
}
};

} // namespace

void Markowitz::ExtractSingletonColumns(
const CompactSparseMatrixView& basis_matrix, RowPermutation* row_perm,
ColumnPermutation* col_perm, int* index) {
SCOPED_TIME_STAT(&stats_);
std::vector<MatrixEntry> singleton_entries;
tmp_singleton_entries_.clear();
const ColIndex num_cols = basis_matrix.num_cols();
for (ColIndex col(0); col < num_cols; ++col) {
const ColumnView& column = basis_matrix.column(col);
const ColumnView column = basis_matrix.column(col);
if (column.num_entries().value() == 1) {
singleton_entries.push_back(
MatrixEntry(column.GetFirstRow(), col, column.GetFirstCoefficient()));
const RowIndex row = column.GetFirstRow();

// We temporary mark row perm (it will be filled below).
// If there is a tie, we will choose the lower column.
if ((*row_perm)[row] != kInvalidRow) continue;
(*row_perm)[row] = 0;

tmp_singleton_entries_.push_back(
MatrixEntry(row, col, column.GetFirstCoefficient()));
}
}

// Sorting the entries by row indices allows the row_permutation to be closer
// to identity which seems like a good idea.
std::sort(singleton_entries.begin(), singleton_entries.end());
for (const MatrixEntry e : singleton_entries) {
if ((*row_perm)[e.row] == kInvalidRow) {
(*col_perm)[e.col] = ColIndex(*index);
(*row_perm)[e.row] = RowIndex(*index);
lower_.AddDiagonalOnlyColumn(1.0);
upper_.AddDiagonalOnlyColumn(e.coefficient);
++(*index);
}
std::sort(tmp_singleton_entries_.begin(), tmp_singleton_entries_.end());
for (const MatrixEntry e : tmp_singleton_entries_) {
(*col_perm)[e.col] = ColIndex(*index);
(*row_perm)[e.row] = RowIndex(*index);
lower_.AddDiagonalOnlyColumn(1.0);
upper_.AddDiagonalOnlyColumn(e.coefficient);
++(*index);
}
stats_.basis_singleton_column_ratio.Add(static_cast<double>(*index) /
basis_matrix.num_rows().value());
Expand All @@ -246,7 +237,7 @@ void Markowitz::ExtractResidualSingletonColumns(
RowIndex row = kInvalidRow;
for (ColIndex col(0); col < num_cols; ++col) {
if ((*col_perm)[col] != kInvalidCol) continue;
const ColumnView& column = basis_matrix.column(col);
const ColumnView column = basis_matrix.column(col);
if (!IsResidualSingletonColumn(column, *row_perm, &row)) continue;
(*col_perm)[col] = ColIndex(*index);
(*row_perm)[row] = RowIndex(*index);
Expand Down Expand Up @@ -810,59 +801,82 @@ void MatrixNonZeroPattern::MergeIntoSorted(RowIndex pivot_row, RowIndex row) {
MergeSortedVectors(col_scratchpad_, &row_non_zero_[row]);
}

void ColumnPriorityQueue::Clear() {
col_degree_.clear();
col_index_.clear();
col_by_degree_.clear();
}

void ColumnPriorityQueue::Reset(int max_degree, ColIndex num_cols) {
Clear();
col_degree_.assign(num_cols, 0);
col_index_.assign(num_cols, -1);
col_by_degree_.resize(max_degree + 1);
degree_.assign(num_cols, 0);
col_by_degree_.assign(max_degree + 1, kInvalidCol);
min_degree_ = max_degree + 1;

// These are not used as long as the degree is zero.
prev_.resize(num_cols, kInvalidCol);
next_.resize(num_cols, kInvalidCol);
}

void ColumnPriorityQueue::Remove(ColIndex col, int32_t old_degree) {
DCHECK_NE(old_degree, 0);

const ColIndex old_next = next_[col];
const ColIndex old_prev = prev_[col];

// Remove.
if (old_next != -1) prev_[old_next] = old_prev;
if (old_prev == -1) {
DCHECK_EQ(col_by_degree_[old_degree], col);
col_by_degree_[old_degree] = old_next;
} else {
next_[old_prev] = old_next;
}

// Mark as removed.
degree_[col] = 0;
}

void ColumnPriorityQueue::Insert(ColIndex col, int32_t degree) {
DCHECK_EQ(degree_[col], 0);
DCHECK_NE(degree, 0);

const ColIndex new_next = col_by_degree_[degree];
next_[col] = new_next;
if (new_next != -1) {
prev_[new_next] = col;
}

col_by_degree_[degree] = col;
prev_[col] = kInvalidCol;
degree_[col] = degree;

min_degree_ = std::min(min_degree_, degree);
}

void ColumnPriorityQueue::PushOrAdjust(ColIndex col, int32_t degree) {
DCHECK_GE(degree, 0);
DCHECK_LT(degree, col_by_degree_.size());
DCHECK_GE(col, 0);
DCHECK_LT(col, col_degree_.size());
DCHECK_LT(col, degree_.size());

const int32_t old_degree = col_degree_[col];
const int32_t old_degree = degree_[col];
if (degree != old_degree) {
const int32_t old_index = col_index_[col];
if (old_index != -1) {
col_by_degree_[old_degree][old_index] = col_by_degree_[old_degree].back();
col_index_[col_by_degree_[old_degree].back()] = old_index;
col_by_degree_[old_degree].pop_back();
if (old_degree != 0) {
Remove(col, old_degree);
}
if (degree > 0) {
col_index_[col] = col_by_degree_[degree].size();
col_degree_[col] = degree;
col_by_degree_[degree].push_back(col);
min_degree_ = std::min(min_degree_, degree);
} else {
col_index_[col] = -1;
col_degree_[col] = 0;
if (degree != 0) {
Insert(col, degree);
}
}
}

ColIndex ColumnPriorityQueue::Pop() {
DCHECK_GE(min_degree_, 0);
DCHECK_LE(min_degree_, col_by_degree_.size());
ColIndex result = kInvalidCol;
const int limit = col_by_degree_.size();
while (true) {
if (min_degree_ == col_by_degree_.size()) return kInvalidCol;
if (!col_by_degree_[min_degree_].empty()) break;
if (min_degree_ == limit) return kInvalidCol;
result = col_by_degree_[min_degree_];
if (result != kInvalidCol) break;
min_degree_++;
}
const ColIndex col = col_by_degree_[min_degree_].back();
col_by_degree_[min_degree_].pop_back();
col_index_[col] = -1;
col_degree_[col] = 0;
return col;
Remove(result, min_degree_);
return result;
}

void SparseMatrixWithReusableColumnMemory::Reset(ColIndex num_cols) {
Expand Down
Loading

0 comments on commit 701cc87

Please sign in to comment.