-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Project focuses on developing a spin-glass solver based on a family of simulated annealing algorithms for large system sizes and an exhaustive search for small Ising instances. This solver is implemented using an Intel's oneAPI development stack.
- Loading branch information
0 parents
commit 1c72590
Showing
86 changed files
with
124,618 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Use Clang-Format, docunentation: | ||
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html | ||
BasedOnStyle: LLVM |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.vscode | ||
build/ | ||
doc/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
cmake_minimum_required(VERSION 3.9) | ||
|
||
project("one-solver" CXX) | ||
|
||
set(CMAKE_CXX_STANDARD 17) | ||
set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||
|
||
|
||
set(CMAKE_C_COMPILER clang) | ||
set(CMAKE_CXX_COMPILER clang++) | ||
|
||
set(CMAKE_CXX_FLAGS "-fsycl") | ||
|
||
find_package(Boost 1.71) | ||
|
||
add_subdirectory(app) | ||
add_subdirectory(tests) |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2020 hyperQ – Ewa Hendzel | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
# oneSolver | ||
Created by hperQ - Ewa Hendzel | ||
|
||
## Build instructions | ||
|
||
``` | ||
mkdir build && cd build | ||
cmake .. | ||
cmake --build . | ||
``` | ||
|
||
## Running the applications | ||
Binaries are ``one-solver-anneal`` and ``one-solver-exhaustive`` created | ||
in the app folder. Binary for tests is located in ``tests``. | ||
|
||
The binary named `one-solver-anneal` allows to solve a QUBO problem using | ||
the simulated annealing algorithm whereas `one-solver-exhaustive` uses | ||
the brute force search method. | ||
|
||
In the ``tests`` folder the application called `main-tests` is build. | ||
|
||
In order to obtain help about the applications arguments | ||
use the `--help` switch. For example, the command | ||
`./one-solver-anneal --help` prints: | ||
|
||
``` | ||
Allowed options: | ||
--help produce help message | ||
--input arg input file | ||
--output arg output file | ||
--num-iter arg (=100) number of iterations of the algorithm | ||
--num-tries arg (=100) number of trajectories to try | ||
--schedule-type arg (=geometric) type of beta schedule tu use, either | ||
linear or geometric | ||
--beta-min arg (=0.10000000000000001) minimum value of beta in the annealing | ||
schedule (default 0.1) | ||
--beta-max arg (=1) maximum value of beta in the annealing | ||
schedule (default 1.0) | ||
--device-type arg (=host) device type to use (cpu, gpu or host) | ||
``` | ||
|
||
The command `./one-solver-exhaustive --help` prints: | ||
|
||
``` | ||
Allowed options: | ||
--help produce help message | ||
--input arg input file | ||
--output arg output file | ||
--device-type arg (=host) device type to use (cpu, gpu or host) | ||
``` | ||
|
||
The following applications call | ||
|
||
``` | ||
./one-solver-exhaustive --input ../../examples/test1.qubo --output result1.qubo | ||
``` | ||
|
||
executes the program for the model described in ``test1.qubo`` file and | ||
the obtained results are written to ``result1.qubo`` file. | ||
|
||
## Original goal of the project | ||
|
||
The project\'s goal is to develop a spin-glass (i.e., Ising model) | ||
solver based on a family of simulated annealing algorithms for large | ||
system sizes and an exhaustive search for small Ising instances. This | ||
solver will be implemented using an oneAPI development stack to utilize | ||
massive parallel capabilities of present-day computing architectures. | ||
|
||
It is well established that NP-hard problems can be solved by cleverly | ||
mapping them to the classical Ising Hamiltonians (i.e., spin-glasses). | ||
With the rapid development of both quantum and classical annealers, the | ||
scientific and computer engineering communities have intertwined once | ||
again in their efforts to reformulate many real-life combinatorial | ||
optimization problems using the ideal of interacting spin variables | ||
(i.e., spins). Various dedicated devices and computer chips are being | ||
developed currently to tackle the very problem of finding the low-energy | ||
configurations (i.e., spectrum) of the Ising models. For instance, | ||
Fujitsu and Hitachi have produced their digital and analog classical | ||
annealers. In stark contrast, D-Wave Inc. has manufactured its quantum | ||
annealers, which promises to solve the Ising instances using the law of | ||
quantum physics; the famous adiabatic theorem to be more specific. | ||
|
||
Although there are many sophisticated methods (e.g., tensor networks, | ||
simulated quantum annealing, path integrals, etc.) to approach the | ||
aforementioned problems, not that many of them can benefit from the | ||
High-Performance Computing (HPC) available today. On the other hand, | ||
fundamental techniques such as the Brute-Force (that simply executes an | ||
exhaustive search) or simulated annealing (that tries to mimic a famous | ||
physical process of annealing known in the material science) can take | ||
advantage of highly parallel architectures (graphics card, many-cores). | ||
This project is devoted precisely for that purpose; i.e., we aim to | ||
provide conceptually simple solvers that can be executed concurrently on | ||
present-day, massively parallel, classical architectures in an agnostic | ||
manner. | ||
|
||
Literature: | ||
1. [Brute-forcing spin-glass problems with CUDA](https://arxiv.org/abs/1904.03621) | ||
2. [Demonstration of a scaling advantage for a quantum annealer over simulated annealing](https://arxiv.org/abs/1705.07452) | ||
3. [Parallel in time dynamics with quantum annealers](https://www.nature.com/articles/s41598-020-70017-x) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
find_package(Boost 1.71 COMPONENTS program_options REQUIRED) | ||
|
||
set(APP_MODULE_DIRECTORY "${PROJECT_SOURCE_DIR}/app") | ||
set(APP_SOURCE_DIRECTORY "${APP_MODULE_DIRECTORY}") | ||
|
||
file(GLOB APP_SOURCES "${APP_SOURCE_DIRECTORY}/*.cpp") | ||
foreach(sourcefile ${APP_SOURCES}) | ||
get_filename_component(filename ${sourcefile} NAME_WE) | ||
add_executable(${filename} ${sourcefile}) | ||
target_include_directories(${filename} PRIVATE "${PROJECT_SOURCE_DIR}/include") | ||
target_link_libraries(${filename} ${LIBRARY_NAME}) | ||
target_link_libraries(${filename} Boost::program_options) | ||
endforeach(sourcefile ${APP_SOURCES}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
/*! file one-solver-anneal.cpp | ||
* | ||
* @copyright Licensed under MIT license by hyperQ – Ewa Hendzel | ||
* | ||
*/ | ||
|
||
#include <boost/program_options.hpp> | ||
#include <fstream> | ||
#include <iostream> | ||
|
||
#include "CL/sycl.hpp" | ||
#include "helpers/devices.hpp" | ||
#include "helpers/qubo_helpers.hpp" | ||
#include "model/qubo.hpp" | ||
#include "model/solution.hpp" | ||
#include "simulated_annealing/annealing.hpp" | ||
|
||
namespace po = boost::program_options; | ||
namespace sycl = cl::sycl; | ||
|
||
using queue_ptr = std::unique_ptr<sycl::queue>; | ||
|
||
void construct_linear_beta_schedule(std::vector<double> &schedule, | ||
double beta_min, double beta_max, | ||
uint num_iter) { | ||
for (auto i = 0; i < num_iter; i++) { | ||
schedule[i] = beta_min + beta_max * i / static_cast<double>(num_iter - 1); | ||
} | ||
} | ||
|
||
void construct_geometric_beta_schedule(std::vector<double> &schedule, | ||
double beta_min, double beta_max, | ||
uint num_iter) { | ||
schedule[0] = beta_min; | ||
auto alpha = pow(beta_max / beta_min, 1.0 / (num_iter - 1)); | ||
for (auto i = 1; i < num_iter; i++) { | ||
schedule[i] = (schedule[i - 1]) * alpha; | ||
} | ||
} | ||
|
||
int main(int argc, char *argv[]) { | ||
|
||
std::string input_file; | ||
std::string output_file; | ||
std::string schedule_type; | ||
std::string device_type; | ||
|
||
uint num_iter; | ||
uint num_tries; | ||
|
||
double beta_min, beta_max; | ||
|
||
try { | ||
|
||
po::options_description options("Allowed options"); | ||
options.add_options()("help", "produce help message")( | ||
"input", po::value<std::string>(&input_file), "input file")( | ||
"output", po::value<std::string>(&output_file), "output file")( | ||
"num-iter", po::value<uint>(&num_iter)->default_value(100), | ||
"number of iterations of the algorithm")( | ||
"num-tries", po::value<uint>(&num_tries)->default_value(100), | ||
"number of trajectories to try")( | ||
"schedule-type", | ||
po::value<std::string>(&schedule_type)->default_value("geometric"), | ||
"type of beta schedule tu use, either linear or geometric")( | ||
"beta-min", po::value<double>(&beta_min)->default_value(0.1), | ||
"minimum value of beta in the annealing schedule (default 0.1)")( | ||
"beta-max", po::value<double>(&beta_max)->default_value(1.0), | ||
"maximum value of beta in the annealing schedule (default 1.0)")( | ||
"device-type", | ||
po::value<std::string>(&device_type)->default_value("host"), | ||
"device type to use (cpu, gpu or host)"); | ||
|
||
po::variables_map vm; | ||
po::store(po::parse_command_line(argc, argv, options), vm); | ||
po::notify(vm); | ||
|
||
if (vm.count("help")) { | ||
std::cout << options << std::endl; | ||
return 0; | ||
} | ||
|
||
if (!vm.count("input")) { | ||
std::cerr << "No input file provided." << std::endl; | ||
return -1; | ||
} | ||
|
||
if (!vm.count("output")) { | ||
std::cerr << "No output file provided." << std::endl; | ||
return -1; | ||
} | ||
|
||
if (device_type != "cpu" && device_type != "gpu" && device_type != "host") { | ||
std::cerr << "Unknown device type: " << device_type << std::endl; | ||
return -1; | ||
} | ||
|
||
if (schedule_type != "linear" && schedule_type != "geometric") { | ||
std::cerr << "Unknown beta schedule: " << schedule_type << std::endl; | ||
return -1; | ||
} | ||
|
||
if (beta_max < 0 || beta_min < 0) { | ||
std::cerr | ||
<< "Invalid schedule, both ends of beta range need to be positive" | ||
<< std::endl; | ||
return -1; | ||
} | ||
|
||
if (beta_min >= beta_max) { | ||
std::cerr | ||
<< "Invalid schedule, initial beta is not lesser than final beta" | ||
<< std::endl; | ||
return -1; | ||
} | ||
|
||
std::cout << "Reading input from: " << input_file << std::endl; | ||
|
||
std::cout << "Output will be saved to: " << output_file << std::endl; | ||
|
||
std::cout << "Schedule type: " << schedule_type << std::endl; | ||
|
||
std::cout << "Beta range: [" << beta_min << ", " << beta_max << "]" | ||
<< std::endl; | ||
|
||
std::cout << "Number of iterations: " << num_iter << std::endl; | ||
std::cout << "Number of tries: " << num_tries << std::endl; | ||
|
||
std::ifstream qubo_file(input_file); | ||
|
||
if (!qubo_file) { | ||
std::cerr << "can not open input file: " << input_file << std::endl; | ||
return -1; | ||
} | ||
|
||
qubo_file.unsetf(std::ios::skipws); | ||
auto instance = qubo::QUBOModel<int, double>::load(qubo_file); | ||
|
||
queue_ptr q_ptr; | ||
|
||
try { | ||
q_ptr = queue_ptr( | ||
new sycl::queue(*devices::construct_device_selector(device_type))); | ||
} catch (std::runtime_error) { | ||
std::cerr << "No devices of given type could be initialized." | ||
<< std::endl; | ||
} | ||
|
||
std::cout << "Using device: " | ||
<< q_ptr->get_device().get_info<sycl::info::device::name>() | ||
<< std::endl; | ||
|
||
std::vector<double> beta_schedule(num_iter); | ||
|
||
if (schedule_type == "linear") { | ||
construct_linear_beta_schedule(beta_schedule, beta_min, beta_max, | ||
num_iter); | ||
} else { | ||
construct_geometric_beta_schedule(beta_schedule, beta_min, beta_max, | ||
num_iter); | ||
} | ||
|
||
auto solution = | ||
sa::anneal(instance, *q_ptr, beta_schedule, num_iter, num_tries); | ||
|
||
std::ofstream results_file(output_file); | ||
|
||
solution.save(results_file); | ||
|
||
results_file.close(); | ||
} catch (std::exception &e) { | ||
std::cerr << "error: " << e.what() << "\n"; | ||
return 1; | ||
} catch (...) { | ||
std::cerr << "Exception of unknown type!\n"; | ||
} | ||
|
||
return 0; | ||
} |
Oops, something went wrong.