Skip to content

Commit

Permalink
Move NameProvider to nl-reader #209
Browse files Browse the repository at this point in the history
  • Loading branch information
glebbelov committed Jun 15, 2023
1 parent 9368149 commit ad85002
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 71 deletions.
7 changes: 6 additions & 1 deletion doc/rst/components.rst
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,18 @@ it unless you need access to the full NL reader API, described below.

* `mp::NLHeader` stores problem information

* `mp::NameProvider` reads variable and constraint names
(see AMPL option ``auxfiles``),
or provides generic names otherwise

* `mp::ReadError`, `mp::BinaryReadError`

* `mp::arith::Kind`

* `mp::READ_BOUNDS_FIRST` can be passed as a flag to `mp::ReadNLFile`

* `mp::MAX_AMPL_OPTIONS` is the maximum number of options reserved for AMPL use in NL and SOL formats
* `mp::MAX_AMPL_OPTIONS` is the maximum number of options reserved
for AMPL use in NL and SOL formats



Expand Down
3 changes: 2 additions & 1 deletion include/mp/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@
#ifndef MP_COMMON_H_
#define MP_COMMON_H_

#include "mp/error.h" // for MP_ASSERT
#include <cstddef> // for std::size_t

#include "mp/error.h" // for MP_ASSERT

/** The mp namespace. */
namespace mp {

Expand Down
46 changes: 35 additions & 11 deletions include/mp/nl-reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -2131,6 +2131,13 @@ void ReadBinary(TextReader<> &reader, const NLHeader &header,
bin_reader, header, handler, flags).Read();
}


