├── .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 | logo 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! --------------------------------------------------------------------------------