├── .gitignore
├── include
├── QMC-methods
│ ├── RiegerKawashimaDiscrete.h
│ ├── SimulatedAnnealing.h
│ ├── SantoroTosattiMartonak.h
│ ├── SwendsenWang.h
│ └── RiegerKawashimaContinuous.h
└── QMC-methods.h
├── tests
├── algorithms
│ ├── RiegerKawashimaDiscreteTest.cpp
│ ├── RiegerKawashimaContinuousTest.cpp
│ ├── SimulatedAnnealingTest.cpp
│ ├── SantoroTosattiMartonakTest.cpp
│ └── SwendsenWangTest.cpp
├── test.cpp
├── models
│ ├── NodeTest.cpp
│ ├── Arc2Test.cpp
│ ├── SubSegmentTest.cpp
│ ├── SegmentTest.cpp
│ ├── Ising2dTest.cpp
│ └── Ising2dTransverseTest.cpp
├── CMakeLists.txt
└── libs
│ └── utilityTest.cpp
├── src
├── algorithms
│ ├── RiegerKawashimaDiscrete.cpp
│ ├── SimulatedAnnealing.cpp
│ ├── SantoroTosattiMartonak.cpp
│ ├── SwendsenWang.cpp
│ └── RiegerKawashimaContinuous.cpp
├── models
│ ├── Cluster.h
│ ├── Arc2.cpp
│ ├── Point.h
│ ├── Arc2.h
│ ├── Node.cpp
│ ├── Node.h
│ ├── Ising2dTransverse.h
│ ├── Ising2d.h
│ ├── Segment.h
│ ├── SubSegment.h
│ ├── Ising2dTransverse.cpp
│ └── Ising2d.cpp
├── CMakeLists.txt
└── libs
│ └── Uniform.h
├── apps
├── CMakeLists.txt
└── example.cpp
├── .editorconfig
├── CMakeLists.txt
├── .vscode
├── c_cpp_properties.json
├── launch.json
├── settings.json
└── tasks.json
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/include/QMC-methods/RiegerKawashimaDiscrete.h:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/algorithms/RiegerKawashimaDiscreteTest.cpp:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/test.cpp:
--------------------------------------------------------------------------------
1 | #define CATCH_CONFIG_MAIN
2 | #include
3 |
--------------------------------------------------------------------------------
/src/algorithms/RiegerKawashimaDiscrete.cpp:
--------------------------------------------------------------------------------
1 | #include "../../include/QMC-methods/RiegerKawashimaDiscrete.h"
2 |
--------------------------------------------------------------------------------
/apps/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_executable(
2 | "${PROJECT_NAME}App"
3 | example.cpp
4 | )
5 | target_link_libraries(
6 | "${PROJECT_NAME}App"
7 | ${PROJECT_NAME}
8 | )
--------------------------------------------------------------------------------
/src/models/Cluster.h:
--------------------------------------------------------------------------------
1 | // #ifndef Cluster_h
2 | // #define Cluster_h
3 |
4 | // #include "Node.h"
5 | // #include
6 |
7 | // struct Cluster {
8 | // std::vector cluster;
9 | // };
10 | // #endif
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | # Tab indentation
7 | [*]
8 | trim_trailing_whitespace = true
9 | indent_style = space
10 | indent_size = 2
11 |
--------------------------------------------------------------------------------
/include/QMC-methods.h:
--------------------------------------------------------------------------------
1 | #include "QMC-methods/SimulatedAnnealing.h"
2 | #include "QMC-methods/SantoroTosattiMartonak.h"
3 | #include "QMC-methods/SwendsenWang.h"
4 | #include "QMC-methods/RiegerKawashimaContinuous.h"
5 | #include "QMC-methods/RiegerKawashimaDiscrete.h"
6 |
--------------------------------------------------------------------------------
/src/models/Arc2.cpp:
--------------------------------------------------------------------------------
1 | #include "Arc2.h"
2 | using namespace QMCm;
3 |
4 | Arc2::Arc2() {
5 | node1 = nullptr;
6 | node2 = nullptr;
7 | value = 0;
8 | }
9 |
10 | Arc2::Arc2(Node* _node1, Node* _node2, double _value) {
11 | node1 = _node1;
12 | node2 = _node2;
13 | value = _value;
14 | }
--------------------------------------------------------------------------------
/src/models/Point.h:
--------------------------------------------------------------------------------
1 | #ifndef Point_h
2 | #define Point_h
3 |
4 | namespace QMCm {
5 | class Point {
6 | public:
7 | Point(int _x = 0, int _y = 0, int _z = 0) {
8 | x = _x;
9 | y = _y;
10 | z = _z;
11 | }
12 | int x;
13 | int y;
14 | int z;
15 | };
16 | }; // namespace QMCm
17 | #endif
--------------------------------------------------------------------------------
/src/models/Arc2.h:
--------------------------------------------------------------------------------
1 | #ifndef Arc2_h
2 | #define Arc2_h
3 |
4 | #include "Node.h"
5 |
6 | namespace QMCm {
7 | class Arc2 {
8 | public:
9 | Arc2();
10 | Arc2(Node* _node1, Node* _node2, double _value);
11 | Node* node1;
12 | Node* node2;
13 | double value;
14 | };
15 | }; // namespace QMCm
16 |
17 | #endif
--------------------------------------------------------------------------------
/tests/algorithms/RiegerKawashimaContinuousTest.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace QMCm;
4 | static Uniform uniform;
5 |
6 | TEST_CASE("RiegerKawashimaContinuous RiegerKawashimaContinuous()", "[rkc]") {
7 | RiegerKawashimaContinuous rkc;
8 | REQUIRE(rkc.scale != 0);
9 | }
10 |
--------------------------------------------------------------------------------
/src/models/Node.cpp:
--------------------------------------------------------------------------------
1 | #include "Node.h"
2 | using namespace QMCm;
3 |
4 | Node::Node() {
5 | id = "0-0";
6 | value = 1;
7 | spin = 1;
8 | }
9 |
10 | Node::Node(const std::string _id, int _spin, double _value) {
11 | id = _id;
12 | spin = _spin;
13 | value = _value;
14 | }
15 |
16 | void Node::flip() { spin *= -1; }
--------------------------------------------------------------------------------
/src/models/Node.h:
--------------------------------------------------------------------------------
1 | #ifndef Node_h
2 | #define Node_h
3 |
4 | #include
5 |
6 | namespace QMCm {
7 | class Node {
8 | public:
9 | Node();
10 | Node(const std::string _id, int _spin, double _value);
11 | void flip();
12 |
13 | std::string id;
14 | int spin;
15 | double value;
16 | };
17 | }; // namespace QMCm
18 | #endif
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | file(
2 | GLOB
3 | HEADER_LISTCONFIGURE_DEPENDS
4 | "${PROJECT_SOURCE_DIR}/include/${PROJECT_NAME}/*.h"
5 | )
6 | file(GLOB autopilot_sources "algorithms/**.cpp" "lib/**.cpp" "models/**.cpp")
7 | SET(autopilot ${autopilot_sources})
8 | add_library(
9 | ${PROJECT_NAME}
10 | ${autopilot}
11 | )
12 | target_include_directories(
13 | ${PROJECT_NAME}
14 | PUBLIC
15 | ../include
16 | )
17 |
18 |
--------------------------------------------------------------------------------
/src/libs/Uniform.h:
--------------------------------------------------------------------------------
1 | #ifndef Uniform_h
2 | #define Uniform_h
3 |
4 | #include
5 | #include
6 |
7 | namespace QMCm {
8 | class Uniform {
9 | private:
10 | std::mt19937 mt;
11 | std::uniform_real_distribution dist;
12 |
13 | public:
14 | Uniform(double lower = 0.0, double upper = 1.0) : mt(std::time(nullptr)), dist(lower, upper) {}
15 | double operator()() { return dist(mt); }
16 | };
17 | }; // namespace QMCm
18 |
19 | #endif
--------------------------------------------------------------------------------
/tests/models/NodeTest.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace QMCm;
4 |
5 | TEST_CASE("Node Node()", "[node]") {
6 | Node node;
7 | REQUIRE(node.id == "0-0");
8 | REQUIRE(node.spin == 1);
9 | REQUIRE(node.value == 1);
10 | }
11 |
12 | TEST_CASE("Node Node(id, value)", "[node]") {
13 | Node node("1-2", 3, 4);
14 | REQUIRE(node.id == "1-2");
15 | REQUIRE(node.spin == 3);
16 | REQUIRE(node.value == 4);
17 | }
--------------------------------------------------------------------------------
/tests/models/Arc2Test.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace QMCm;
4 |
5 | TEST_CASE("Arc2 Arc2()", "[arc]") {
6 | Arc2 arc;
7 | REQUIRE(arc.value == 0);
8 | REQUIRE(arc.node1 == 0);
9 | REQUIRE(arc.node2 == 0);
10 | }
11 |
12 | TEST_CASE("Arc2 Arc2(_node1, _node2, _value)", "[arc]") {
13 | Node node;
14 | Arc2 arc(&node, &node, 3);
15 | REQUIRE(arc.value == 3);
16 | REQUIRE(arc.node1 == &node);
17 | REQUIRE(arc.node2 == &node);
18 | }
--------------------------------------------------------------------------------
/tests/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | include(FetchContent)
2 | FetchContent_Declare(
3 | catch2
4 | GIT_REPOSITORY https://github.com/catchorg/Catch2.git
5 | GIT_TAG v2.9.1
6 | )
7 | FetchContent_MakeAvailable(catch2)
8 | file(GLOB autopilot_sources "algorithms/**.cpp" "libs/**.cpp" "models/**.cpp")
9 | SET(autopilot ${autopilot_sources})
10 | add_executable(
11 | "${PROJECT_NAME}Test"
12 | test.cpp
13 | ${autopilot}
14 | )
15 | target_link_libraries(
16 | "${PROJECT_NAME}Test"
17 | PRIVATE
18 | ${PROJECT_NAME}
19 | Catch2::Catch2
20 | )
--------------------------------------------------------------------------------
/include/QMC-methods/SimulatedAnnealing.h:
--------------------------------------------------------------------------------
1 | #ifndef SimulatedAnnealing_h
2 | #define SimulatedAnnealing_h
3 |
4 | #include "../../src/models/Ising2d.h"
5 | #include "../../src/libs/Uniform.h"
6 |
7 | namespace QMCm {
8 | class SimulatedAnnealing {
9 | public:
10 | SimulatedAnnealing();
11 | Ising2d generateNeighboringConfig(Ising2d _ising);
12 | void run();
13 |
14 | Ising2d startingConfig;
15 | Ising2d endingConfig;
16 | double startingTemperature;
17 | double deltaTemperature;
18 | double endingTemperature;
19 | double scale;
20 | };
21 | }; // namespace QMCm
22 | #endif
--------------------------------------------------------------------------------
/tests/libs/utilityTest.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace QMCm;
4 |
5 | TEST_CASE("Uniform uniform", "[uniform]") {
6 | Uniform uniform;
7 | double array[50];
8 | bool oneValue = true;
9 | bool sameSequence = true;
10 | for (int i = 0; i < 50; i++) {
11 | array[i] = uniform();
12 | if (i > 0 && array[i] != array[i - 1])
13 | oneValue = false;
14 | }
15 | REQUIRE(!oneValue);
16 | for (int i = 0; i < 50; i++) {
17 | if (array[i] != uniform())
18 | sameSequence = false;
19 | }
20 | REQUIRE(!sameSequence);
21 | }
22 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.14)
2 |
3 | project(
4 | "QMC-methods"
5 | VERSION 1.0.0
6 | DESCRIPTION "In this repository there are various implementations of the monte carlo algorithm for the calculation of the minimum in an ising model."
7 | LANGUAGES CXX
8 | )
9 |
10 | if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
11 | set(CMAKE_CXX_STANDARD 11)
12 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
13 | set(CMAKE_CXX_EXTENSIONS OFF)
14 | set_property(GLOBAL PROPERTY USE_FOLDERS ON)
15 | add_subdirectory(apps)
16 | add_subdirectory(tests)
17 | endif()
18 |
19 | add_subdirectory(src)
20 |
--------------------------------------------------------------------------------
/src/models/Ising2dTransverse.h:
--------------------------------------------------------------------------------
1 | #ifndef Ising2dTransverse_h
2 | #define Ising2dTransverse_h
3 |
4 | #include
5 | #include "Ising2d.h"
6 |
7 | namespace QMCm {
8 | class Ising2dTransverse {
9 | public:
10 | Ising2dTransverse();
11 | void generate();
12 | double getEnergy() const;
13 | double getIsingDiscreteEnergy() const;
14 | double getIsingContinueEnergy() const;
15 | double getIsingAVGEnergy() const;
16 | double getDelta(const Ising2dTransverse& ising) const;
17 | std::vector slices;
18 | Ising2d mainReplica;
19 | int numberOfreplicas;
20 | double tranverseField;
21 | double periodicBoundary;
22 | };
23 | }; // namespace QMCm
24 | #endif
--------------------------------------------------------------------------------
/include/QMC-methods/SantoroTosattiMartonak.h:
--------------------------------------------------------------------------------
1 | #ifndef SantoroTosattiMartonak_h
2 | #define SantoroTosattiMartonak_h
3 |
4 | #include "../../src/models/Ising2dTransverse.h"
5 | #include "../../src/libs/Uniform.h"
6 |
7 | namespace QMCm {
8 | class SantoroTosattiMartonak {
9 | public:
10 | SantoroTosattiMartonak();
11 | Ising2dTransverse generateNeighboringConfig(Ising2dTransverse _ising);
12 | void run();
13 |
14 | Ising2dTransverse startingConfig;
15 | Ising2dTransverse endingConfig;
16 | double temperature;
17 | double numberOfreplicas;
18 | double startingField;
19 | double endingField;
20 | double deltaField;
21 | double scale;
22 | };
23 | }; // namespace QMCm
24 | #endif
--------------------------------------------------------------------------------
/src/models/Ising2d.h:
--------------------------------------------------------------------------------
1 | #ifndef Ising2d_h
2 | #define Ising2d_h
3 |
4 | #include
5 | #include "Arc2.h"
6 |
7 | #define UP 0
8 | #define LEFT 1
9 | #define DIM 2
10 |
11 | namespace QMCm {
12 | class Ising2d {
13 | public:
14 | Ising2d();
15 | void generate();
16 | double getEnergy() const;
17 | double getDelta(const Ising2d& ising) const;
18 | std::vector> nodes;
19 | std::vector>> arcs;
20 | int size;
21 | bool favorAlignment;
22 | bool favorSpinUp;
23 | bool periodicBoundary;
24 | double nodeMaxValue;
25 | double nodeMinValue;
26 | double arcMaxValue;
27 | double arcMinValue;
28 | };
29 | }; // namespace QMCm
30 | #endif
--------------------------------------------------------------------------------
/include/QMC-methods/SwendsenWang.h:
--------------------------------------------------------------------------------
1 | #ifndef SwendsenWang_h
2 | #define SwendsenWang_h
3 |
4 | #include "../../src/models/Ising2d.h"
5 | #include "../../src/libs/Uniform.h"
6 |
7 | namespace QMCm {
8 | class SwendsenWang {
9 | public:
10 | SwendsenWang();
11 | std::vector>> generateJoins(Ising2d ising);
12 | std::vector> generateClusters(Ising2d &ising, std::vector>> joins);
13 | void randomFlip(std::vector> clusters);
14 | void run();
15 |
16 | Ising2d startingConfig;
17 | Ising2d endingConfig;
18 | double temperature;
19 | double scale;
20 | int numberOfIterations;
21 | };
22 | }; // namespace QMCm
23 | #endif
--------------------------------------------------------------------------------
/.vscode/c_cpp_properties.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "Win32",
5 | "includePath": [
6 | "c:/mingw/lib/gcc/mingw32/6.3.0/include/c++",
7 | "c:/mingw/lib/gcc/mingw32/6.3.0/include/c++/mingw32",
8 | "c:/mingw/lib/gcc/mingw32/6.3.0/include/c++/backward",
9 | "c:/mingw/lib/gcc/mingw32/6.3.0/include",
10 | "c:/mingw/include",
11 | "c:/mingw/lib/gcc/mingw32/6.3.0/include-fixed",
12 | "c:/mingw/mingw32/include",
13 | "${workspaceFolder}/**"
14 | ],
15 | "defines": [
16 | "_DEBUG",
17 | "UNICODE"
18 | ],
19 | "compilerPath": "C:/MinGW/bin/gcc.exe",
20 | "intelliSenseMode": "clang-x64"
21 | }
22 | ],
23 | "version": 4
24 | }
--------------------------------------------------------------------------------
/src/models/Segment.h:
--------------------------------------------------------------------------------
1 | #ifndef Segment_h
2 | #define Segment_h
3 |
4 | #include "SubSegment.h"
5 |
6 | namespace QMCm {
7 | class Segment {
8 | public:
9 | Segment() {
10 | spin = 0;
11 | }
12 | Segment(int _begin, int _back, int _spin) {
13 | add(_begin, _back);
14 | spin = _spin;
15 | }
16 | void add(int _begin, int _back) {
17 | subsegment.emplace_back(_begin, _back);
18 | }
19 | int size() {
20 | int size = 0;
21 | for (int i = 0; i < subsegment.size(); i++) {
22 | size += subsegment[i].size();
23 | }
24 | return size;
25 | }
26 | int intersectionSize(Segment _segment) {
27 | int size = 0;
28 | for (int i = 0; i < subsegment.size(); i++) {
29 | for (int j = 0; j < _segment.subsegment.size(); j++) {
30 | size += subsegment[i].intersectionSize(_segment.subsegment[j]);
31 | }
32 | }
33 | return size;
34 | }
35 | std::vector subsegment;
36 | int spin;
37 | };
38 | }; // namespace QMCm
39 | #endif
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Usare IntelliSense per informazioni sui possibili attributi.
3 | // Al passaggio del mouse vengono visualizzate le descrizioni degli attributi esistenti.
4 | // Per ulteriori informazioni, visitare: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "(gdb) Launch",
9 | "type": "cppdbg",
10 | "request": "launch",
11 | "program": "${workspaceFolder}/test.exe",
12 | "args": [],
13 | "stopAtEntry": false,
14 | "cwd": "${workspaceFolder}",
15 | "environment": [],
16 | "externalConsole": true,
17 | "MIMode": "gdb",
18 | "miDebuggerPath": "C:/MinGW/bin/gdb.exe",
19 | "preLaunchTask": "test-debug",
20 | "setupCommands": [
21 | {
22 | "description": "Enable pretty-printing for gdb",
23 | "text": "-enable-pretty-printing",
24 | "ignoreFailures": true
25 | }
26 | ]
27 | }
28 | ]
29 | }
--------------------------------------------------------------------------------
/include/QMC-methods/RiegerKawashimaContinuous.h:
--------------------------------------------------------------------------------
1 | #ifndef RiegerKawashimaContinuous_h
2 | #define RiegerKawashimaContinuous_h
3 |
4 | #include "../../src/models/Ising2dTransverse.h"
5 | #include "../../src/models/Segment.h"
6 | #include "../../src/libs/Uniform.h"
7 |
8 | namespace QMCm {
9 | class RiegerKawashimaContinuous {
10 | public:
11 | RiegerKawashimaContinuous();
12 | std::vector>> generateCuts(Ising2dTransverse ising);
13 | std::vector generateSegments(Ising2dTransverse ising, std::vector>> cuts);
14 | std::vector> generateClusters(Ising2d &ising, std::vector>> cuts);
15 | void randomFlip(std::vector> clusters);
16 | void run();
17 |
18 | Ising2dTransverse startingConfig;
19 | Ising2dTransverse endingConfig;
20 | double temperature;
21 | double numberOfreplicas;
22 | double startingField;
23 | double endingField;
24 | double deltaField;
25 | double scale;
26 | };
27 | }; // namespace QMCm
28 | #endif
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Federico Berra
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/models/SubSegment.h:
--------------------------------------------------------------------------------
1 | #ifndef SubSegment_h
2 | #define SubSegment_h
3 |
4 | #include
5 |
6 | namespace QMCm {
7 | class SubSegment {
8 | public:
9 | SubSegment() {
10 | begin = 0;
11 | end = 0;
12 | }
13 | SubSegment(int _begin) {
14 | begin = _begin;
15 | end = 0;
16 | }
17 | SubSegment(int _begin, int _end) {
18 | begin = _begin;
19 | end = _end;
20 | }
21 | int size() {
22 | return abs(begin - end);
23 | }
24 | int intersectionSize(SubSegment _subsegment) {
25 | int max1, max2, max3, min1, min2, min3;
26 | if (begin > end) {
27 | max1 = begin;
28 | min1 = end;
29 | } else {
30 | max1 = end;
31 | min1 = begin;
32 | }
33 | if (_subsegment.begin > _subsegment.end) {
34 | max2 = _subsegment.begin;
35 | min2 = _subsegment.end;
36 | } else {
37 | max2 = _subsegment.end;
38 | min2 = _subsegment.begin;
39 | }
40 | max3 = (max1 > max2) ? max2 : max1;
41 | min3 = (min1 > min2) ? min1 : min2;
42 | return (max3 - min3 > 0) ? max3 - min3 : 0;
43 | }
44 | int begin;
45 | int end;
46 | };
47 | }; // namespace QMCm
48 | #endif
--------------------------------------------------------------------------------
/apps/example.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | using namespace QMCm;
3 | static Uniform uniform;
4 |
5 | int main(int argc, char const *argv[]) {
6 | SimulatedAnnealing sa;
7 | sa.startingConfig.size = 3;
8 | sa.startingConfig.generate();
9 | /*
10 | Nodes value matrix
11 | 1 1 1
12 | 1 1 1
13 | 1 1 1
14 | */
15 | for (int i = 0; i < sa.startingConfig.nodes.size(); i++) {
16 | for (int j = 0; j < sa.startingConfig.nodes.size(); j++) {
17 | sa.startingConfig.nodes[i][j].value = 1;
18 | sa.startingConfig.nodes[i][j].spin = (uniform() < 0.5) ? 1 : -1;
19 | }
20 | }
21 | /*
22 | Arcs value matrix
23 | 1 1 1
24 | 1 1 1
25 | 1 1 1
26 | */
27 | for (int i = 0; i < sa.startingConfig.arcs.size(); i++)
28 | for (int j = 0; j < sa.startingConfig.arcs[i].size(); j++)
29 | for (int k = 0; k < sa.startingConfig.arcs[i][k].size(); k++)
30 | sa.startingConfig.arcs[i][j][k].value = 1;
31 |
32 | printf("The starting energy is [%f]\n", sa.startingConfig.getEnergy());
33 | for (int i = 0; i < 10; i++) {
34 | sa.run();
35 | printf("The ending energy is [%f]\n", sa.endingConfig.getEnergy());
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/tests/models/SubSegmentTest.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace QMCm;
4 |
5 | TEST_CASE("SubSegment SubSegment()", "[sseg]") {
6 | SubSegment sseg;
7 | REQUIRE(sseg.begin == 0);
8 | REQUIRE(sseg.end == 0);
9 | }
10 |
11 | TEST_CASE("SubSegment size()", "[sseg]") {
12 | SubSegment sseg;
13 | REQUIRE(sseg.size() == 0);
14 | sseg.end = 100;
15 | REQUIRE(sseg.size() == 100);
16 | sseg.begin = 200;
17 | REQUIRE(sseg.size() == 100);
18 | }
19 |
20 | TEST_CASE("SubSegment intersectionSize(subsegment)", "[sseg1, sseg2]") {
21 | SubSegment sseg1, sseg2;
22 | REQUIRE(sseg1.intersectionSize(sseg2) == 0);
23 | sseg1.begin = 5;
24 | sseg1.end = 10;
25 | sseg2.begin = 1;
26 | sseg2.end = 5;
27 | REQUIRE(sseg1.intersectionSize(sseg2) == 0);
28 | sseg2.end = 6;
29 | REQUIRE(sseg1.intersectionSize(sseg2) == 1);
30 | sseg2.begin = 5;
31 | sseg2.end = 7;
32 | REQUIRE(sseg1.intersectionSize(sseg2) == 2);
33 | sseg2.begin = 8;
34 | sseg2.end = 12;
35 | REQUIRE(sseg1.intersectionSize(sseg2) == 2);
36 | sseg2.begin = 1;
37 | sseg2.end = 12;
38 | REQUIRE(sseg1.intersectionSize(sseg2) == 5);
39 | }
--------------------------------------------------------------------------------
/tests/models/SegmentTest.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace QMCm;
4 |
5 | TEST_CASE("Segment Segment()", "[seg]") {
6 | Segment seg;
7 | REQUIRE(seg.spin == 0);
8 | REQUIRE(seg.size() == 0);
9 | }
10 |
11 | TEST_CASE("Segment add(point, point)", "[seg]") {
12 | Segment seg;
13 | seg.add(1, 4);
14 | REQUIRE(seg.subsegment[0].begin == 1);
15 | REQUIRE(seg.subsegment[0].end == 4);
16 | }
17 |
18 | TEST_CASE("Segment Segment(point, point, spin)", "[seg]") {
19 | Segment seg(1, 4, 1);
20 | REQUIRE(seg.spin == 1);
21 | REQUIRE(seg.subsegment[0].begin == 1);
22 | REQUIRE(seg.subsegment[0].end == 4);
23 | }
24 |
25 | TEST_CASE("Segment size()", "[seg]") {
26 | Segment seg;
27 | REQUIRE(seg.size() == 0);
28 | seg.add(1, 4);
29 | REQUIRE(seg.size() == 3);
30 | seg.add(10, 4);
31 | REQUIRE(seg.size() == 9);
32 | }
33 |
34 | TEST_CASE("Segment intersect(segment)", "[seg1, seg2]") {
35 | Segment seg1, seg2;
36 | seg1.add(1, 2);
37 | seg1.add(4, 5);
38 | REQUIRE(seg1.intersectionSize(seg2) == 0);
39 | seg2.add(1, 2);
40 | REQUIRE(seg1.intersectionSize(seg2) == 1);
41 | seg2.add(4, 7);
42 | REQUIRE(seg1.intersectionSize(seg2) == 2);
43 | }
--------------------------------------------------------------------------------
/src/algorithms/SimulatedAnnealing.cpp:
--------------------------------------------------------------------------------
1 | #include "../../include/QMC-methods/SimulatedAnnealing.h"
2 | #include
3 | #include
4 | using namespace QMCm;
5 | static Uniform uniform;
6 |
7 | SimulatedAnnealing::SimulatedAnnealing() {
8 | startingTemperature = 100.0;
9 | deltaTemperature = 1.0;
10 | endingTemperature = 0.0;
11 | scale = 10;
12 | }
13 |
14 | Ising2d SimulatedAnnealing::generateNeighboringConfig(Ising2d _ising) {
15 | _ising.nodes[(int)(uniform() * (float)(_ising.nodes.size() - 1))]
16 | [(int)(uniform() * (float)(_ising.nodes.size() - 1))]
17 | .flip();
18 | return _ising;
19 | }
20 |
21 | void SimulatedAnnealing::run() {
22 | Ising2d trialConfig;
23 | Ising2d bestConfig = startingConfig;
24 | double delta;
25 | for (double currentTemperature = startingTemperature;
26 | currentTemperature > endingTemperature;
27 | currentTemperature -= deltaTemperature) {
28 | trialConfig = generateNeighboringConfig(bestConfig);
29 | delta = trialConfig.getDelta(bestConfig);
30 | if (uniform() < exp(-scale * delta / currentTemperature))
31 | bestConfig = trialConfig;
32 | }
33 | endingConfig = bestConfig;
34 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "C_Cpp.clang_format_fallbackStyle": "{ BasedOnStyle: Google, IndentWidth: 2, AlignConsecutiveAssignments: true, ColumnLimit: 0 }",
3 | "files.associations": {
4 | "array": "cpp",
5 | "bitset": "cpp",
6 | "initializer_list": "cpp",
7 | "utility": "cpp",
8 | "cstdlib": "cpp",
9 | "*.tcc": "cpp",
10 | "chrono": "cpp",
11 | "functional": "cpp",
12 | "istream": "cpp",
13 | "tuple": "cpp",
14 | "cctype": "cpp",
15 | "clocale": "cpp",
16 | "cmath": "cpp",
17 | "cstddef": "cpp",
18 | "cstdint": "cpp",
19 | "cstdio": "cpp",
20 | "cstring": "cpp",
21 | "ctime": "cpp",
22 | "cwchar": "cpp",
23 | "cwctype": "cpp",
24 | "deque": "cpp",
25 | "list": "cpp",
26 | "unordered_map": "cpp",
27 | "vector": "cpp",
28 | "exception": "cpp",
29 | "optional": "cpp",
30 | "fstream": "cpp",
31 | "iomanip": "cpp",
32 | "iosfwd": "cpp",
33 | "iostream": "cpp",
34 | "limits": "cpp",
35 | "memory": "cpp",
36 | "new": "cpp",
37 | "ostream": "cpp",
38 | "numeric": "cpp",
39 | "ratio": "cpp",
40 | "sstream": "cpp",
41 | "stdexcept": "cpp",
42 | "streambuf": "cpp",
43 | "system_error": "cpp",
44 | "type_traits": "cpp",
45 | "typeinfo": "cpp",
46 | "string_view": "cpp"
47 | },
48 | "C_Cpp.loggingLevel": "Debug",
49 | "C_Cpp.errorSquiggles": "Disabled"
50 | }
--------------------------------------------------------------------------------
/tests/algorithms/SimulatedAnnealingTest.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace QMCm;
4 | static Uniform uniform;
5 |
6 | TEST_CASE("SimulatedAnnealing SimulatedAnnealing()", "[sa]") {
7 | SimulatedAnnealing sa;
8 | REQUIRE(sa.scale != 0);
9 | }
10 |
11 | TEST_CASE("SimulatedAnnealing generateNeighboringConfig()", "[sa]") {
12 | SimulatedAnnealing sa;
13 | Ising2d ising1, ising2;
14 | ising1.generate();
15 | ising2 = sa.generateNeighboringConfig(ising1);
16 | REQUIRE(ising1.getEnergy() != ising2.getEnergy());
17 | }
18 |
19 | TEST_CASE("SimulatedAnnealing [prob] run()", "[sa]") {
20 | SimulatedAnnealing sa;
21 | double min = 999;
22 | sa.startingConfig.size = 3;
23 | sa.startingConfig.generate();
24 | for (int i = 0; i < sa.startingConfig.nodes.size(); i++) {
25 | for (int j = 0; j < sa.startingConfig.nodes[i].size(); j++) {
26 | sa.startingConfig.nodes[i][j].value = 1;
27 | sa.startingConfig.nodes[i][j].spin = (uniform() < 0.5) ? 1 : -1;
28 | }
29 | }
30 | for (int i = 0; i < sa.startingConfig.arcs.size(); i++)
31 | for (int j = 0; j < sa.startingConfig.arcs[i].size(); j++)
32 | for (int k = 0; k < sa.startingConfig.arcs[i][k].size(); k++)
33 | sa.startingConfig.arcs[i][j][k].value = 1;
34 |
35 | for (int i = 0; i < 10; i++) {
36 | sa.run();
37 | if (min > sa.endingConfig.getEnergy()) min = sa.endingConfig.getEnergy();
38 | }
39 | REQUIRE(sa.startingConfig.getEnergy() > min);
40 | }
--------------------------------------------------------------------------------
/src/algorithms/SantoroTosattiMartonak.cpp:
--------------------------------------------------------------------------------
1 | #include "../../include/QMC-methods/SantoroTosattiMartonak.h"
2 | #include
3 | #include
4 | using namespace QMCm;
5 | static Uniform uniform;
6 |
7 | SantoroTosattiMartonak::SantoroTosattiMartonak() {
8 | temperature = 1;
9 | numberOfreplicas = 3;
10 | startingField = 100;
11 | endingField = 0;
12 | deltaField = 1;
13 | scale = 10;
14 | }
15 |
16 | Ising2dTransverse SantoroTosattiMartonak::generateNeighboringConfig(Ising2dTransverse _ising) {
17 | _ising.slices[(int)(uniform() * (float)(_ising.numberOfreplicas - 1))]
18 | .nodes[(int)(uniform() * (float)(_ising.mainReplica.nodes.size() - 1))]
19 | [(int)(uniform() * (float)(_ising.mainReplica.nodes.size() - 1))]
20 | .flip();
21 | int row = (int)(uniform() * (float)(_ising.mainReplica.nodes.size() - 1));
22 | int col = (int)(uniform() * (float)(_ising.mainReplica.nodes.size() - 1));
23 | for (int i = 0; i < _ising.numberOfreplicas; i++)
24 | _ising.slices[i].nodes[row][col].flip();
25 | return _ising;
26 | }
27 |
28 | void SantoroTosattiMartonak::run() {
29 | Ising2dTransverse trialConfig;
30 | Ising2dTransverse bestConfig = startingConfig;
31 | double delta;
32 | for (double currentField = startingField; currentField > endingField; currentField -= deltaField) {
33 | bestConfig.tranverseField = -log(tanh(currentField / (numberOfreplicas * temperature)));
34 | trialConfig = generateNeighboringConfig(bestConfig);
35 | delta = trialConfig.getDelta(bestConfig);
36 | if (uniform() < exp(-scale * delta / currentField))
37 | bestConfig = trialConfig;
38 | }
39 | endingConfig = bestConfig;
40 | }
--------------------------------------------------------------------------------
/tests/algorithms/SantoroTosattiMartonakTest.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace QMCm;
4 | static Uniform uniform;
5 |
6 | TEST_CASE("SantoroTosattiMartonak SantoroTosattiMartonak()", "[stm]") {
7 | SantoroTosattiMartonak stm;
8 | REQUIRE(stm.scale != 0);
9 | }
10 |
11 | TEST_CASE("SantoroTosattiMartonak generateNeighboringConfig()", "[stm]") {
12 | SantoroTosattiMartonak stm;
13 | Ising2dTransverse ising1, ising2;
14 | ising1.numberOfreplicas = 4;
15 | ising1.mainReplica.generate();
16 | ising1.generate();
17 | ising2 = stm.generateNeighboringConfig(ising1);
18 | REQUIRE(ising1.getEnergy() != ising2.getEnergy());
19 | }
20 |
21 | TEST_CASE("SantoroTosattiMartonak [prob] run()", "[stm]") {
22 | SantoroTosattiMartonak stm;
23 | double min = 999;
24 | double temp;
25 | stm.startingConfig.numberOfreplicas = 3;
26 | stm.startingConfig.mainReplica.size = 3;
27 | stm.startingConfig.mainReplica.generate();
28 |
29 | for (int i = 0; i < stm.startingConfig.mainReplica.nodes.size(); i++) {
30 | for (int j = 0; j < stm.startingConfig.mainReplica.nodes[i].size(); j++) {
31 | stm.startingConfig.mainReplica.nodes[i][j].value = 1;
32 | stm.startingConfig.mainReplica.nodes[i][j].spin =
33 | (uniform() < 0.5) ? 1 : -1;
34 | }
35 | }
36 | for (int i = 0; i < stm.startingConfig.mainReplica.arcs.size(); i++)
37 | for (int j = 0; j < stm.startingConfig.mainReplica.arcs[i].size(); j++)
38 | for (int k = 0; k < stm.startingConfig.mainReplica.arcs[i][j].size(); k++)
39 | stm.startingConfig.mainReplica.arcs[i][j][k].value = 1;
40 |
41 | stm.startingConfig.generate();
42 |
43 | for (int i = 0; i < 10; i++) {
44 | stm.run();
45 | temp = stm.endingConfig.getIsingDiscreteEnergy();
46 | if (min > temp) min = temp;
47 | }
48 | REQUIRE(stm.startingConfig.mainReplica.getEnergy() > min);
49 | }
--------------------------------------------------------------------------------
/src/models/Ising2dTransverse.cpp:
--------------------------------------------------------------------------------
1 | #include "Ising2dTransverse.h"
2 | #include "../libs/Uniform.h"
3 | #include
4 | #include
5 | #include
6 | using namespace QMCm;
7 |
8 | static Uniform uniform;
9 |
10 | Ising2dTransverse::Ising2dTransverse() {
11 | numberOfreplicas = 3;
12 | tranverseField = 1;
13 | periodicBoundary = false;
14 | }
15 |
16 | void Ising2dTransverse::generate() {
17 | slices = std::vector(numberOfreplicas, mainReplica);
18 | }
19 |
20 | double Ising2dTransverse::getEnergy() const {
21 | double energy = 0;
22 | for (int i = 0; i < slices.size(); i++) {
23 | energy += slices[i].getEnergy();
24 | for (int j = 0; j < slices[i].nodes.size(); j++)
25 | for (int k = 0; k < slices[i].nodes[j].size(); k++)
26 | if (periodicBoundary || i != slices.size() - 1)
27 | energy += -tranverseField * slices[i].nodes[j][k].spin * slices[(i + 1) % slices.size()].nodes[j][k].spin;
28 | }
29 | return energy;
30 | }
31 |
32 | double Ising2dTransverse::getIsingDiscreteEnergy() const {
33 | double energy = std::numeric_limits::max();
34 | if (slices.size() <= 0) return 0;
35 | for (auto& slice : slices)
36 | energy = std::min(energy, slice.getEnergy());
37 | return energy;
38 | }
39 |
40 | double Ising2dTransverse::getIsingContinueEnergy() const {
41 | double energy = 0;
42 | if (slices.size() <= 0) return 0;
43 | return slices[(int)((slices.size() - 1) * uniform())].getEnergy();
44 | }
45 |
46 | double Ising2dTransverse::getIsingAVGEnergy() const {
47 | double energy = 0;
48 | if (slices.size() <= 0) return 0;
49 | for (auto& slice : slices)
50 | energy += slice.getEnergy();
51 | return energy / slices.size();
52 | }
53 |
54 | double Ising2dTransverse::getDelta(const Ising2dTransverse& ising) const {
55 | double myEnergy = getEnergy();
56 | double otherEnergy = ising.getEnergy();
57 | return (myEnergy > otherEnergy ? 1 : -1) * abs(myEnergy - otherEnergy);
58 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | // See https://go.microsoft.com/fwlink/?LinkId=733558
3 | // for the documentation about the tasks.json format
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "label": "build",
8 | "type": "shell",
9 | "command": "./example.out",
10 | "dependsOn": [
11 | "build-build"
12 | ],
13 | "group": {
14 | "kind": "build",
15 | "isDefault": true
16 | }
17 | },
18 | {
19 | "label": "build-build",
20 | "type": "shell",
21 | "command": "g++ -std=c++14 -O0 src/example.cpp src/models/*.cpp src/algorithms/*.cpp -o example.out",
22 | "dependsOn": [
23 | "build-clear"
24 | ]
25 | },
26 | {
27 | "label": "build-clear",
28 | "type": "shell",
29 | "command": "rm example.out -force"
30 | },
31 | {
32 | "label": "test",
33 | "type": "shell",
34 | "command": "./test.out",
35 | "dependsOn": [
36 | "test-build"
37 | ],
38 | "group": {
39 | "kind": "test",
40 | "isDefault": true
41 | }
42 | },
43 | {
44 | "label": "test-speed",
45 | "type": "shell",
46 | "command": "make",
47 | "dependsOn": [
48 | "test-clear"
49 | ]
50 | },
51 | {
52 | "label": "test-debug",
53 | "type": "shell",
54 | "command": "g++ -std=c++14 -g src/models/*.cpp src/algorithms/*.cpp test/models/*.cpp test/algorithms/*.cpp test/lib/*.cpp testexample.o -o test.out",
55 | "dependsOn": [
56 | // "test-clear"
57 | ]
58 | },
59 | {
60 | "label": "test-build",
61 | "type": "shell",
62 | "command": "g++ -std=c++14 -O0 src/models/*.cpp src/algorithms/*.cpp test/models/*.cpp test/algorithms/*.cpp test/lib/*.cpp testexample.o -o test.out",
63 | "dependsOn": [
64 | // "test-clear"
65 | ]
66 | },
67 | {
68 | "label": "test-clear",
69 | "type": "shell",
70 | "command": "rm test.out -force"
71 | },
72 | {
73 | "label": "test-build-catch",
74 | "type": "shell",
75 | "command": "g++ -std=c++14 -O2 -c test/test.cpp -o testexample.o"
76 | },
77 | {
78 | "label": "test-build-nocatch",
79 | "type": "shell",
80 | "command": "g++ -std=c++14 -O0 src/models/*.cpp src/algorithms/*.cpp test/models/*.cpp test/algorithms/*.cpp test/lib/*.cpp testexample.o -o test.out"
81 | }
82 | ]
83 | }
--------------------------------------------------------------------------------
/tests/models/Ising2dTest.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace QMCm;
4 |
5 | TEST_CASE("Ising2d Ising2d()", "[ising]") {
6 | Ising2d ising;
7 | REQUIRE(ising.nodes.size() == 0);
8 | }
9 |
10 | TEST_CASE("Ising2d generate()", "[ising]") {
11 | Ising2d ising;
12 | ising.generate();
13 | for (int i = 0; i < ising.nodes.size(); i++)
14 | for (int j = 0; j < ising.nodes[i].size(); j++)
15 | REQUIRE(ising.nodes[i][j].id == std::to_string(i) + "-" + std::to_string(j));
16 |
17 | for (int i = 0; i < ising.arcs.size(); i++)
18 | for (int j = 0; j < ising.arcs[i].size(); j++)
19 | for (int k = 0; k < ising.arcs[i][j].size(); k++)
20 | if (i > 0 && j > 0) {
21 | REQUIRE(ising.arcs[i][j][k].node1 != nullptr);
22 | REQUIRE(ising.arcs[i][j][k].node2 != nullptr);
23 | REQUIRE(ising.arcs[i][j][k].node1->id == std::to_string(i) + "-" + std::to_string(j));
24 | }
25 |
26 | ising.size = 1;
27 | ising.generate();
28 | REQUIRE(ising.arcs.size() == 1);
29 | REQUIRE(ising.nodes.size() == 1);
30 | ising.size = 2;
31 | ising.generate();
32 | REQUIRE(ising.arcs.size() == 2);
33 | REQUIRE(ising.nodes.size() == 2);
34 | }
35 |
36 | TEST_CASE("Ising2d getEnergy()", "[ising]") {
37 | Ising2d ising;
38 | REQUIRE(ising.getEnergy() == 0);
39 | ising.generate();
40 | double energy = ising.getEnergy();
41 | ising.periodicBoundary = true;
42 | ising.generate();
43 | REQUIRE(ising.getEnergy() != energy);
44 | }
45 |
46 | TEST_CASE("Ising2d ising1 = ising2", "[ising]") {
47 | Ising2d ising1, ising2;
48 | ising1.size = 2;
49 | ising1.periodicBoundary = true;
50 | ising1.generate();
51 | ising2 = ising1;
52 | REQUIRE(ising2.size == ising1.size);
53 | REQUIRE(ising2.periodicBoundary == ising1.periodicBoundary);
54 | REQUIRE(ising2.getEnergy() == ising1.getEnergy());
55 | ising1.nodes[0][0].flip();
56 | REQUIRE(ising2.getEnergy() != ising1.getEnergy());
57 | }
58 |
59 | TEST_CASE("Ising2d getDelta()", "[ising1,ising2]") {
60 | Ising2d ising1, ising2;
61 | ising1.size = 1;
62 | ising2.size = 1;
63 | ising1.generate();
64 | ising2.generate();
65 | ising1.nodes[0][0].spin = 1;
66 | ising1.nodes[0][0].value = 1;
67 | ising2.nodes[0][0].spin = 1;
68 | ising2.nodes[0][0].value = 1;
69 | REQUIRE(ising1.getEnergy() == -1);
70 | REQUIRE(ising2.getEnergy() == -1);
71 | REQUIRE(ising1.getDelta(ising2) == 0);
72 | REQUIRE(ising2.getDelta(ising1) == 0);
73 | ising1.nodes[0][0].value = 2;
74 | REQUIRE(ising1.getDelta(ising2) == -1);
75 | REQUIRE(ising2.getDelta(ising1) == 1);
76 | }
--------------------------------------------------------------------------------
/src/models/Ising2d.cpp:
--------------------------------------------------------------------------------
1 | #include "Ising2d.h"
2 | #include "../libs/Uniform.h"
3 | #include
4 | #include
5 | #include
6 | using namespace QMCm;
7 |
8 | static Uniform uniform;
9 |
10 | Ising2d::Ising2d() {
11 | size = 3;
12 | favorAlignment = true;
13 | favorSpinUp = true;
14 | periodicBoundary = false;
15 | nodeMaxValue = 1;
16 | nodeMinValue = -1;
17 | arcMaxValue = 1;
18 | arcMinValue = -1;
19 | }
20 |
21 | void Ising2d::generate() {
22 | nodes = std::vector>(size, std::vector(size));
23 | arcs = std::vector>>(size, std::vector>(size, std::vector(DIM)));
24 | for (int i = 0; i < nodes.size(); i++) {
25 | for (int j = 0; j < nodes[i].size(); j++) {
26 | nodes[i][j].id = std::to_string(i) + "-" + std::to_string(j);
27 | nodes[i][j].value = uniform() * (nodeMaxValue - nodeMinValue) + nodeMinValue;
28 | if (i > 0) {
29 | arcs[i][j][UP].node1 = &(nodes[i][j]);
30 | arcs[i][j][UP].node2 = &(nodes[i - 1][j]);
31 | arcs[i][j][UP].value = uniform() * (arcMaxValue - arcMinValue) + arcMinValue;
32 | }
33 | if (periodicBoundary && (i == nodes.size() - 1)) {
34 | arcs[0][j][UP].node1 = &(nodes[0][j]);
35 | arcs[0][j][UP].node2 = &(nodes[i][j]);
36 | arcs[0][j][UP].value = uniform() * (arcMaxValue - arcMinValue) + arcMinValue;
37 | }
38 | if (j > 0) {
39 | arcs[i][j][LEFT].node1 = &(nodes[i][j]);
40 | arcs[i][j][LEFT].node2 = &(nodes[i][j - 1]);
41 | arcs[i][j][LEFT].value = uniform() * (arcMaxValue - arcMinValue) + arcMinValue;
42 | }
43 | if (periodicBoundary && (j == nodes.size() - 1)) {
44 | arcs[i][0][LEFT].node1 = &(nodes[i][0]);
45 | arcs[i][0][LEFT].node2 = &(nodes[i][j]);
46 | arcs[i][0][LEFT].value = uniform() * (arcMaxValue - arcMinValue) + arcMinValue;
47 | }
48 | }
49 | }
50 | }
51 |
52 | double Ising2d::getEnergy() const {
53 | double energy = 0;
54 | int alpha = favorSpinUp ? -1 : 1;
55 | int beta = favorAlignment ? -1 : 1;
56 | for (int i = 0; i < nodes.size(); i++)
57 | for (int j = 0; j < nodes[i].size(); j++)
58 | energy += alpha * nodes[i][j].value * nodes[i][j].spin;
59 |
60 | for (int i = 0; i < arcs.size(); i++)
61 | for (int j = 0; j < arcs[i].size(); j++)
62 | for (int k = 0; k < DIM; k++)
63 | if (arcs[i][j][k].node1 != nullptr && arcs[i][j][k].node2 != nullptr)
64 | energy += beta * arcs[i][j][k].value * arcs[i][j][k].node1->spin * arcs[i][j][k].node2->spin;
65 |
66 | return energy;
67 | }
68 |
69 | double Ising2d::getDelta(const Ising2d& ising) const {
70 | double myEnergy = getEnergy();
71 | double otherEnergy = ising.getEnergy();
72 | return (myEnergy > otherEnergy ? 1 : -1) * abs(myEnergy - otherEnergy);
73 | }
--------------------------------------------------------------------------------
/src/algorithms/SwendsenWang.cpp:
--------------------------------------------------------------------------------
1 | #include "../../include/QMC-methods/SwendsenWang.h"
2 | #include
3 | #include
4 | using namespace QMCm;
5 | static Uniform uniform;
6 |
7 | SwendsenWang::SwendsenWang() {
8 | temperature = 1;
9 | scale = 1;
10 | numberOfIterations = 1;
11 | }
12 |
13 | std::vector>> SwendsenWang::generateJoins(Ising2d ising) {
14 | std::vector>> joins =
15 | std::vector>>(ising.size, std::vector>(ising.size, std::vector(DIM)));
16 | int beta = ising.favorAlignment ? -1 : 1;
17 | for (int i = 0; i < ising.arcs.size(); i++)
18 | for (int j = 0; j < ising.arcs[i].size(); j++)
19 | for (int k = 0; k < ising.arcs[i][j].size(); k++)
20 | if (ising.arcs[i][j][k].node1 != nullptr &&
21 | ising.arcs[i][j][k].node2 != nullptr &&
22 | ising.arcs[i][j][k].node1->spin == ising.arcs[i][j][k].node2->spin &&
23 | uniform() < (1 - exp(-scale * beta * ising.arcs[i][j][k].value / temperature)))
24 | joins[i][j][k] = true;
25 | else
26 | joins[i][j][k] = false;
27 | return joins;
28 | }
29 |
30 | std::vector> SwendsenWang::generateClusters(Ising2d &ising, std::vector>> joins) {
31 | std::vector> clusters = std::vector>();
32 | int clustersMap[ising.size][ising.size] = {};
33 | int lastCluster = 0;
34 | for (int i = 0; i < ising.nodes.size(); i++)
35 | for (int j = 0; j < ising.nodes[i].size(); j++) {
36 | if (j == ising.nodes[i].size() - 1 && joins[i][0][LEFT]) {
37 | clustersMap[i][j] = clustersMap[i][0];
38 | clusters[clustersMap[i][0]].push_back(&(ising.nodes[i][j]));
39 | } else if (j > 0 && joins[i][j][LEFT]) {
40 | clustersMap[i][j] = clustersMap[i][j - 1];
41 | clusters[clustersMap[i][j - 1]].push_back(&(ising.nodes[i][j]));
42 | } else if (i == ising.nodes.size() - 1 && joins[0][j][UP]) {
43 | clustersMap[i][j] = clustersMap[0][j];
44 | clusters[clustersMap[0][j]].push_back(&(ising.nodes[i][j]));
45 | } else if (i > 0 && joins[i][j][UP]) {
46 | clustersMap[i][j] = clustersMap[i - 1][j];
47 | clusters[clustersMap[i - 1][j]].push_back(&(ising.nodes[i][j]));
48 | } else {
49 | std::vector newCluster = std::vector();
50 | newCluster.push_back(&(ising.nodes[i][j]));
51 | clusters.push_back(newCluster);
52 | clustersMap[i][j] = lastCluster++;
53 | }
54 | }
55 | return clusters;
56 | }
57 |
58 | void SwendsenWang::randomFlip(std::vector> clusters) {
59 | for (int i = 0; i < clusters.size(); i++)
60 | if (uniform() < 0.5)
61 | for (int j = 0; j < clusters[i].size(); j++)
62 | clusters[i][j]->flip();
63 | }
64 |
65 | void SwendsenWang::run() {
66 | Ising2d currentConfig = startingConfig;
67 | std::vector>> joins;
68 | std::vector> clusters;
69 | for (int i = 0; i < numberOfIterations; i++) {
70 | joins = generateJoins(currentConfig);
71 | clusters = generateClusters(currentConfig, joins);
72 | randomFlip(clusters);
73 | }
74 | endingConfig = currentConfig;
75 | }
--------------------------------------------------------------------------------
/tests/models/Ising2dTransverseTest.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace QMCm;
4 | static Uniform uniform;
5 |
6 | TEST_CASE("Ising2dTransverse Ising2dTransverse()", "[ising]") {
7 | Ising2dTransverse ising;
8 | REQUIRE(ising.slices.size() == 0);
9 | }
10 |
11 | TEST_CASE("Ising2dTransverse getEnergy()", "[ising]") {
12 | Ising2dTransverse ising;
13 | REQUIRE(ising.getEnergy() == 0);
14 | ising.periodicBoundary = false;
15 | ising.mainReplica.periodicBoundary = false;
16 | ising.mainReplica.generate();
17 | ising.generate();
18 | double energy = ising.getEnergy();
19 | REQUIRE(energy != 0);
20 | ising.slices[(int)(uniform() * (float)(ising.numberOfreplicas - 1))]
21 | .nodes[(int)(uniform() * (float)(ising.mainReplica.nodes.size() - 1))]
22 | [(int)(uniform() * (float)(ising.mainReplica.nodes.size() - 1))]
23 | .flip();
24 | REQUIRE(energy != ising.getEnergy());
25 | ising.periodicBoundary = true;
26 | ising.mainReplica.periodicBoundary = true;
27 | ising.mainReplica.generate();
28 | ising.generate();
29 | REQUIRE(energy != ising.getEnergy());
30 | }
31 |
32 | TEST_CASE("Ising2dTransverse ising1 = ising2", "[ising]") {
33 | Ising2dTransverse ising1, ising2;
34 | ising1.numberOfreplicas = 2;
35 | ising1.periodicBoundary = true;
36 | ising1.mainReplica.periodicBoundary = true;
37 | ising1.mainReplica.generate();
38 | ising1.generate();
39 | ising2 = ising1;
40 | REQUIRE(ising2.numberOfreplicas == ising1.numberOfreplicas);
41 | REQUIRE(ising2.periodicBoundary == ising1.periodicBoundary);
42 | REQUIRE(ising2.mainReplica.periodicBoundary == ising1.mainReplica.periodicBoundary);
43 | REQUIRE(ising2.getEnergy() == ising1.getEnergy());
44 | ising1.slices[0].nodes[0][0].flip();
45 | REQUIRE(ising2.getEnergy() != ising1.getEnergy());
46 | ising1.generate();
47 | ising1.mainReplica.nodes[0][0].spin = 1;
48 | ising1.mainReplica.nodes[0][0].value = 1;
49 | ising2 = ising1;
50 | REQUIRE(ising2.getEnergy() == ising1.getEnergy());
51 | }
52 |
53 | TEST_CASE("Ising2dTransverse getDelta()", "[ising1,ising2]") {
54 | Ising2dTransverse ising1, ising2;
55 | ising1.mainReplica.size = 1;
56 | ising1.mainReplica.nodeMaxValue = 1;
57 | ising1.mainReplica.nodeMinValue = 1;
58 | ising1.mainReplica.arcMaxValue = 1;
59 | ising1.mainReplica.arcMinValue = 1;
60 | ising1.numberOfreplicas = 2;
61 | ising1.tranverseField = 1;
62 | ising1.mainReplica.generate();
63 | ising1.generate();
64 | ising1.mainReplica.nodes[0][0].spin = 1;
65 | ising1.mainReplica.nodes[0][0].value = 1;
66 | ising2 = ising1;
67 | REQUIRE(ising1.getEnergy() == -3);
68 | REQUIRE(ising2.getEnergy() == -3);
69 | REQUIRE(ising1.getDelta(ising2) == 0);
70 | REQUIRE(ising2.getDelta(ising1) == 0);
71 | ising1.slices[0].nodes[0][0].flip();
72 | REQUIRE(ising1.getEnergy() == 1);
73 | REQUIRE(ising2.getEnergy() == -3);
74 | REQUIRE(ising1.getDelta(ising2) == 4);
75 | REQUIRE(ising2.getDelta(ising1) == -4);
76 | }
77 |
78 | TEST_CASE("Ising2dTransverse getIsingDiscreteEnergy()", "[ising]") {
79 | Ising2dTransverse ising;
80 | REQUIRE(ising.getEnergy() == 0);
81 | ising.numberOfreplicas = 3;
82 | ising.periodicBoundary = false;
83 | ising.mainReplica.periodicBoundary = false;
84 | ising.mainReplica.generate();
85 | ising.generate();
86 | REQUIRE(ising.slices[0].getEnergy() == ising.getIsingDiscreteEnergy());
87 | }
88 |
89 | TEST_CASE("Ising2dTransverse getIsingContinueEnergy()", "[ising]") {
90 | Ising2dTransverse ising;
91 | REQUIRE(ising.getEnergy() == 0);
92 | ising.numberOfreplicas = 3;
93 | ising.periodicBoundary = false;
94 | ising.mainReplica.periodicBoundary = false;
95 | ising.mainReplica.generate();
96 | ising.generate();
97 | REQUIRE(ising.slices[0].getEnergy() == ising.getIsingContinueEnergy());
98 | }
99 |
100 | TEST_CASE("Ising2dTransverse getIsingAVGEnergy()", "[ising]") {
101 | Ising2dTransverse ising;
102 | REQUIRE(ising.getEnergy() == 0);
103 | ising.numberOfreplicas = 3;
104 | ising.periodicBoundary = false;
105 | ising.mainReplica.periodicBoundary = false;
106 | ising.mainReplica.generate();
107 | ising.generate();
108 | REQUIRE(ising.slices[0].getEnergy() == ising.getIsingAVGEnergy());
109 | }
--------------------------------------------------------------------------------
/tests/algorithms/SwendsenWangTest.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace QMCm;
4 | static Uniform uniform;
5 |
6 | void printJoins(std::vector>> joins);
7 | void printIsing(Ising2d ising);
8 |
9 | TEST_CASE("SwendsenWang SwendsenWang()", "[sw]") {
10 | SwendsenWang sw;
11 | REQUIRE(sw.scale != 0);
12 | }
13 |
14 | TEST_CASE("SwendsenWang [prob] generateJoins(ising)", "[sw, joins]") {
15 | SwendsenWang sw;
16 | Ising2d ising;
17 | int trueCount = 0;
18 | int falseCount = 0;
19 | std::vector>> joins;
20 | ising.size = 10;
21 | ising.generate();
22 | joins = sw.generateJoins(ising);
23 |
24 | for (int i = 0; i < joins.size(); i++)
25 | for (int j = 0; j < joins[i].size(); j++)
26 | for (int k = 0; k < joins[i][j].size(); k++)
27 | if (joins[i][j][k])
28 | trueCount++;
29 | else
30 | falseCount++;
31 |
32 | REQUIRE(trueCount > 0);
33 | REQUIRE(falseCount > 0);
34 | }
35 |
36 | TEST_CASE("SwendsenWang [prob] generateClusters(ising, joins)", "[sw, clusters]") {
37 | SwendsenWang sw;
38 | Ising2d ising;
39 | int count = 0;
40 | std::vector>> joins;
41 | std::vector> clusters;
42 | ising.size = 5;
43 | ising.generate();
44 | joins = sw.generateJoins(ising);
45 | clusters = sw.generateClusters(ising, joins);
46 | REQUIRE(clusters.size() > 0);
47 | for (int i = 0; i < clusters.size(); i++)
48 | count += clusters[i].size();
49 | REQUIRE(ising.size * ising.size == count);
50 | }
51 |
52 | TEST_CASE("SwendsenWang [prob] randomFlip(clusters)", "[sw, ising1]") {
53 | SwendsenWang sw;
54 | Ising2d ising1, ising2;
55 | bool equals = true;
56 | std::vector>> joins;
57 | std::vector> clusters;
58 | ising1.size = 5;
59 | ising1.generate();
60 | ising2 = ising1;
61 | joins = sw.generateJoins(ising1);
62 | clusters = sw.generateClusters(ising1, joins);
63 | sw.randomFlip(clusters);
64 | for (int i = 0; i < ising1.nodes.size(); i++)
65 | for (int j = 0; j < ising1.nodes[i].size(); j++)
66 | if (ising1.nodes[i][j].spin != ising2.nodes[i][j].spin) {
67 | equals = false;
68 | break;
69 | }
70 | REQUIRE(!equals);
71 | }
72 |
73 | TEST_CASE("SwendsenWang [prob] run()", "[sw]") {
74 | SwendsenWang sw;
75 | sw.startingConfig.generate();
76 | sw.numberOfIterations = 100;
77 | double min = 999;
78 | for (int i = 0; i < 10; i++) {
79 | sw.run();
80 | if (min > sw.endingConfig.getEnergy()) min = sw.endingConfig.getEnergy();
81 | }
82 | REQUIRE(sw.startingConfig.getEnergy() > min);
83 | }
84 |
85 | void printJoins(std::vector>> joins) {
86 | printf("-----------UP-----------\n");
87 | for (int i = 0; i < joins.size(); i++) {
88 | for (int j = 0; j < joins[i].size(); j++)
89 | printf(" %d", joins[i][j][UP] ? 1 : 0);
90 | printf("\n");
91 | }
92 |
93 | printf("----------LEFT----------\n");
94 | for (int i = 0; i < joins.size(); i++) {
95 | for (int j = 0; j < joins[i].size(); j++)
96 | printf(" %d", joins[i][j][LEFT] ? 1 : 0);
97 | printf("\n");
98 | }
99 | }
100 |
101 | void printIsing(Ising2d ising) {
102 | printf("----------NODES---------\n");
103 | for (int i = 0; i < ising.nodes.size(); i++) {
104 | for (int j = 0; j < ising.nodes[i].size(); j++)
105 | printf(" %d [%f]", ising.nodes[i][j].spin, ising.nodes[i][j].value);
106 | printf("\n");
107 | }
108 |
109 | // printf("---------ARCS-UP-------\n");
110 | // for (int i = 0; i < ising.arcs.size(); i++) {
111 | // for (int j = 0; j < ising.arcs[i].size(); j++)
112 | // printf(" %f[%s][%s]", ising.arcs[i][j][UP].value,
113 | // ising.arcs[i][j][UP].node1 != nullptr ? ising.arcs[i][j][UP].node1->id.c_str() : "NULL",
114 | // ising.arcs[i][j][UP].node2 != nullptr ? ising.arcs[i][j][UP].node2->id.c_str() : "NULL");
115 | // printf("\n");
116 | // }
117 |
118 | // printf("--------ARCS-DOWN------\n");
119 | // for (int i = 0; i < ising.arcs.size(); i++) {
120 | // for (int j = 0; j < ising.arcs[i].size(); j++)
121 | // printf(" %f[%s][%s]", ising.arcs[i][j][LEFT].value,
122 | // ising.arcs[i][j][LEFT].node1 != nullptr ? ising.arcs[i][j][LEFT].node1->id.c_str() : "NULL",
123 | // ising.arcs[i][j][LEFT].node2 != nullptr ? ising.arcs[i][j][LEFT].node2->id.c_str() : "NULL");
124 | // printf("\n");
125 | // }
126 | }
--------------------------------------------------------------------------------
/src/algorithms/RiegerKawashimaContinuous.cpp:
--------------------------------------------------------------------------------
1 | #include "../../include/QMC-methods/RiegerKawashimaContinuous.h"
2 | #include
3 | #include
4 | using namespace QMCm;
5 | static Uniform uniform;
6 |
7 | RiegerKawashimaContinuous::RiegerKawashimaContinuous() {
8 | temperature = 1;
9 | numberOfreplicas = 3;
10 | startingField = 100;
11 | endingField = 0;
12 | deltaField = 1;
13 | scale = 10;
14 | }
15 |
16 | std::vector>> RiegerKawashimaContinuous::generateCuts(Ising2dTransverse ising) {
17 | int beta = ising.mainReplica.favorAlignment ? -1 : 1;
18 | double deltaTau = 1 / (temperature * ising.numberOfreplicas);
19 | std::vector>> cuts =
20 | std::vector>>(
21 | ising.slices.size(),
22 | std::vector>(ising.mainReplica.size, std::vector(ising.mainReplica.size)));
23 | int count[ising.mainReplica.size][ising.mainReplica.size] = {};
24 | for (int s = 0; s < ising.slices.size(); s++)
25 | for (int i = 0; i < ising.slices[s].nodes.size(); i++) {
26 | for (int j = 0; j < ising.slices[s].nodes[i].size(); j++) {
27 | if (s == ising.slices.size() - 1)
28 | if (!ising.periodicBoundary || uniform() < (1 - exp(ising.tranverseField * count[i][j] * deltaTau))) {
29 | cuts[0][i][j] = true;
30 | count[i][j] = 0;
31 | } else {
32 | cuts[0][i][j] = false;
33 | count[i][j]++;
34 | }
35 | if (s > 0)
36 | if (ising.slices[s].nodes[i][j].spin != ising.slices[s - 1].nodes[i][j].spin || uniform() < (1 - exp(ising.tranverseField * count[i][j] * deltaTau))) {
37 | cuts[s][i][j] = true;
38 | count[i][j] = 0;
39 | } else {
40 | cuts[s][i][j] = false;
41 | count[i][j]++;
42 | }
43 | }
44 | }
45 | return cuts;
46 | }
47 |
48 | std::vector RiegerKawashimaContinuous::generateSegments(Ising2dTransverse ising, std::vector>> cuts) {
49 | std::vector segments;
50 | int lastSegment = -1;
51 | int loopSegment = 0;
52 | int beta = ising.mainReplica.favorAlignment ? -1 : 1;
53 | double deltaTau = 1 / (temperature * ising.numberOfreplicas);
54 | for (int i = 0; i < ising.mainReplica.nodes.size(); i++)
55 | for (int j = 0; j < ising.mainReplica.nodes[i].size(); j++) {
56 | for (int s = 0; s < ising.slices.size(); s++) {
57 | // if (!(s > 0 &&
58 | // ising.slices[s - 1].nodes[i][j].spin == ising.slices[s].nodes[i][j].spin &&
59 | // (uniform() < (1 - exp(ising.tranverseField * segments[lastSegment].size() * deltaTau))))) {
60 | // lastSegment++;
61 | // if (s == 0) loopSegment = lastSegment;
62 | // segments[lastSegment].spin = ising.slices[s].nodes[i][j].spin;
63 | // }
64 | // segments[lastSegment].points.push_back(Point(s, i, j));
65 | // if (s == (ising.slices.size() - 1) &&
66 | // segments[loopSegment].value == segments[lastSegment].value &&
67 | // (uniform() < (1 - exp(ising.tranverseField * (segments[loopSegment].end.x - segments[loopSegment].begin.x + segments[lastSegment].end.x - segments[lastSegment].begin.x) * deltaTau)))) {
68 | // // join 2 segments
69 | // // remove last segment
70 | // }
71 | }
72 | }
73 |
74 | return segments;
75 | }
76 |
77 | std::vector> RiegerKawashimaContinuous::generateClusters(Ising2d &ising, std::vector>> cuts) {
78 | std::vector> clusters;
79 | double t, j = 0;
80 | double pjoin = 1 - exp(2 * t * j);
81 | return clusters;
82 | }
83 |
84 | void RiegerKawashimaContinuous::randomFlip(std::vector> clusters) {
85 | for (int i = 0; i < clusters.size(); i++)
86 | if (uniform() < 0.5)
87 | for (int j = 0; j < clusters[i].size(); j++)
88 | clusters[i][j]->flip();
89 | }
90 |
91 | void RiegerKawashimaContinuous::run() {
92 | Ising2dTransverse currentConfig = startingConfig;
93 | std::vector>> cuts;
94 | std::vector segments;
95 | std::vector> clusters;
96 | for (double currentField = startingField; currentField > endingField; currentField -= deltaField) {
97 | cuts = generateCuts(currentConfig);
98 | // segments = generateSegments(currentConfig, cuts);
99 | // clusters = generateClusters(currentConfig, joins);
100 | // randomFlip(clusters);
101 | }
102 | endingConfig = currentConfig;
103 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
QMC-methods
4 |
5 | In this repository there are various implementations of the Monte Carlo algorithm for the calculation of the minimum in an Ising model.
6 |
7 | - Requirements -
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | ## Installation
20 | - **Manual**
21 |
22 | Download this repository:
23 | ```sh
24 | git clone git@github.com:XaBerr/quantum-monte-carlo-methods.git
25 | ```
26 | and compile it running:
27 | ```sh
28 | rm build/ -rf;cmake -S . -B build;make -C build;
29 | ```
30 |
31 | - **CMake module**
32 |
33 | Module data:
34 | ```java
35 | FetchContent_Declare(
36 | "QMC-methods"
37 | GIT_REPOSITORY https://github.com/XaBerr/quantum-monte-carlo-methods.git
38 | GIT_TAG 1.0.0
39 | )
40 | ```
41 |
42 | ## Inclusion
43 | All include files are available in the `include` directory.
44 | After the inclusion it is required to instantiate the random distribution `Uniform`.
45 | Libraries can be included individually:
46 | ```cpp
47 | #include
48 | #include
49 | #include
50 | using namespace QMCm;
51 | static Uniform uniform;
52 | ```
53 | or in batch using the single include:
54 | ```cpp
55 | #include
56 | using namespace QMCm;
57 | static Uniform uniform;
58 | ```
59 |
60 | ## Usage
61 |
62 | These are the algorithms implemented until now:
63 |
64 | - [x] [Simulated Annealing](https://link.springer.com/chapter/10.1007/0-387-28356-0_7)
65 | - [x] [SwendsenWang](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.58.86)
66 | - [x] [SantoroTosattiMartonak](https://arxiv.org/abs/cond-mat/0205280)
67 | - [ ] [RiegerKawashimaDiscrete](https://science.sciencemag.org/content/348/6231/215)
68 | - [ ] [RiegerKawashimaContinuous](https://arxiv.org/abs/cond-mat/9802104)
69 |
70 | ### Simulated Annealing
71 |
72 | First you must generate your Ising model.
73 | ```cpp
74 | SimulatedAnnealing monteCarlo;
75 | monteCarlo.startingConfig.size = 3;
76 | monteCarlo.startingConfig.generate();
77 | ```
78 |
79 | Then you can set the spins and fields values.
80 |
81 | ```cpp
82 | /*
83 | Initial nodes matrix of values
84 | 1 1 1
85 | 1 1 1
86 | 1 1 1
87 | */
88 | for (int i = 0; i < monteCarlo.startingConfig.nodes.size(); i++) {
89 | for (int j = 0; j < monteCarlo.startingConfig.nodes.size(); j++) {
90 | monteCarlo.startingConfig.nodes[i][j].value = 1;
91 | monteCarlo.startingConfig.nodes[i][j].spin = (uniform() < 0.5) ? 1 : -1;
92 | }
93 | }
94 |
95 | /*
96 | Initial arcs matrix of values
97 | 1 1 1
98 | 1 1 1
99 | 1 1 1
100 | */
101 | for (int i = 0; i < monteCarlo.startingConfig.arcs.size(); i++)
102 | for (int j = 0; j < monteCarlo.startingConfig.arcs[i].size(); j++)
103 | for (int k = 0; k < monteCarlo.startingConfig.arcs[i][k].size(); k++)
104 | monteCarlo.startingConfig.arcs[i][j][k].value = 1;
105 | ```
106 |
107 | Last you run the algorithm few times.
108 |
109 | ```cpp
110 | printf("The starting energy is [%f]\n", monteCarlo.startingConfig.getEnergy());
111 | for (int i = 0; i < 10; i++) {
112 | monteCarlo.run();
113 | printf("The ending energy is [%f]\n", monteCarlo.endingConfig.getEnergy());
114 | }
115 | ```
116 |
117 | ### Swendsen Wang
118 |
119 | First you must generate your Ising model.
120 | ```cpp
121 | SwendsenWang monteCarlo;
122 | monteCarlo.startingConfig.size = 3;
123 | monteCarlo.startingConfig.generate();
124 | ```
125 |
126 | Then you can set the spins and fields values.
127 |
128 | ```cpp
129 | /*
130 | Initial nodes matrix of values
131 | 1 1 1
132 | 1 1 1
133 | 1 1 1
134 | */
135 | for (int i = 0; i < monteCarlo.startingConfig.nodes.size(); i++) {
136 | for (int j = 0; j < monteCarlo.startingConfig.nodes.size(); j++) {
137 | monteCarlo.startingConfig.nodes[i][j].value = 1;
138 | monteCarlo.startingConfig.nodes[i][j].spin = (uniform() < 0.5) ? 1 : -1;
139 | }
140 | }
141 |
142 | /*
143 | Initial arcs matrix of values
144 | 1 1 1
145 | 1 1 1
146 | 1 1 1
147 | */
148 | for (int i = 0; i < monteCarlo.startingConfig.arcs.size(); i++)
149 | for (int j = 0; j < monteCarlo.startingConfig.arcs[i].size(); j++)
150 | for (int k = 0; k < monteCarlo.startingConfig.arcs[i][k].size(); k++)
151 | monteCarlo.startingConfig.arcs[i][j][k].value = 1;
152 | ```
153 |
154 | Last you run the algorithm few times.
155 |
156 | ```cpp
157 | printf("The starting energy is [%f]\n", monteCarlo.startingConfig.getEnergy());
158 | for (int i = 0; i < 10; i++) {
159 | monteCarlo.run();
160 | printf("The ending energy is [%f]\n", monteCarlo.endingConfig.getEnergy());
161 | }
162 | ```
163 |
164 | ### Santoro Tosatti Martonak
165 |
166 | First you must generate your Ising model that will be used to generate the transverse once.
167 | ```cpp
168 | SantoroTosattiMartonak transverseMonteCarlo;
169 | transverseMonteCarlo.startingConfig.numberOfreplicas = 3;
170 | transverseMonteCarlo.startingConfig.mainReplica.size = 3;
171 | transverseMonteCarlo.startingConfig.mainReplica.generate();
172 | ```
173 |
174 | Then you can set the spins and fields values.
175 |
176 | ```cpp
177 | /*
178 | Initial nodes matrix of values
179 | 1 1 1
180 | 1 1 1
181 | 1 1 1
182 | */
183 | for (int i = 0; i < transverseMonteCarlo.startingConfig.mainReplica.nodes.size(); i++) {
184 | for (int j = 0; j < transverseMonteCarlo.startingConfig.mainReplica.nodes[i].size(); j++) {
185 | transverseMonteCarlo.startingConfig.mainReplica.nodes[i][j].value = 1;
186 | transverseMonteCarlo.startingConfig.mainReplica.nodes[i][j].spin =
187 | (uniform() < 0.5) ? 1 : -1;
188 | }
189 | }
190 |
191 | /*
192 | Initial arcs matrix of values
193 | 1 1 1
194 | 1 1 1
195 | 1 1 1
196 | */
197 | for (int i = 0; i < transverseMonteCarlo.startingConfig.mainReplica.arcs.size(); i++)
198 | for (int j = 0; j < transverseMonteCarlo.startingConfig.mainReplica.arcs[i].size(); j++)
199 | for (int k = 0; k < transverseMonteCarlo.startingConfig.mainReplica.arcs[i][j].size(); k++)
200 | transverseMonteCarlo.startingConfig.mainReplica.arcs[i][j][k].value = 1;
201 | ```
202 |
203 | Here you have an intermediate step to generate the transverse Ising model.
204 |
205 | ```cpp
206 | transverseMonteCarlo.startingConfig.generate();
207 | ```
208 |
209 | Last you run the algorithm few times.
210 |
211 | ```cpp
212 | printf("The starting energy is [%f]\n", transverseMonteCarlo.startingConfig.getIsingDiscreteEnergy());
213 | for (int i = 0; i < 10; i++) {
214 | transverseMonteCarlo.run();
215 | printf("The ending energy is [%f]\n", transverseMonteCarlo.endingConfig.getIsingDiscreteEnergy());
216 | }
217 | ```
218 |
219 | ## 2D Ising model parameters
220 |
221 | The parameters for the Ising model (__monteCarlo.startingConfig__, __transverseMonteCarlo.startingConfig.mainReplica__) are the following:
222 | ```cpp
223 | // the size of the square of the Ising model
224 | monteCarlo.startingConfig.size = +3;
225 |
226 | // energy configuration parameters
227 | monteCarlo.startingConfig.favorAlignment = true;
228 | monteCarlo.startingConfig.favorSpinUp = true;
229 |
230 | // if we want the structure is recursive
231 | monteCarlo.startingConfig.periodicBoundary = false;
232 |
233 | // this is the boundary of the random generation that is used by default
234 | monteCarlo.startingConfig.nodeMaxValue = +1;
235 | monteCarlo.startingConfig.nodeMinValue = -1;
236 | monteCarlo.startingConfig.arcMaxValue = +1;
237 | monteCarlo.startingConfig.arcMinValue = -1;
238 | ```
239 |
240 |
241 | ## 2D Transverse Ising model parameters
242 |
243 | The parameters for the transverse Ising model (__transverseMonteCarlo.startingConfig__) are the following.
244 | ```cpp
245 | // number of replicas of the Ising model
246 | transverseMonteCarlo.startingConfig.numberOfreplicas = 3;
247 |
248 | // initial strength of the transverse field
249 | transverseMonteCarlo.startingConfig.transverseField = 1;
250 |
251 | // periodic boundary along the time direction
252 | transverseMonteCarlo.startingConfig.periodicBoundary = false;
253 | ```
254 |
255 | ## Example
256 | Also check out the example in `apps/example.cpp`.
257 |
258 | ## Contributions
259 | At the moment I don't have time to finish the last two algorithms, if you want to finish and push them, I would gladly accept a pull request.
260 |
261 | Of course if you like this repository remember to :star: the project!
--------------------------------------------------------------------------------