/// Reads names from the string *data* sending the names to the *handler*
/// object by calling ``handler.OnName(name)``. The name argument to
/// ``OnName`` is a ``fmt::StringRef`` object and the string it refers to
/// is not null-terminated.
/// Each name in the input string/file should be on a separate line
/// ended with a newline character ('\n') or "\r\n" (on Windows).
template <typename NameHandler>
void ReadNames(fmt::CStringRef filename, fmt::StringRef data,
NameHandler &handler) {
Expand All @@ -2141,8 +2148,7 @@ void ReadNames(fmt::CStringRef filename, fmt::StringRef data,
for (const char *ptr = start; ptr != end; ++ptr) {
if (*ptr == '\r') in_win_newline = true;
if (*ptr == '\n') {
handler.OnName(fmt::StringRef(start, ptr - start - in_win_newline));

handler.OnName(fmt::StringRef(start, ptr - start - in_win_newline));
start = ptr + 1;
++line;
in_win_newline = false;
Expand All @@ -2154,32 +2160,31 @@ void ReadNames(fmt::CStringRef filename, fmt::StringRef data,
}
}


/// A name file reader.
class NameReader {
private:
MemoryMappedFile<> mapped_file_;

public:
/// Reads names from the file *filename* sending the names to the *handler*
/// object by calling ``handler.OnName(name)``. The name argument to
/// ``OnName`` is a ``fmt::StringRef`` object and the string it refers to
/// is not null-terminated.
/// Each name in the input file should be on a separate line ended with a
/// newline character ('\n').
/// Reads names from file *filename*
/// by passing its contents to ReadNames().
template <typename NameHandler>
void Read(fmt::CStringRef filename, NameHandler &handler) {
try {
fmt::File file(filename, fmt::File::RDONLY);
mapped_file_.map(file, filename);
} catch (...) { // ignore if not provided
return;
}
catch (...) { return; } // do nothing if name file doesn't exist

fmt::StringRef data(mapped_file_.start(), mapped_file_.size());
ReadNames(filename, data, handler);
}
};

/// An NL handler that constructs an optimization problem using ProblemBuilder.

/// An NL handler that constructs an optimization problem
/// using ProblemBuilder.
template <typename ProblemBuilder>
class NLProblemBuilder {
public:
Expand Down Expand Up @@ -2613,6 +2618,25 @@ template <typename Handler>
inline void ReadNLFile(fmt::CStringRef filename, Handler &handler, int flags) {
internal::NLFileReader<>().Read(filename, handler, flags);
}


/// A variable or constraint name provider.
/// Caters for possible missing names.
class NameProvider {
private:
std::vector<const char *> names_;
std::string gen_name_;
internal::NameReader reader_;
fmt::MemoryWriter writer_;

public:
NameProvider(fmt::CStringRef filename, fmt::CStringRef gen_name,
std::size_t num_items);

// Returns the name of the item at specified index.
fmt::StringRef name(std::size_t index);
};

} // namespace mp

#endif // MP_NL_READER_H_
20 changes: 2 additions & 18 deletions include/mp/solver-io.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,22 +251,6 @@ void SolverNLHandlerImpl<Solver, PB, NLPB>::OnHeader(const NLHeader &h) {
}


/// A variable or constraint name provider.
class NameProvider {
private:
std::vector<const char *> names_;
std::string gen_name_;
NameReader reader_;
fmt::MemoryWriter writer_;

public:
NameProvider(fmt::CStringRef filename, fmt::CStringRef gen_name,
std::size_t num_items);

// Returns the name of the item at specified index.
fmt::StringRef name(std::size_t index);
};

/// Prints a solution to stdout.
void PrintSolution(const double *values, int num_values, const char *name_col,
const char *value_col, NameProvider &np);
Expand Down Expand Up @@ -327,12 +311,12 @@ void AppSolutionHandlerImpl<Solver, PB, Writer>::HandleSolution(
using internal::PrintSolution;
if ((wantsol & Solver::PRINT_SOLUTION) != 0) {
int num_vars = this->builder().num_vars();
internal::NameProvider np(this->stub() + ".col", "_svar", num_vars);
NameProvider np(this->stub() + ".col", "_svar", num_vars);
PrintSolution(values, num_vars, "variable", "value", np);
}
if ((wantsol & Solver::PRINT_DUAL_SOLUTION) != 0) {
int num_cons = this->builder().num_algebraic_cons();
internal::NameProvider np(this->stub() + ".row", "_scon", num_cons);
NameProvider np(this->stub() + ".row", "_scon", num_cons);
PrintSolution(dual_values, num_cons, "constraint", "dual value", np);
}
}
Expand Down
48 changes: 48 additions & 0 deletions src/nl-reader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -302,5 +302,53 @@ void mp::internal::NLFileReader<File>::Read(
array[size_] = 0;
}


namespace internal {

class NameHandler {
private:
std::vector<const char *> &names_;
fmt::StringRef name_;

public:
explicit NameHandler(std::vector<const char *> &names)
: names_(names), name_("") {}

void OnName(fmt::StringRef name) {
name_ = name;
names_.push_back(name.data());
}

fmt::StringRef name() const { return name_; }
};

} // namespace internal

mp::NameProvider::NameProvider(
fmt::CStringRef filename, fmt::CStringRef gen_name, std::size_t num_items)
: gen_name_(gen_name.c_str()) {
::internal::NameHandler handler(names_);
names_.reserve(num_items + 1);
try {
reader_.Read(filename, handler);
} catch (const fmt::SystemError &) {
return; // System error, ignore the file and use generated names.
}
fmt::StringRef last_name = handler.name();
names_.push_back(last_name.data() + last_name.size() + 1);
}

fmt::StringRef mp::NameProvider::name(std::size_t index) {
if (index + 1 < names_.size()) {
const char *name = names_[index];
return fmt::StringRef(name, names_[index + 1] - name - 1);
}
writer_.clear();
writer_ << gen_name_ << '[' << (index + 1) << ']';
return fmt::StringRef(writer_.c_str(), writer_.size());
}


// Instantiate
template class mp::internal::TextReader<>;
template class mp::internal::NLFileReader<>;
41 changes: 1 addition & 40 deletions src/solver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -233,22 +233,6 @@ void RSTFormatter::HandleDirective(const char *type) {
end_block_ = true;
}

class NameHandler {
private:
std::vector<const char *> &names_;
fmt::StringRef name_;

public:
explicit NameHandler(std::vector<const char *> &names)
: names_(names), name_("") {}

void OnName(fmt::StringRef name) {
name_ = name;
names_.push_back(name.data());
}

fmt::StringRef name() const { return name_; }
};
} // namespace

namespace mp {
Expand Down Expand Up @@ -538,29 +522,6 @@ void SignalHandler::HandleSigInt(int sig) {
std::signal(sig, HandleSigInt);
}

NameProvider::NameProvider(
fmt::CStringRef filename, fmt::CStringRef gen_name, std::size_t num_items)
: gen_name_(gen_name.c_str()) {
NameHandler handler(names_);
names_.reserve(num_items + 1);
try {
reader_.Read(filename, handler);
} catch (const fmt::SystemError &) {
return; // System error, ignore the file and use generated names.
}
fmt::StringRef last_name = handler.name();
names_.push_back(last_name.data() + last_name.size() + 1);
}

fmt::StringRef NameProvider::name(std::size_t index) {
if (index + 1 < names_.size()) {
const char *name = names_[index];
return fmt::StringRef(name, names_[index + 1] - name - 1);
}
writer_.clear();
writer_ << gen_name_ << "[" << (index + 1) << ']';
return fmt::StringRef(writer_.c_str(), writer_.size());
}

void PrintSolution(const double *values, int num_values, const char *name_col,
const char *value_col, NameProvider &np) {
Expand Down Expand Up @@ -1168,7 +1129,7 @@ mp::BasicBackend* AMPLSGetBackend(AMPLS_MP_Solver* slv) {
/// Load model incl. suffixes
int AMPLSLoadNLModel(AMPLS_MP_Solver* slv,
const char* nl_filename,
char** options) {
char** options) {
return AMPLS__internal__TryCatchWrapper( slv, [=]() {
std::string nl_filename_ = nl_filename;
auto filename_no_ext_ = nl_filename_;
Expand Down

0 comments on commit ad85002

Please sign in to comment.