Files
ortools-clone/ortools/set_cover/capacity_model.h
Corentin Le Molgat b4b226801b update include guards
2025-11-05 11:54:02 +01:00

156 lines
5.6 KiB
C++

// Copyright 2010-2025 Google LLC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ORTOOLS_SET_COVER_CAPACITY_MODEL_H_
#define ORTOOLS_SET_COVER_CAPACITY_MODEL_H_
#include <cmath>
#include <cstdint>
#include <limits>
#include <vector>
#include "absl/log/check.h"
#include "ortools/base/strong_int.h"
#include "ortools/base/strong_vector.h"
#include "ortools/set_cover/base_types.h"
#include "ortools/set_cover/capacity.pb.h"
#include "ortools/set_cover/set_cover_model.h"
// Representation class for the capacity side-constraint for a weighted
// set-covering problem.
//
// This constraint restricts the selection of elements within subsets that
// respect the constraint. Such a constraint can mix elements in any subset.
//
// Using the same mixed-integer-programming formulation as `set_cover_model.h`,
// this class corresponds to the following constraint:
// min_capacity <= \sum_{e in elements} weight_e * x_e <= max_capacity
namespace operations_research {
// Basic type for weights. For now, the same as `Cost` for the set covering.
using CapacityWeight = int64_t;
// Term index in a capacity constraint.
DEFINE_STRONG_INT_TYPE(CapacityTermIndex, BaseInt);
// The terms are represented as three aligned vectors: the element, the subset,
// and the weight. Each vector is indexed by the term.
using CapacityElements =
util_intops::StrongVector<CapacityTermIndex, ElementIndex>;
using CapacitySubsets =
util_intops::StrongVector<CapacityTermIndex, SubsetIndex>;
using CapacityWeights =
util_intops::StrongVector<CapacityTermIndex, CapacityWeight>;
// Main class for describing a single capacity constraint in the context of a
// set-covering problem.
class CapacityModel {
public:
// Builds an empty capacity constraint.
//
// Use either WithMinimumWeight or WithMaximumWeight to set only one of the
// two bounds.
CapacityModel(CapacityWeight min, CapacityWeight max)
: elements_(),
subsets_(),
weights_(),
min_capacity_(min),
max_capacity_(max) {
// At least one bound must be set. Otherwise, the constraint is vacuous.
CHECK(min_capacity_ != std::numeric_limits<CapacityWeight>::min() ||
max_capacity_ != std::numeric_limits<CapacityWeight>::max());
}
static CapacityModel WithMinimumWeight(CapacityWeight min) {
return CapacityModel(min, std::numeric_limits<CapacityWeight>::max());
}
static CapacityModel WithMaximumWeight(CapacityWeight max) {
return CapacityModel(std::numeric_limits<CapacityWeight>::min(), max);
}
// Returns the current number of terms in the constraint.
BaseInt num_terms() const { return elements_.size(); }
// Returns the range of terms.
util_intops::StrongIntRange<CapacityTermIndex> TermRange() const {
return util_intops::StrongIntRange<CapacityTermIndex>(
CapacityTermIndex(num_terms()));
}
// Adds a new term to the constraint.
void AddTerm(SubsetIndex subset, ElementIndex element, CapacityWeight weight);
// Returns the element, subset, or capacity of the given term.
ElementIndex GetTermElementIndex(CapacityTermIndex term) const {
return elements_[term];
}
SubsetIndex GetTermSubsetIndex(CapacityTermIndex term) const {
return subsets_[term];
}
CapacityWeight GetTermCapacityWeight(CapacityTermIndex term) const {
return weights_[term];
}
// Sets the lower/upper bounds for the constraint.
// This will CHECK-fail if a capacity is a NaN.
void SetMinimumCapacity(CapacityWeight min_capacity);
void SetMaximumCapacity(CapacityWeight max_capacity);
// Returns the lower/upper bounds for the constraint.
CapacityWeight GetMinimumCapacity() const { return min_capacity_; }
CapacityWeight GetMaximumCapacity() const { return max_capacity_; }
// Returns true if the constraint is feasible, i.e. there is at least one
// assignment that satisfies the constraint.
bool ComputeFeasibility() const;
// Reserves num_terms terms in the model.
void ReserveNumTerms(BaseInt num_terms) {
ReserveNumTerms(CapacityTermIndex(num_terms));
}
void ReserveNumTerms(CapacityTermIndex num_terms) {
subsets_.reserve(num_terms);
elements_.reserve(num_terms);
weights_.reserve(num_terms);
}
// Returns the model as a CapacityConstraintProto.
//
// The function is not const because the terms need to be sorted for the
// representation as a protobuf to be canonical.
CapacityConstraintProto ExportModelAsProto();
// Imports the model from a CapacityConstraintProto.
void ImportModelFromProto(const CapacityConstraintProto& proto);
private:
// The terms in the constraint.
CapacityElements elements_;
CapacitySubsets subsets_;
CapacityWeights weights_;
// The bounds of the constraint. Both are always active at the same time.
// An inactive constraint corresponds to a capacity set to ±∞.
CapacityWeight min_capacity_;
CapacityWeight max_capacity_;
// Returns a canonical indexing of the constraint, i.e. reading the terms in
// this order yields the order that is explained in the proto.
std::vector<CapacityTermIndex> CanonicalIndexing();
};
} // namespace operations_research
#endif // ORTOOLS_SET_COVER_CAPACITY_MODEL_H_