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

Add tests for subset sum #4

Merged
merged 1 commit into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions include/knapsacksolver/subset_sum/solution.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Solution
/** Create a solution from a file. */
Solution(
const Instance& instance,
std::string certificate_path);
const std::string& certificate_path);

/** Add an item to the solution. */
void add(ItemId item_id);
Expand Down Expand Up @@ -61,7 +61,7 @@ class Solution
*/

/** Write the solution to a file. */
void write(std::string filepath) const;
void write(const std::string& certificate_path) const;

/** Export solution characteristics to a JSON structure. */
nlohmann::json to_json() const;
Expand Down
51 changes: 51 additions & 0 deletions include/knapsacksolver/subset_sum/tests.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#pragma once

#include "knapsacksolver/subset_sum/solution.hpp"

#include <gtest/gtest.h>

namespace knapsacksolver
{
namespace subset_sum
{

std::string get_path(const std::vector<std::string>& path);

struct TestInstancePath
{
std::string instance_path;
std::string instance_format;
std::string certificate_path;
std::string certificate_format;
};

std::vector<TestInstancePath> get_pthree_instance_paths(
ItemId number_of_items);

std::vector<TestInstancePath> get_psix_instance_paths(
ItemId number_of_items);

using Algorithm = std::function<const Output(const Instance&)>;

struct TestParams
{
Algorithm algorithm;
TestInstancePath files;
};

std::vector<TestParams> get_test_params(
const std::vector<Algorithm>& algorithms,
const std::vector<std::vector<TestInstancePath>>& instance_paths);

const Instance get_instance(
const TestInstancePath& files);

const Solution get_solution(
const Instance& instance,
const TestInstancePath& files);

class ExactAlgorithmTest: public testing::TestWithParam<TestParams> { };
class ExactNoSolutionAlgorithmTest: public testing::TestWithParam<TestParams> { };

}
}
2 changes: 1 addition & 1 deletion scripts/download_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ def download(id):
pathlib.Path("data.7z").unlink()

