added const int array storage class
This commit is contained in:
@@ -237,6 +237,7 @@ $(LIBPREFIX)linear_solver.$(LIBSUFFIX): $(LINEAR_SOLVER_LIB_OS)
|
||||
UTIL_LIB_OS=\
|
||||
objs/bitset.$O \
|
||||
objs/cached_log.$O \
|
||||
objs/const_int_array.$O \
|
||||
objs/xml_helper.$O
|
||||
|
||||
objs/bitset.$O:util/bitset.cc
|
||||
@@ -245,6 +246,9 @@ objs/bitset.$O:util/bitset.cc
|
||||
objs/cached_log.$O:util/cached_log.cc
|
||||
$(CCC) $(CFLAGS) -c util/cached_log.cc $(OBJOUT)objs/cached_log.$O
|
||||
|
||||
objs/const_int_array.$O:util/const_int_array.cc
|
||||
$(CCC) $(CFLAGS) -c util/const_int_array.cc $(OBJOUT)objs/const_int_array.$O
|
||||
|
||||
objs/xml_helper.$O:util/xml_helper.cc
|
||||
$(CCC) $(CFLAGS) -c util/xml_helper.cc $(OBJOUT)objs/xml_helper.$O
|
||||
|
||||
|
||||
230
util/const_int_array.cc
Normal file
230
util/const_int_array.cc
Normal file
@@ -0,0 +1,230 @@
|
||||
// Copyright 2010-2011 Google
|
||||
// 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.
|
||||
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include "base/stringprintf.h"
|
||||
#include "util/const_int_array.h"
|
||||
#include "util/bitset.h"
|
||||
|
||||
namespace operations_research {
|
||||
ConstIntArray::ConstIntArray(int64 v0)
|
||||
: data_(new vector<int64>(1)), scanned_(false), status_(0) {
|
||||
(*data_)[0] = v0;
|
||||
}
|
||||
|
||||
ConstIntArray::ConstIntArray(int64 v0, int64 v1)
|
||||
: data_(new vector<int64>(2)), scanned_(false), status_(0) {
|
||||
(*data_)[0] = v0;
|
||||
(*data_)[1] = v1;
|
||||
}
|
||||
|
||||
ConstIntArray::ConstIntArray(int64 v0, int64 v1, int64 v2)
|
||||
: data_(new vector<int64>(3)), scanned_(false), status_(0) {
|
||||
(*data_)[0] = v0;
|
||||
(*data_)[1] = v1;
|
||||
(*data_)[2] = v2;
|
||||
}
|
||||
|
||||
ConstIntArray::ConstIntArray(int64 v0, int64 v1, int64 v2, int64 v3)
|
||||
: data_(new vector<int64>(4)), scanned_(false), status_(0) {
|
||||
(*data_)[0] = v0;
|
||||
(*data_)[1] = v1;
|
||||
(*data_)[2] = v2;
|
||||
(*data_)[3] = v3;
|
||||
}
|
||||
|
||||
ConstIntArray::ConstIntArray(int64 v0, int64 v1, int64 v2, int64 v3, int64 v4)
|
||||
: data_(new vector<int64>(5)), scanned_(false), status_(0) {
|
||||
(*data_)[0] = v0;
|
||||
(*data_)[1] = v1;
|
||||
(*data_)[2] = v2;
|
||||
(*data_)[3] = v3;
|
||||
(*data_)[4] = v4;
|
||||
}
|
||||
|
||||
ConstIntArray::ConstIntArray(int64 v0, int64 v1, int64 v2, int64 v3, int64 v4,
|
||||
int64 v5)
|
||||
: data_(new vector<int64>(6)), scanned_(false), status_(0) {
|
||||
(*data_)[0] = v0;
|
||||
(*data_)[1] = v1;
|
||||
(*data_)[2] = v2;
|
||||
(*data_)[3] = v3;
|
||||
(*data_)[4] = v4;
|
||||
(*data_)[5] = v5;
|
||||
}
|
||||
|
||||
ConstIntArray::ConstIntArray(const vector<int64>& data)
|
||||
: data_(new vector<int64>(data)),
|
||||
scanned_(false),
|
||||
status_(0) {}
|
||||
|
||||
ConstIntArray::ConstIntArray(const vector<int>& data)
|
||||
: data_(new vector<int64>(data.size())),
|
||||
scanned_(false),
|
||||
status_(0) {
|
||||
for (int i = 0; i < data.size(); ++i) {
|
||||
(*data_)[i] = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
ConstIntArray::ConstIntArray(const int64 * const data, int size)
|
||||
: data_(new vector<int64>(size)), scanned_(false), status_(0) {
|
||||
CHECK_GT(size, 0);
|
||||
CHECK_NOTNULL(data);
|
||||
memcpy((data_->data()), data, size * sizeof(*data));
|
||||
}
|
||||
|
||||
ConstIntArray::ConstIntArray(const int * const data, int size)
|
||||
: data_(new vector<int64>(size)), scanned_(false), status_(0) {
|
||||
CHECK_GT(size, 0);
|
||||
CHECK_NOTNULL(data);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
(*data_)[i] = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
ConstIntArray::ConstIntArray(vector<int64>* data)
|
||||
: data_(data), scanned_(false), status_(0) {
|
||||
CHECK_GT(data->size(), 0);
|
||||
}
|
||||
|
||||
ConstIntArray::~ConstIntArray() {}
|
||||
|
||||
vector<int64>* ConstIntArray::Release() {
|
||||
return data_.release();
|
||||
}
|
||||
|
||||
int ConstIntArray::size() const {
|
||||
CHECK_NOTNULL(data_.get());
|
||||
return data_->size();
|
||||
}
|
||||
|
||||
vector<int64>* ConstIntArray::SortedCopy(bool increasing) const {
|
||||
vector<int64>* new_data = new vector<int64>(*data_);
|
||||
if (increasing) {
|
||||
std::sort(new_data->begin(), new_data->end());
|
||||
} else {
|
||||
std::sort(new_data->begin(), new_data->end(), std::greater<int64>());
|
||||
}
|
||||
return new_data;
|
||||
}
|
||||
|
||||
vector<int64>*
|
||||
ConstIntArray::SortedCopyWithoutDuplicates(bool increasing) const {
|
||||
vector<int64>* new_data = new vector<int64>(*data_);
|
||||
if (increasing) {
|
||||
std::sort(new_data->begin(), new_data->end());
|
||||
} else {
|
||||
std::sort(new_data->begin(), new_data->end(), std::greater<int64>());
|
||||
}
|
||||
int duplicates = 0;
|
||||
for (int i = 0; i < data_->size() - 1; ++i) {
|
||||
duplicates += (*new_data)[i] == (*new_data)[i + 1];
|
||||
}
|
||||
if (duplicates == 0) {
|
||||
return new_data;
|
||||
} else {
|
||||
const int final_size = data_->size() - duplicates;
|
||||
vector<int64>* final_data = new vector<int64>(final_size);
|
||||
(*final_data)[0] = (*new_data)[0];
|
||||
int counter = 1;
|
||||
for (int i = 1; i < data_->size(); ++i) {
|
||||
if ((*new_data)[i] != (*new_data)[i - 1]) {
|
||||
(*final_data)[counter++] = (*new_data)[i];
|
||||
}
|
||||
}
|
||||
CHECK_EQ(final_size, counter);
|
||||
delete new_data;
|
||||
return final_data;
|
||||
}
|
||||
}
|
||||
|
||||
bool ConstIntArray::Equals(const ConstIntArray& other) {
|
||||
if (data_->size() != other.data_->size()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < data_->size(); ++i) {
|
||||
if ((*data_)[i] != other[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConstIntArray::HasProperty(Property info) {
|
||||
const int kBitsInChar = 8;
|
||||
DCHECK_GE(info, 0);
|
||||
DCHECK_LT(info, kBitsInChar * sizeof(status_));
|
||||
CHECK_NOTNULL(data_.get());
|
||||
if (!scanned_) {
|
||||
Scan();
|
||||
}
|
||||
return IsBitSet64(&status_, info);
|
||||
}
|
||||
|
||||
void ConstIntArray::AndProperty(Property info, bool value) {
|
||||
if (!value) {
|
||||
ClearBit64(&status_, info);
|
||||
}
|
||||
}
|
||||
|
||||
void ConstIntArray::Scan() {
|
||||
DCHECK(!scanned_);
|
||||
status_ = IntervalDown64(NUM_PROPERTY);
|
||||
scanned_ = true;
|
||||
if (data_.get() == NULL) { // After a release.
|
||||
return;
|
||||
}
|
||||
const int64 first = (*data_)[0];
|
||||
AndProperty(IS_POSITIVE, first > 0);
|
||||
AndProperty(IS_NEGATIVE, first < 0);
|
||||
AndProperty(IS_NEGATIVE_OR_NULL, first <= 0);
|
||||
AndProperty(IS_POSITIVE_OR_NULL, first >= 0);
|
||||
AndProperty(IS_BOOLEAN, first == 0 || first == 1);
|
||||
|
||||
for (int i = 1; i < data_->size(); ++i) {
|
||||
const int64 previous = (*data_)[i - 1];
|
||||
const int64 current = (*data_)[i];
|
||||
AndProperty(IS_CONSTANT, current == previous);
|
||||
AndProperty(IS_DECREASING, previous >= current);
|
||||
AndProperty(IS_STRICTLY_DECREASING, previous > current);
|
||||
AndProperty(IS_INCREASING, previous <= current);
|
||||
AndProperty(IS_STRICTLY_INCREASING, previous < current);
|
||||
AndProperty(IS_BOOLEAN, current == 0 || current == 1);
|
||||
AndProperty(IS_POSITIVE, current > 0);
|
||||
AndProperty(IS_NEGATIVE, current < 0);
|
||||
AndProperty(IS_NEGATIVE_OR_NULL, current <= 0);
|
||||
AndProperty(IS_POSITIVE_OR_NULL, current >= 0);
|
||||
if (!status_) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string ConstIntArray::DebugString() const {
|
||||
if (data_.get() == NULL) {
|
||||
return "Released ConstIntArray";
|
||||
}
|
||||
string result = "[";
|
||||
for (int i = 0; i < data_->size(); ++i) {
|
||||
StringAppendF(&result, StringPrintf("%lld", (*data_)[i]).c_str());
|
||||
if (i != data_->size() - 1) {
|
||||
StringAppendF(&result, ", ");
|
||||
}
|
||||
}
|
||||
StringAppendF(&result, "]");
|
||||
return result;
|
||||
}
|
||||
} // namespace operations_research
|
||||
136
util/const_int_array.h
Normal file
136
util/const_int_array.h
Normal file
@@ -0,0 +1,136 @@
|
||||
// Copyright 2010-2011 Google
|
||||
// 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 UTIL_CONST_INT_ARRAY_H_
|
||||
#define UTIL_CONST_INT_ARRAY_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "base/basictypes.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/scoped_ptr.h"
|
||||
|
||||
namespace operations_research {
|
||||
// This class is used to store constant copies of int64 arrays inside
|
||||
// constraints or expression. When constructed with a C array or a
|
||||
// vector, The const int array will make a internal copy and own that
|
||||
// copy. It will not take ownership of the vector/array which can be
|
||||
// deleted afterwards. This follows the semantics of constraints and
|
||||
// expressions which store a read-only copy of the data.
|
||||
//
|
||||
// Its goals are:
|
||||
// - to unify the construction code across the optimization libraries.
|
||||
// - to provide one code to scan these arrays and compute given properties like
|
||||
// monotonicity.
|
||||
//
|
||||
// As const int arrays provide scanning capabilities, the code inside
|
||||
// a constraint and its factory looks like:
|
||||
//
|
||||
// IntExpr* MakeMyExpr(const vector<int64>& values) {
|
||||
// ConstIntArray copy(values);
|
||||
// if (copy.Status(ConstIntArray::IS_INCREASING)) {
|
||||
// return new MyOptimizedExpr(copy.Release());
|
||||
// } else {
|
||||
// return new MyGenericExpr(copy.Release());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// With:
|
||||
// class MyOptimizedExpr : IntExpr {
|
||||
// public:
|
||||
// MyOptimizedExpr(vector<int64>* data) : values_(data) {}
|
||||
// private:
|
||||
// ConstIntArray values_;
|
||||
// };
|
||||
class ConstIntArray {
|
||||
public:
|
||||
// These describe static properties of the int64 array.
|
||||
enum Property {
|
||||
IS_CONSTANT = 0,
|
||||
IS_STRICTLY_INCREASING = 1,
|
||||
IS_INCREASING = 2,
|
||||
IS_STRICTLY_DECREASING = 3,
|
||||
IS_DECREASING = 4,
|
||||
IS_BOOLEAN = 5, // in {0, 1}
|
||||
IS_POSITIVE = 6, // > 0
|
||||
IS_NEGATIVE = 7, // < 0
|
||||
IS_POSITIVE_OR_NULL = 8, // >= 0
|
||||
IS_NEGATIVE_OR_NULL = 9, // <= 0
|
||||
NUM_PROPERTY = 10 // Sentinel.
|
||||
};
|
||||
|
||||
// These constructors remove the needs to explicitely create an
|
||||
// intermediate data storage.
|
||||
explicit ConstIntArray(int64 v0);
|
||||
ConstIntArray(int64 v0, int64 v1);
|
||||
ConstIntArray(int64 v0, int64 v1, int64 v2);
|
||||
ConstIntArray(int64 v0, int64 v1, int64 v2, int64 v3);
|
||||
ConstIntArray(int64 v0, int64 v1, int64 v2, int64 v3, int64 v4);
|
||||
ConstIntArray(int64 v0, int64 v1, int64 v2, int64 v3, int64 v4, int64 v5);
|
||||
|
||||
// Build from a vector. Copy the data internally.
|
||||
explicit ConstIntArray(const vector<int64>& data);
|
||||
// Build from a vector. Copy the data internally.
|
||||
explicit ConstIntArray(const vector<int>& data);
|
||||
// Build from a C array. Copy the data internally.
|
||||
ConstIntArray(const int64* const data, int size);
|
||||
// Build from a C array. Copy the data internally.
|
||||
ConstIntArray(const int* const data, int size);
|
||||
// Build from a pointer to a vector (usually created by the
|
||||
// Release(), or SortedCopy() method). This call will take ownership of
|
||||
// the data and not make a copy.
|
||||
explicit ConstIntArray(vector<int64>* data);
|
||||
|
||||
~ConstIntArray();
|
||||
|
||||
// Pretty print.
|
||||
string DebugString() const;
|
||||
|
||||
// This code release the ownership of the data into the returned vector.
|
||||
// After this method is called, data_ points to a null vector.
|
||||
vector<int64>* Release();
|
||||
|
||||
// This will create a new data holder with the sorted array.
|
||||
vector<int64>* SortedCopy(bool increasing) const;
|
||||
|
||||
// This will create a new data holder with the sorted array where
|
||||
// the duplicate values have been removed.
|
||||
vector<int64>* SortedCopyWithoutDuplicates(bool increasing) const;
|
||||
|
||||
// Equality test.
|
||||
bool Equals(const ConstIntArray& other);
|
||||
|
||||
// Size of the array. This is not valid after Release() has been called.
|
||||
int size() const;
|
||||
|
||||
// Operator to access the data at the given index. This is not valid
|
||||
// after a release.
|
||||
int64 operator[](int64 index) const {
|
||||
CHECK_NOTNULL(data_.get());
|
||||
return (*data_)[index];
|
||||
}
|
||||
|
||||
// Check the status of a given info bit. It will scan the array on demand.
|
||||
// This is not valid after Release() has been called.
|
||||
bool HasProperty(Property info);
|
||||
private:
|
||||
void AndProperty(Property info, bool value);
|
||||
void Scan();
|
||||
scoped_ptr<vector<int64> > data_;
|
||||
bool scanned_;
|
||||
uint64 status_;
|
||||
DISALLOW_COPY_AND_ASSIGN(ConstIntArray);
|
||||
};
|
||||
} // namespace operations_research
|
||||
|
||||
#endif // UTIL_CONST_INT_ARRAY_H_
|
||||
Reference in New Issue
Block a user