Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

`Feature/1180 pathfinder single path csvs #1184

Merged
merged 20 commits into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
f6a4110
added arg; redo init writers logic
mitzimorris Aug 16, 2023
55edf12
unit tests
mitzimorris Aug 17, 2023
770b9ef
Merge commit 'b15c02fad0360552e005dea266302e0407daba59' into HEAD
yashikno Aug 17, 2023
3d22daf
[Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1
stan-buildbot Aug 17, 2023
df42b09
Merge branch 'feature/1180-pathfinder-single-path-csvs' of https://gi…
mitzimorris Aug 18, 2023
f72ef40
Merge branch 'feature/1180-pathfinder-single-path-csvs' of https://gi…
mitzimorris Aug 18, 2023
f4a93be
checkpointing
mitzimorris Aug 18, 2023
e0d6f37
[Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1
stan-buildbot Aug 18, 2023
4abe484
Merge branch 'feature/1180-pathfinder-single-path-csvs' of https://gi…
mitzimorris Aug 18, 2023
fc279a4
checkpointing
mitzimorris Aug 19, 2023
76610fe
checkpointing
mitzimorris Aug 20, 2023
0c79479
Merge commit 'b3fe97e202abeed6f4146829f71bdddd83c1afca' into HEAD
yashikno Aug 20, 2023
e0fde95
[Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1
stan-buildbot Aug 20, 2023
ddf8f10
Merge branch 'feature/1180-pathfinder-single-path-csvs' of https://gi…
mitzimorris Aug 20, 2023
5b54d70
Merge branch 'feature/1180-pathfinder-single-path-csvs' of https://gi…
mitzimorris Aug 20, 2023
002c8f5
updated logic and unit tests
mitzimorris Aug 20, 2023
3095496
tweak pathfinder args ordering
mitzimorris Aug 20, 2023
b4be8cc
changes per code review
mitzimorris Aug 21, 2023
71e54dc
changes per code review
mitzimorris Aug 21, 2023
4e647f0
[Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1
stan-buildbot Aug 21, 2023
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
3 changes: 3 additions & 0 deletions src/cmdstan/arguments/arg_pathfinder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ class arg_pathfinder : public arg_lbfgs {
"num_psis_draws", "Number of draws from PSIS sample", 1000));
_subarguments.push_back(
new arg_single_int_pos("num_paths", "Number of single pathfinders", 4));
_subarguments.push_back(new arg_single_bool(
"save_single_paths", "Output single-path pathfinder draws as CSV",
false));
_subarguments.push_back(new arg_single_int_pos(
"max_lbfgs_iters", "Maximum number of LBFGS iterations", 1000));
_subarguments.push_back(new arg_single_int_pos(
Expand Down
22 changes: 11 additions & 11 deletions src/cmdstan/command.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ int command(int argc, const char *argv[]) {
diagnostic_csv_writers;
std::vector<stan::callbacks::json_writer<std::ofstream>>
diagnostic_json_writers;

init_callbacks(parser, sample_writers, diagnostic_csv_writers,
diagnostic_json_writers);

Expand All @@ -207,9 +208,11 @@ int command(int argc, const char *argv[]) {
init = "";
} catch (const std::logic_error &e) {
}

std::vector<std::shared_ptr<stan::io::var_context>> init_contexts
= get_vec_var_context(init, num_chains);
std::vector<std::string> model_compile_info = model.model_compile_info();

for (int i = 0; i < num_chains; ++i) {
write_stan(sample_writers[i]);
write_model(sample_writers[i], model.model_name());
Expand Down Expand Up @@ -253,8 +256,8 @@ int command(int argc, const char *argv[]) {
= get_arg_val<int_argument>(*pathfinder_arg, "num_psis_draws");
int num_paths = get_arg_val<int_argument>(*pathfinder_arg, "num_paths");
bool save_iterations
= !get_arg_val<string_argument>(parser, "output", "diagnostic_file")
.empty();
= get_arg_val<bool_argument>(*pathfinder_arg, "save_single_paths");

if (num_paths == 1) {
return_code = stan::services::pathfinder::pathfinder_lbfgs_single<
false, stan::model::model_base>(
Expand All @@ -264,16 +267,13 @@ int command(int argc, const char *argv[]) {
save_iterations, refresh, interrupt, logger, init_writer,
sample_writers[0], diagnostic_json_writers[0]);
} else {
std::string output_file
= get_arg_val<string_argument>(parser, "output", "file");
auto base_sfx = get_basename_suffix(output_file);
if (base_sfx.second.empty())
base_sfx.second = ".csv";
auto ofs = std::make_unique<std::ofstream>(base_sfx.first + "_pathfinder"
+ base_sfx.second);
if (sig_figs > -1) {
auto ofs = std::make_unique<std::ofstream>(
get_basename_suffix(
get_arg_val<string_argument>(parser, "output", "file"))
.first
+ ".csv");
if (sig_figs > -1)
ofs->precision(sig_figs);
}
stan::callbacks::unique_stream_writer<std::ofstream> pathfinder_writer(
std::move(ofs), "# ");
write_stan(pathfinder_writer);
Expand Down
107 changes: 76 additions & 31 deletions src/cmdstan/command_helper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@ void check_file_config(argument_parser &parser) {
}

std::vector<std::string> make_filenames(const std::string &filename,
const std::string &tag,
const std::string &type,
unsigned int num_chains,
unsigned int id) {
Expand All @@ -754,7 +755,7 @@ std::vector<std::string> make_filenames(const std::string &filename,
}
};
for (int i = 0; i < num_chains; ++i) {
names[i] = base_sfx.first + name_iterator(i) + base_sfx.second;
names[i] = base_sfx.first + tag + name_iterator(i) + base_sfx.second;
}
return names;
}
Expand All @@ -771,48 +772,92 @@ void init_callbacks(
unsigned int num_chains = get_num_chains(parser);
unsigned int id = get_arg_val<int_argument>(parser, "id");
int sig_figs = get_arg_val<int_argument>(parser, "output", "sig_figs");

bool save_single_paths
= user_method->arg("pathfinder")
&& get_arg_val<bool_argument>(parser, "method", "pathfinder",
"save_single_paths");
std::string output_file
= get_arg_val<string_argument>(parser, "output", "file");
std::string diagnostic_file
= get_arg_val<string_argument>(parser, "output", "diagnostic_file");
std::vector<std::string> output_filenames;
std::vector<std::string> diagnostic_filenames;
sample_writers.reserve(num_chains);
std::vector<std::string> output_filenames
= make_filenames(get_arg_val<string_argument>(parser, "output", "file"),
".csv", num_chains, id);
for (int i = 0; i < num_chains; ++i) {
auto ofs = std::make_unique<std::ofstream>(output_filenames[i]);
if (sig_figs > -1)
ofs->precision(sig_figs);
sample_writers.emplace_back(std::move(ofs), "# ");
}

diag_json_writers.reserve(num_chains);
diag_csv_writers.reserve(num_chains);
// create no-op writers by default
diag_json_writers.reserve(num_chains);

// default - no diagnostics
for (int i = 0; i < num_chains; ++i) {
diag_csv_writers.emplace_back(nullptr, "# ");
diag_json_writers.emplace_back(
stan::callbacks::json_writer<std::ofstream>());
}
for (int i = 0; i < num_chains; ++i) {
diag_csv_writers.emplace_back(nullptr, "# ");
}
// create json, csv writers as needed.
std::string diagnostic_file
= get_arg_val<string_argument>(parser, "output", "diagnostic_file");
if (!diagnostic_file.empty()) {
std::vector<std::string> diag_filenames;
if (user_method->arg("pathfinder")) {
diag_json_writers.clear();
diag_filenames = make_filenames(diagnostic_file, ".json", num_chains, id);

if (user_method->arg("pathfinder")) {
std::string basename = get_basename_suffix(output_file).first;
std::string diag_basename = get_basename_suffix(diagnostic_file).first;
bool inst_writers = true;
bool inst_diags = true;
if (num_chains == 1) {
output_filenames.emplace_back(basename + ".csv");
if (!diag_basename.empty()) {
diagnostic_filenames.emplace_back(diag_basename + ".json");
} else if (save_single_paths) {
diagnostic_filenames.emplace_back(basename + ".json");
} else {
inst_diags = false;
}
} else if (save_single_paths) { // filenames for single-path outputs
output_filenames
= make_filenames(basename, "_path", ".csv", num_chains, id);
diagnostic_filenames
= make_filenames(basename, "_path", ".json", num_chains, id);
} else { // multi-path default: don't save single-path outputs
inst_writers = false;
inst_diags = false;
for (int i = 0; i < num_chains; ++i) {
auto ofs = std::make_unique<std::ofstream>(diag_filenames[i]);
if (sig_figs > -1)
sample_writers.emplace_back(nullptr, "# ");
}
}
// allocate writers
if (inst_writers) {
for (int i = 0; i < num_chains; ++i) {
auto ofs = std::make_unique<std::ofstream>(output_filenames[i]);
if (sig_figs > -1) {
ofs->precision(sig_figs);
stan::callbacks::json_writer<std::ofstream> jwriter(std::move(ofs));
}
sample_writers.emplace_back(std::move(ofs), "# ");
}
}
if (inst_diags) {
diag_json_writers.clear();
for (int i = 0; i < num_chains; ++i) {
auto ofs_diag
= std::make_unique<std::ofstream>(diagnostic_filenames[i]);
if (sig_figs > -1) {
ofs_diag->precision(sig_figs);
}
stan::callbacks::json_writer<std::ofstream> jwriter(
std::move(ofs_diag));
diag_json_writers.emplace_back(std::move(jwriter));
}
} else {
}
} else { // not pathfinder
output_filenames
= make_filenames(get_arg_val<string_argument>(parser, "output", "file"),
"", ".csv", num_chains, id);
for (int i = 0; i < num_chains; ++i) {
auto ofs = std::make_unique<std::ofstream>(output_filenames[i]);
if (sig_figs > -1)
ofs->precision(sig_figs);
sample_writers.emplace_back(std::move(ofs), "# ");
}
if (!diagnostic_file.empty()) {
diag_csv_writers.clear();
diag_filenames = make_filenames(diagnostic_file, ".csv", num_chains, id);
diagnostic_filenames
= make_filenames(diagnostic_file, "", ".csv", num_chains, id);
for (int i = 0; i < num_chains; ++i) {
auto ofs = std::make_unique<std::ofstream>(diag_filenames[i]);
auto ofs = std::make_unique<std::ofstream>(diagnostic_filenames[i]);
if (sig_figs > -1)
ofs->precision(sig_figs);
diag_csv_writers.emplace_back(std::move(ofs), "# ");
Expand Down
Loading