download("1jCf-Ye7pAQLVep6MT1HA_G05gdEgWeKk")
download("1n64Bti7qgImKDtY_bNAR3oNSC-S80-We")
download("1tNIfm81yBp7DU3qfQVLLnewYwKlyzsrt")
15 changes: 9 additions & 6 deletions src/knapsack/tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,12 @@ const Instance knapsacksolver::knapsack::get_instance(
const TestInstancePath& files)
{
InstanceBuilder instance_builder;
std::string data_path = std::getenv("KNAPSACK_DATA");
data_path += "/";
std::string instance_path = get_path({
std::getenv("KNAPSACK_DATA"),
files.instance_path});
std::cout << "Instance path: " << instance_path << std::endl;
instance_builder.read(
data_path + files.instance_path,
instance_path,
files.instance_format);
return instance_builder.build();
}
Expand All @@ -112,10 +114,11 @@ const Solution knapsacksolver::knapsack::get_solution(
const Instance& instance,
const TestInstancePath& files)
{
std::string data_path = std::getenv("KNAPSACK_DATA");
data_path += "/";
std::string certificate_path = get_path({
std::getenv("KNAPSACK_DATA"),
files.certificate_path});
return Solution(
instance,
data_path + files.certificate_path,
certificate_path,
files.certificate_format);
}
9 changes: 9 additions & 0 deletions src/subset_sum/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,12 @@ target_sources(KnapsackSolver_subset_sum_generator PRIVATE
target_link_libraries(KnapsackSolver_subset_sum_generator PUBLIC
KnapsackSolver_subset_sum)
add_library(KnapsackSolver::subset_sum::generator ALIAS KnapsackSolver_subset_sum_generator)

add_library(KnapsackSolver_subset_sum_tests)
target_sources(KnapsackSolver_subset_sum_tests PRIVATE
tests.cpp)
target_link_libraries(KnapsackSolver_subset_sum_tests PUBLIC
KnapsackSolver_subset_sum
Boost::filesystem
GTest::gtest_main)
add_library(KnapsackSolver::subset_sum::tests ALIAS KnapsackSolver_subset_sum_tests)
2 changes: 1 addition & 1 deletion src/subset_sum/algorithms/dynamic_programming_bellman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ const Output knapsacksolver::subset_sum::dynamic_programming_bellman_word_ram(
// std::cout << ((values[word] >> bit) & 1);
//std::cout << std::endl;

if (((values[capacity_number_of_words - 1] >> capacity_number_of_bits_to_shift) & 1) == 1)
if (((values[capacity_number_of_words] >> capacity_number_of_bits_to_shift) & 1) == 1)
break;
}

Expand Down
31 changes: 20 additions & 11 deletions src/subset_sum/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,24 @@ void read_args(
parameters.log_to_stderr = vm.count("log-to-stderr");
bool only_write_at_the_end = vm.count("only-write-at-the-end");
if (!only_write_at_the_end) {
std::string certificate_path = vm["certificate"].as<std::string>();
std::string json_output_path = vm["output"].as<std::string>();

std::string certificate_path;
if (vm.count("certificate"))
certificate_path = vm["certificate"].as<std::string>();

std::string json_output_path;
if (vm.count("output"))
json_output_path = vm["output"].as<std::string>();

parameters.new_solution_callback = [
json_output_path,
certificate_path](
const Output& output)
{
output.write_json_output(json_output_path);
output.solution.write(certificate_path);
if (!json_output_path.empty())
output.write_json_output(json_output_path);
if (!certificate_path.empty())
output.solution.write(certificate_path);
};
}
}
Expand Down Expand Up @@ -85,8 +94,8 @@ int main(int argc, char *argv[])
("algorithm,a", po::value<std::string>(), "set algorithm")
("input,i", po::value<std::string>()->required(), "set input file (required)")
("format,f", po::value<std::string>()->default_value(""), "set input file format (default: standard)")
("output,o", po::value<std::string>()->default_value(""), "set JSON output file")
("certificate,c", po::value<std::string>()->default_value(""), "set certificate file")
("output,o", po::value<std::string>(), "set JSON output file")
("certificate,c", po::value<std::string>(), "set certificate file")
("seed,s", po::value<Seed>()->default_value(0), "set seed")
("time-limit,t", po::value<double>(), "set time limit in seconds")
("verbosity-level,v", po::value<int>(), "set verbosity level")
Expand All @@ -103,7 +112,7 @@ int main(int argc, char *argv[])
try {
po::notify(vm);
} catch (const po::required_option& e) {
std::cout << desc << std::endl;;
std::cout << desc << std::endl;
return 1;
}

Expand All @@ -118,10 +127,10 @@ int main(int argc, char *argv[])
Output output = run(instance, vm);

// Write outputs.
std::string certificate_path = vm["certificate"].as<std::string>();
std::string json_output_path = vm["output"].as<std::string>();
output.write_json_output(json_output_path);
output.solution.write(certificate_path);
if (vm.count("certificate"))
output.solution.write(vm["certificate"].as<std::string>());
if (vm.count("output"))
output.write_json_output(vm["output"].as<std::string>());

return 0;
}
5 changes: 3 additions & 2 deletions src/subset_sum/solution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Solution::Solution(const Instance& instance):

Solution::Solution(
const Instance& instance,
std::string certificate_path):
const std::string& certificate_path):
Solution(instance)
{
if (certificate_path.empty())
Expand All @@ -38,7 +38,8 @@ void Solution::add(ItemId item_id)
weight_ += instance().weight(item_id);
}

