From 7548abd44c37d4495dd498193ea15b0df757b904 Mon Sep 17 00:00:00 2001 From: Jaron Kent-Dobias Date: Wed, 9 Jun 2021 16:32:27 +0200 Subject: Lots of work. --- glass.hpp | 677 -------------------------------------------------------------- 1 file changed, 677 deletions(-) delete mode 100644 glass.hpp (limited to 'glass.hpp') diff --git a/glass.hpp b/glass.hpp deleted file mode 100644 index b35964b..0000000 --- a/glass.hpp +++ /dev/null @@ -1,677 +0,0 @@ -#include -#include -#include -#include - -#include - -#include "pcg-cpp/include/pcg_random.hpp" -#include "randutils/randutils.hpp" - -using Rng = randutils::random_generator; - -template using Vector = Eigen::Matrix; -template using Matrix = Eigen::Matrix; - -int iPow(int x, unsigned p) { - if (p == 0) - return 1; - if (p == 1) - return x; - - int tmp = iPow(x, p / 2); - if (p % 2 == 0) - return tmp * tmp; - else - return x * tmp * tmp; -} - -unsigned mod(signed a, unsigned b) { return ((a < 0) ? (a + (1 - a / (signed)b) * b) : a) % b; } - -template Vector mod(const Eigen::MatrixBase& v, unsigned b) { - Vector u; - for (unsigned i = 0; i < D; i++) { - u(i) = mod(v(i), b); - } - return u; -} - -template void one_sequences(std::list>& sequences, unsigned level) { - if (level > 0) { - unsigned new_level = level - 1; - for (std::array& sequence : sequences) { - std::array new_sequence = sequence; - new_sequence[new_level] = -1; - sequences.push_front(new_sequence); - } - one_sequences(sequences, new_level); - } -} - -template std::vector> generateTorusMatrices() { - std::vector> mats; - - std::array ini_sequence; - ini_sequence.fill(1); - std::list> sequences; - sequences.push_back(ini_sequence); - - one_sequences(sequences, D); - - sequences.pop_back(); // don't want the identity matrix! - - for (std::array sequence : sequences) { - Matrix m; - for (unsigned i = 0; i < D; i++) { - for (unsigned j = 0; j < D; j++) { - if (i == j) { - m(i, j) = sequence[i]; - } else { - m(i, j) = 0; - } - } - } - - mats.push_back(m); - } - - for (unsigned i = 0; i < D; i++) { - for (unsigned j = 0; j < D; j++) { - if (i != j) { - Matrix m; - for (unsigned k = 0; k < D; k++) { - for (unsigned l = 0; l < D; l++) { - if ((k == i && l == j) || (k == j && l == i)) { - if (i < j) { - m(k, l) = 1; - } else { - m(k, l) = -1; - } - } else if (k == l && (k != i && k != j)) { - m(k, l) = 1; - } else { - m(k, l) = 0; - } - } - } - mats.push_back(m); - } - } - } - - return mats; -} - -template class CiamarraState : public Vector { -public: - CiamarraState() : Vector(Vector::Zero()) {} - - CiamarraState(const Vector& v) : Vector(v) {} - - CiamarraState(unsigned a, signed b) : Vector(Vector::Zero()) { this->operator()(a) = b; } - - CiamarraState(Rng& r) : CiamarraState(r.uniform(0, D - 1), r.pick({-1, 1})) {} - - bool isEmpty() const { return this->squaredNorm() == 0; } - - void remove() { this->setZero(); } - - CiamarraState flip() const { - CiamarraState s; - for (unsigned i = 0; i < D; i++) { - s(i) = -this->operator()(i); - } - return s; - } -}; - -class BiroliState { -public: - unsigned type; - unsigned occupiedNeighbors; - - BiroliState() { - type = std::numeric_limits::max(); - occupiedNeighbors = 0; - } - - BiroliState(unsigned t, unsigned o) { - type = t; - occupiedNeighbors = o; - } - - BiroliState(Rng& r) { - type = r.pick({1,2,2,2,2,2,3,3,3,3}); - } - - bool isEmpty() const { return type == std::numeric_limits::max(); } - - void remove() { type = std::numeric_limits::max(); }; -}; - -template class Transformation { -public: - unsigned L; - Matrix m; - Vector v; - - Transformation(unsigned L) : L(L) { - m.setIdentity(); - v.setZero(); - } - - Transformation(unsigned L, const Matrix& m, const Vector& v) : L(L), m(m), v(v) {} - - Transformation(unsigned L, const std::vector>& ms, Rng& r) : m(r.pick(ms)), L(L) { - for (unsigned i = 0; i < D; i++) { - v[i] = r.uniform((unsigned)0, L - 1); - } - - v = v - m * v; - } - - Transformation inverse() const { - return Transformation(L, m.transpose(), -m.transpose() * v); - } - - Vector apply(const Vector& x) const { return mod(v + m * x, L); } - - Transformation apply(const Transformation& t) const { - Transformation tNew(L); - - tNew.m = m * t.m; - tNew.v = apply(t.v); - - return tNew; - } - - CiamarraState apply(const CiamarraState& s) const { return CiamarraState(m * s); } - - BiroliState apply(const BiroliState& s) const { return s; } -}; - -template class HalfEdge; - -template class Vertex { -public: - Vector position; - std::vector> adjacentEdges; - State state; - bool marked; - - bool isEmpty() const { return state.isEmpty(); } -}; - -template class HalfEdge { -public: - Vertex& neighbor; - Vector Δx; - - HalfEdge(Vertex& n, const Vector& d) : neighbor(n), Δx(d) {} -}; - -template class System { -public: - const unsigned L; - unsigned N; - std::vector> vertices; - Transformation orientation; - - unsigned vectorToIndex(const Vector& x) const { - unsigned i = 0; - for (unsigned d = 0; d < D; d++) { - i += x[d] * iPow(L, d); - } - return i; - } - - Vector indexToVector(unsigned i) const { - Vector x; - for (unsigned d = 0; d < D; d++) { - x[d] = (i / iPow(L, d)) % L; - } - return x; - } - - System(unsigned L) : L(L), N(0), vertices(iPow(L, D)), orientation(L) { - for (unsigned i = 0; i < iPow(L, D); i++) { - vertices[i].position = indexToVector(i); - vertices[i].adjacentEdges.reserve(2 * D); - vertices[i].marked = false; - } - - for (unsigned d = 0; d < D; d++) { - Vector Δx = Vector::Zero(); - Δx[d] = 1; - for (signed i = 0; i < iPow(L, D); i++) { - unsigned j = iPow(L, d + 1) * (i / iPow(L, d + 1)) + mod(i + iPow(L, d), pow(L, d + 1)); - vertices[i].adjacentEdges.push_back(HalfEdge(vertices[j], Δx)); - vertices[j].adjacentEdges.push_back(HalfEdge(vertices[i], -Δx)); - } - } - } - - virtual std::list>> overlaps(Vertex&) { return {}; }; - - virtual bool insert(Vertex& v, const State& s, bool force = false) { return false; }; - - virtual bool remove(Vertex& v) { return false;}; - - virtual bool randomMove(Rng& r) { return false;}; - - virtual void swap(Vertex& v1, Vertex& v2) {}; - - virtual bool exchange(Vertex& v1, Vertex& v2) { return false;}; - - bool randomExchange(Rng& r) { - Vertex& v1 = r.pick(vertices); - Vertex& v2 = r.pick(vertices); - - return exchange(v1, v2); - } - - bool compatible() { - for (Vertex& v : vertices) { - if (overlaps(v).size() > 0) { - return false; - } - } - - return true; - } - - double density() const { return N / pow(L, D); } - - unsigned size() const { return vertices.size(); } - - void sweepGrandCanonical(double z, Rng& r) { - for (unsigned i = 0; i < iPow(L, D); i++) { - if (0.5 < r.uniform(0.0, 1.0)) { - double pIns = size() * z / (N + 1); - - if (pIns > r.uniform(0.0, 1.0)) { - while (true) { - Vertex& v = r.pick(vertices); - if (v.isEmpty()) { - insert(v, State(r)); - break; - } - } - } - } else { - - double pDel = N / (z * size()); - - if (pDel > r.uniform(0.0, 1.0)) { - remove(r.pick(vertices)); - } - } - - randomMove(r); - } - } - - void sweepLocal(Rng& r) { - for (unsigned i = 0; i < iPow(L, D); i++) { - randomMove(r); - } - } - - void sweepSwap(Rng& r) { - for (unsigned i = 0; i < iPow(L, D); i++) { - randomExchange(r); - } - } - - unsigned flipCluster(const Transformation& R, Vertex& v0, bool dry = false) { - unsigned n = 0; - - Vertex& v0New = vertices[vectorToIndex(R.apply(v0.position))]; - - if (&v0New != &v0) { - std::queue>> q; - - v0.marked = true; - v0New.marked = true; - - swap(v0, v0New); - - for (Vertex& vn : overlaps(v0)) { - if (!vn.marked) { - q.push(vn); - } - } - for (Vertex& vn : overlaps(v0New)) { - if (!vn.marked) { - q.push(vn); - } - } - - while (!q.empty()) { - Vertex& v = q.front(); - q.pop(); - - if (!v.marked && !overlaps(v).empty()) { - v.marked = true; - Vertex& vNew = vertices[vectorToIndex(R.apply(v.position))]; - - if (&vNew != &v) { - vNew.marked = true; - - swap(v, vNew); - - for (Vertex& vn : overlaps(v)) { - if (!vn.marked) { - q.push(vn); - } - } - for (Vertex& vn : overlaps(vNew)) { - if (!vn.marked) { - q.push(vn); - } - } - - n += 2; - } else { - n += 1; - } - } - if (q.empty()) { - for (Vertex& vv : vertices) { - if (!vv.marked && !overlaps(vv).empty()) { -// std::cerr << "Found bad state at end" << std::endl; - q.push(vv); - } - } - } - } - - - } - - if (n > size() / 4) { - orientation = R.apply(orientation); - } - - for (Vertex& v : vertices) { - v.marked = false; - } - - return n; - } - - void swendsenWang(const Transformation& R, Rng& r) { - for (Vertex& v : vertices) { - if (!v.marked) { - bool dry = 0.5 < r.uniform(0.0, 1.0); - unsigned n = flipCluster(R, v, dry); - if (n > size() / 4 && !dry) { - orientation = R.apply(orientation); - } - } - } - - for (Vertex& v : vertices) { - v.marked = false; - } - } - - virtual int overlap(const System& s) const { return 0; }; -}; - -template class CiamarraSystem : public System> { - public: - - using System>::System; - std::list>>> - overlaps(Vertex>& v, const CiamarraState& s, - bool excludeSelf = false) override { - std::list>>> o; - - if (s.isEmpty()) { - return o; - } - - if (!v.isEmpty() && !excludeSelf) { - o.push_back(v); - } - - for (const HalfEdge>& e : v.adjacentEdges) { - if (!e.neighbor.isEmpty()) { - if (s.dot(e.Δx) == 1 || e.neighbor.state.dot(e.Δx) == -1) { - o.push_back(e.neighbor); - } - } - } - - return o; - } - - bool insert(Vertex>& v, const CiamarraState& s, bool force = false) override { - if (force || overlaps(v, s).empty()) { - v.state = s; - this->N++; - return true; - } else { - return false; - } - } - - bool remove(Vertex>& v) override { - if (v.isEmpty()) { - return false; - } else { - v.state.remove(); - this->N--; - return true; - } - } - - bool randomMove(Rng& r) override { - Vertex>& v = r.pick(this->vertices); - CiamarraState oldState = v.state; - - if (!remove(v)) { - return false; - } - - if (1.0 / (2.0 * D) > r.uniform(0.0, 1.0)) { - for (HalfEdge>& e : v.adjacentEdges) { - if (1 == e.Δx.dot(oldState)) { - if (insert(e.neighbor, oldState.flip())) { - return true; - } - break; - } - } - } else { - CiamarraState newState(r); - while (newState.dot(oldState) == 1) { - newState = CiamarraState(r); - } - if (insert(v, newState)) { - return true; - } - } - v.state = oldState; - this->N++; - return false; - } - - void swap(Vertex>& v1, Vertex>& v2) override { - std::swap(v1.state, v2.state); - } - - bool exchange(Vertex>& v1, Vertex>& v2) override { - if (overlaps(v1, v2.state, true).size() == 0 && overlaps(v2, v1.state, true).size() == 0) { - swap(v1, v2); - return true; - } else { - return false; - } - } - - void setGroundState() { - this->N = 0; - - for (Vertex>& v : this->vertices) { - unsigned a = 0; - for (unsigned d = 0; d < D; d++) { - a += (d + 1) * v.position(d); - } - a %= 2 * D + 1; - - v.state.setZero() = Vector::Zero(); - - if (0 < a && a <= D) { - v.state(a - 1) = -1; - this->N++; - } else if (D < a) { - v.state(2 * D - a) = 1; - this->N++; - } - } - } - - int overlap(const System>& s) const override { - int o = 0; - - for (unsigned i = 0; i < this->vertices.size(); i++) { - CiamarraState s2 = this->orientation.apply( - s.vertices[this->vectorToIndex(this->orientation.inverse().apply(this->indexToVector(i)))].state); - o += this->vertices[i].state.dot(s2); - } - - return o; - } -}; - -template class BiroliSystem : public System { -public: - using System::System; - - bool canReplaceWith(const Vertex& v, const BiroliState& s) { - if (s.isEmpty()) { - return true; - } - if (s.type < v.state.occupiedNeighbors) { - return false; - } else { - int Δn = 0; - if (v.isEmpty()) { - Δn += 1; - } - for (const HalfEdge& e : v.adjacentEdges) { - if (e.neighbor.state.type < e.neighbor.state.occupiedNeighbors + Δn) { - return false; - } - } - } - return true; - } - - std::list>> - overlaps(Vertex& v) override { - std::list>> o; - - if (v.isEmpty()) { // an empty site cannot be frustrating anyone - return o; - } - - bool selfFrustrated = v.state.occupiedNeighbors > v.state.type; - bool anyNeighborFrustrated = false; - - for (const HalfEdge& e : v.adjacentEdges) { - if (!e.neighbor.isEmpty()) { - bool thisNeighborFrustrated = e.neighbor.state.type < e.neighbor.state.occupiedNeighbors; - - if (thisNeighborFrustrated) { - anyNeighborFrustrated = true; - } - - if (selfFrustrated || thisNeighborFrustrated) { - o.push_back(e.neighbor); - } - } - } - - if (selfFrustrated || anyNeighborFrustrated) { - o.push_back(v); - } - - return o; - } - - bool insert(Vertex& v, const BiroliState& s, bool force = false) override { - if (force || (v.isEmpty() && canReplaceWith(v, s))) { - v.state.type = s.type; - for (HalfEdge& e : v.adjacentEdges) { - e.neighbor.state.occupiedNeighbors++; - } - this->N++; - return true; - } else { - return false; - } - } - - bool remove(Vertex& v) override { - if (v.isEmpty()) { - return false; - } else { - v.state.remove(); - for (HalfEdge& e : v.adjacentEdges) { - e.neighbor.state.occupiedNeighbors--; - } - this->N--; - return true; - } - } - - bool randomMove(Rng& r) override { - Vertex& v = r.pick(this->vertices); - - return exchange(v, r.pick(v.adjacentEdges).neighbor); - } - - void swap(Vertex& v1, Vertex& v2) override { - if (v1.state.type != v2.state.type) { - if (!v1.isEmpty() && !v2.isEmpty()) { - std::swap(v1.state.type, v2.state.type); - } else if (v1.isEmpty()) { - unsigned t = v2.state.type; - remove(v2); - insert(v1, BiroliState(t, 0), true); - } else { - unsigned t = v1.state.type; - remove(v1); - insert(v2, BiroliState(t, 0), true); - } - } - } - - bool exchange(Vertex& v1, Vertex& v2) override { - if (canReplaceWith(v1, v2.state) && canReplaceWith(v2, v1.state)) { - swap(v1, v2); - return true; - } else { - return false; - } - } - - int overlap(const System& s) const override { - int o = 0; - - for (unsigned i = 0; i < this->vertices.size(); i++) { - BiroliState s2 = this->orientation.apply( - s.vertices[this->vectorToIndex(this->orientation.inverse().apply(this->indexToVector(i)))].state); - if (s2.type > 0 && s2.type == this->vertices[i].state.type) { - o++; - } else { - o--; - } - } - - return o; - } -}; -- cgit v1.2.3-54-g00ecf