#include #include #include #include #include #include "randutils/randutils.hpp" #include "pcg-cpp/include/pcg_random.hpp" using Rng = randutils::random_generator; class Edge { public: unsigned index; std::list weights; double probability; Edge() { probability = 0; } }; class Face { public: std::array, 4> edges; Face(Edge& a, Edge& b, Edge& c, Edge& d) : edges({a, b, c, d}) {} }; class AztecDiamond { public: std::vector edges; std::vector> faces; AztecDiamond(unsigned n) : edges(pow(2 * n, 2)), faces(n) { for (unsigned i = 0; i < edges.size(); i++) { edges[i].index = i; } for (unsigned i = 1; i <= n; i++) { faces[n - i].reserve(pow(i, 2)); for (unsigned j = 0; j < pow(i, 2); j++) { unsigned x = j % (i); unsigned y = j / (i); unsigned x0 = n - i; unsigned y0 = n - i; faces[n - i].push_back(Face( edges[2 * n * (y0 + 2 * y) + x0 + 2 * x], edges[2 * n * (y0 + 2 * y) + x0 + 2 * x + 1], edges[2 * n * (y0 + 2 * y + 1) + x0 + 2 * x], edges[2 * n * (y0 + 2 * y + 1) + x0 + 2 * x + 1] )); } } } void computeWeights() { for (std::vector& fs : faces) { for (Face& f : fs) { double w = f.edges[0].get().weights.back(); double x = f.edges[1].get().weights.back(); double y = f.edges[2].get().weights.back(); double z = f.edges[3].get().weights.back(); double cellFactor = w * z + x * y; f.edges[0].get().weights.push_back(z / cellFactor); f.edges[1].get().weights.push_back(y / cellFactor); f.edges[2].get().weights.push_back(x / cellFactor); f.edges[3].get().weights.push_back(w / cellFactor); } } for (Edge& e : edges) { e.weights.pop_back(); } } void computeProbabilities() { for (auto it = faces.rbegin(); it != faces.rend(); it++) { for (Face& f : *it) { double p = f.edges[0].get().probability; double q = f.edges[1].get().probability; double r = f.edges[2].get().probability; double s = f.edges[3].get().probability; double w = f.edges[0].get().weights.back(); double x = f.edges[1].get().weights.back(); double y = f.edges[2].get().weights.back(); double z = f.edges[3].get().weights.back(); std::cout << w << " " << x << " " << y << " " << z << std::endl; double cellFactor = w * z + x * y; double deficit = 1 - p - q - r - s; f.edges[0].get().probability = s + deficit * w * z / cellFactor; f.edges[1].get().probability = r + deficit * x * y / cellFactor; f.edges[2].get().probability = q + deficit * x * y / cellFactor; f.edges[3].get().probability = p + deficit * w * z / cellFactor; for (Edge& e : f.edges) { if (e.weights.empty()) { std::cout << "No weights left!" << std::endl; } else { e.weights.pop_back(); } } } } } }; int main(int argc, char* argv[]) { unsigned n = 100; unsigned m = 100; int opt; while ((opt = getopt(argc, argv, "n:m:")) != -1) { switch (opt) { case 'n': n = atoi(optarg); break; case 'm': m = (unsigned)atof(optarg); break; default: exit(1); } } Rng r; // AztecDiamond a(n); /* For checking if the faces are appropriately defined. for (std::vector& fs : a.faces) { for (Face& f : fs) { for (Edge& e : f.edges) { unsigned v1 = (1 + (e.index % (2 * n))) / 2 + (n + 1) * ((e.index / 4) / n); unsigned v2 = n * (n + 1) + (e.index % (2 * n)) / 2 + n * (((e.index + 2 * n) / 4) / n); std::cout << v1 << " " << v2 << " "; } } std::cout << std::endl; } */ AztecDiamond a(3); for (Edge& e : a.edges) { e.weights.push_back(1); } a.edges[1].weights.front() = 0; a.edges[4].weights.front() = 0; a.edges[6].weights.front() = 0; a.edges[11].weights.front() = 0; a.edges[24].weights.front() = 0; a.edges[29].weights.front() = 0; a.edges[31].weights.front() = 0; a.edges[34].weights.front() = 0; a.computeWeights(); for (unsigned i = 0; i < 3; i++) { for (unsigned j = 0; j < a.edges.size(); j++) { if (j % 6 == 0) { std::cout << std::endl; } if (!a.edges[j].weights.empty()) { std::cout << a.edges[j].weights.front() << " "; a.edges[j].weights.pop_front(); } } } std::cout << std::endl; for (Edge& e : a.edges) { e.weights.push_back(1); } a.edges[1].weights.front() = 0; a.edges[4].weights.front() = 0; a.edges[6].weights.front() = 0; a.edges[11].weights.front() = 0; a.edges[24].weights.front() = 0; a.edges[29].weights.front() = 0; a.edges[31].weights.front() = 0; a.edges[34].weights.front() = 0; a.computeWeights(); a.computeProbabilities(); for (unsigned i = 0; i < a.edges.size(); i++) { if (i%6 == 0) { std::cout << std::endl; } std::cout << a.edges[i].probability << " "; } std::cout << std::endl; return 0; }