void Solution::write(std::string certificate_path) const
void Solution::write(
const std::string& certificate_path) const
{
if (certificate_path.empty())
return;
Expand Down
88 changes: 88 additions & 0 deletions src/subset_sum/tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#include "knapsacksolver/subset_sum/tests.hpp"

#include "knapsacksolver/subset_sum/instance_builder.hpp"

#include <boost/filesystem.hpp>

using namespace knapsacksolver::subset_sum;

namespace fs = boost::filesystem;

std::string knapsacksolver::subset_sum::get_path(
const std::vector<std::string>& path)
{
if (path.empty())
return "";
fs::path p(path[0]);
for (size_t i = 1; i < path.size(); ++i)
p /= path[i];
return p.string();
}

std::vector<TestInstancePath> knapsacksolver::subset_sum::get_pthree_instance_paths(
ItemId number_of_items)
{
std::vector<TestInstancePath> instance_paths;
for (int i = 0; i < 100; ++i) {
instance_paths.push_back({
get_path({"pthree", "pthree_" + std::to_string(number_of_items) + "_" + std::to_string(i)}), "standard",
get_path({"pthree", "pthree_" + std::to_string(number_of_items) + "_" + std::to_string(i) + "_solution.txt"}), "standard"});
}
return instance_paths;
}

std::vector<TestInstancePath> knapsacksolver::subset_sum::get_psix_instance_paths(
ItemId number_of_items)
{
std::vector<TestInstancePath> instance_paths;
for (int i = 0; i < 100; ++i) {
instance_paths.push_back({
get_path({"psix", "psix_" + std::to_string(number_of_items) + "_" + std::to_string(i)}), "standard",
get_path({"psix", "psix_" + std::to_string(number_of_items) + "_" + std::to_string(i) + "_solution.txt"}), "standard"});
}
return instance_paths;
}

std::vector<TestParams> knapsacksolver::subset_sum::get_test_params(
const std::vector<Algorithm>& algorithms,
const std::vector<std::vector<TestInstancePath>>& instance_paths)
{
std::vector<TestParams> res;
for (const Algorithm& algorithm: algorithms) {
for (const auto& v: instance_paths) {
for (const TestInstancePath& files: v) {
TestParams test_params;
test_params.algorithm = algorithm;
test_params.files = files;
res.push_back(test_params);
}
}
}
return res;
}

const Instance knapsacksolver::subset_sum::get_instance(
const TestInstancePath& files)
{
InstanceBuilder instance_builder;
std::string instance_path = get_path({
std::getenv("SUBSET_SUM_DATA"),
files.instance_path});
std::cout << "Instance path: " << instance_path << std::endl;
instance_builder.read(
instance_path,
files.instance_format);
return instance_builder.build();
}

const Solution knapsacksolver::subset_sum::get_solution(
const Instance& instance,
const TestInstancePath& files)
{
std::string certificate_path = get_path({
std::getenv("SUBSET_SUM_DATA"),
files.certificate_path});
return Solution(
instance,
certificate_path);
}
6 changes: 3 additions & 3 deletions test/knapsack/algorithms/dynamic_programming_bellman_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ TEST_P(ExactNoSolutionAlgorithmTest, ExactNoSolutionAlgorithm)
}

INSTANTIATE_TEST_SUITE_P(
DynamicProgrammingBellmanArray,
KnapsackDynamicProgrammingBellmanArray,
ExactNoSolutionAlgorithmTest,
testing::ValuesIn(get_test_params(
{
Expand All @@ -42,7 +42,7 @@ INSTANTIATE_TEST_SUITE_P(
})));

INSTANTIATE_TEST_SUITE_P(
DynamicProgrammingBellmanNoSolution,
KnapsackDynamicProgrammingBellmanNoSolution,
ExactNoSolutionAlgorithmTest,
testing::ValuesIn(get_test_params(
{
Expand Down Expand Up @@ -74,7 +74,7 @@ INSTANTIATE_TEST_SUITE_P(
})));

INSTANTIATE_TEST_SUITE_P(
DynamicProgrammingBellman,
KnapsackDynamicProgrammingBellman,
ExactAlgorithmTest,
testing::ValuesIn(get_test_params(
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ TEST_P(ExactAlgorithmTest, ExactAlgorithm)
}

INSTANTIATE_TEST_SUITE_P(
DynamicProgrammingPrimalDualPartialSolutionSize,
KnapsackDynamicProgrammingPrimalDualPartialSolutionSize,
ExactAlgorithmTest,
testing::ValuesIn(get_test_params(
{
Expand All @@ -43,7 +43,7 @@ INSTANTIATE_TEST_SUITE_P(
{get_test_instance_paths()})));

INSTANTIATE_TEST_SUITE_P(
DynamicProgrammingPrimalDual,
KnapsackDynamicProgrammingPrimalDual,
ExactAlgorithmTest,
testing::ValuesIn(get_test_params(
{
Expand Down
8 changes: 8 additions & 0 deletions test/subset_sum/algorithms/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
add_executable(KnapsackSolver_subset_sum_dynamic_programming_bellman_test)
target_sources(KnapsackSolver_subset_sum_dynamic_programming_bellman_test PRIVATE
dynamic_programming_bellman_test.cpp)
target_link_libraries(KnapsackSolver_subset_sum_dynamic_programming_bellman_test
KnapsackSolver_subset_sum_dynamic_programming_bellman
KnapsackSolver_subset_sum_tests
GTest::gtest_main)
add_test(KnapsackSolver_subset_sum_dynamic_programming_bellman_test KnapsackSolver_subset_sum_dynamic_programming_bellman_test)
Loading
Loading