| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #ifndef HPC_MOBIUS_H |
| #define HPC_MOBIUS_H |
|
|
| #include "hpc_graph.h" |
| #include "hpc_contract.h" |
| #include "hpc_amplitude.h" |
| #include <math.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdio.h> |
|
|
| |
| |
| |
|
|
| #define MOBIUS_D 6 |
| #define MOBIUS_MAX_DEGREE 128 |
| #define MOBIUS_BP_MAX_ITER 100 |
| #define MOBIUS_BP_TOL 1e-14 |
| #define MOBIUS_DAMPING 0.3 |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| typedef struct { |
| double p[MOBIUS_D]; |
| } MobiusProbMsg; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| typedef struct { |
| |
| double dressed_re[MOBIUS_D]; |
| double dressed_im[MOBIUS_D]; |
|
|
| |
| double marginal[MOBIUS_D]; |
|
|
| |
| MobiusProbMsg *msg_in; |
| uint64_t n_messages; |
| uint64_t msg_capacity; |
|
|
| |
| double vesica_re[3], vesica_im[3]; |
| double wave_re[3], wave_im[3]; |
| int vesica_valid; |
|
|
| |
| double coherence; |
| } MobiusSiteSheet; |
|
|
| |
| |
| |
|
|
| typedef struct { |
| const HPCGraph *graph; |
|
|
| uint64_t n_sites; |
| MobiusSiteSheet *sheets; |
|
|
| int converged; |
| int iterations; |
| double max_residual; |
|
|
| uint64_t msg_updates; |
| uint64_t amplitude_queries; |
| uint64_t surface_walks; |
| double bethe_free_energy; |
| } MobiusAmplitudeSheet; |
|
|
| |
| |
| |
|
|
| static inline MobiusAmplitudeSheet *mobius_create(const HPCGraph *g) |
| { |
| MobiusAmplitudeSheet *ms = (MobiusAmplitudeSheet *)calloc(1, sizeof(MobiusAmplitudeSheet)); |
| if (!ms) return NULL; |
|
|
| ms->graph = g; |
| ms->n_sites = g->n_sites; |
| ms->sheets = (MobiusSiteSheet *)calloc(g->n_sites, sizeof(MobiusSiteSheet)); |
| if (!ms->sheets) { free(ms); return NULL; } |
|
|
| for (uint64_t k = 0; k < g->n_sites; k++) { |
| MobiusSiteSheet *s = &ms->sheets[k]; |
| const HPCAdjList *adj = &g->adj[k]; |
|
|
| s->n_messages = adj->count; |
| s->msg_capacity = adj->count > 0 ? adj->count : 1; |
| s->msg_in = (MobiusProbMsg *)calloc(s->msg_capacity, sizeof(MobiusProbMsg)); |
|
|
| |
| for (uint64_t m = 0; m < s->n_messages; m++) |
| for (int v = 0; v < MOBIUS_D; v++) |
| s->msg_in[m].p[v] = 1.0; |
|
|
| |
| double total = 0.0; |
| for (int v = 0; v < MOBIUS_D; v++) { |
| s->marginal[v] = g->locals[k].edge_re[v] * g->locals[k].edge_re[v] + |
| g->locals[k].edge_im[v] * g->locals[k].edge_im[v]; |
| total += s->marginal[v]; |
| } |
| if (total > 1e-30) |
| for (int v = 0; v < MOBIUS_D; v++) |
| s->marginal[v] /= total; |
|
|
| |
| for (int v = 0; v < MOBIUS_D; v++) { |
| s->dressed_re[v] = g->locals[k].edge_re[v]; |
| s->dressed_im[v] = g->locals[k].edge_im[v]; |
| } |
|
|
| s->vesica_valid = 0; |
| s->coherence = 0.5; |
| } |
|
|
| return ms; |
| } |
|
|
| static inline void mobius_destroy(MobiusAmplitudeSheet *ms) |
| { |
| if (!ms) return; |
| if (ms->sheets) { |
| for (uint64_t k = 0; k < ms->n_sites; k++) |
| free(ms->sheets[k].msg_in); |
| free(ms->sheets); |
| } |
| free(ms); |
| } |
|
|
| |
| |
| |
|
|
| static inline int mobius_find_msg_idx(const HPCGraph *g, uint64_t site, uint64_t eid) |
| { |
| const HPCAdjList *adj = &g->adj[site]; |
| for (uint64_t i = 0; i < adj->count; i++) |
| if (adj->edge_ids[i] == eid) return (int)i; |
| return -1; |
| } |
|
|
| |
| |
| |
| |
| |
| |
|
|
| static inline double mobius_edge_factor(const HPCEdge *edge, |
| uint32_t va, uint32_t vb) |
| { |
| if (edge->type == HPC_EDGE_CZ) { |
| return 1.0; |
| } else { |
| double wr = edge->w_re[va][vb]; |
| double wi = edge->w_im[va][vb]; |
| return wr * wr + wi * wi; |
| } |
| } |
|
|
| |
| |
| |
|
|
| static inline void mobius_edge_weight(const HPCEdge *edge, |
| uint32_t va, uint32_t vb, |
| double *w_re, double *w_im) |
| { |
| if (edge->type == HPC_EDGE_CZ) { |
| uint32_t pidx = (va * vb) % MOBIUS_D; |
| *w_re = HPC_W6_RE[pidx]; |
| *w_im = HPC_W6_IM[pidx]; |
| } else { |
| *w_re = edge->w_re[va][vb]; |
| *w_im = edge->w_im[va][vb]; |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| static inline double mobius_bp_iterate(MobiusAmplitudeSheet *ms) |
| { |
| const HPCGraph *g = ms->graph; |
| double max_delta = 0.0; |
|
|
| for (uint64_t eid = 0; eid < g->n_edges; eid++) { |
| const HPCEdge *edge = &g->edges[eid]; |
| uint64_t sa = edge->site_a; |
| uint64_t sb = edge->site_b; |
|
|
| int idx_a_in_b = mobius_find_msg_idx(g, sb, eid); |
| int idx_b_in_a = mobius_find_msg_idx(g, sa, eid); |
| if (idx_a_in_b < 0 || idx_b_in_a < 0) continue; |
|
|
| |
| { |
| MobiusProbMsg new_msg; |
| const MobiusSiteSheet *sheet_a = &ms->sheets[sa]; |
| const HPCAdjList *adj_a = &g->adj[sa]; |
|
|
| for (int vb = 0; vb < MOBIUS_D; vb++) { |
| double sum = 0.0; |
|
|
| for (int va = 0; va < MOBIUS_D; va++) { |
| |
| double local_prob = g->locals[sa].edge_re[va] * g->locals[sa].edge_re[va] + |
| g->locals[sa].edge_im[va] * g->locals[sa].edge_im[va]; |
|
|
| |
| for (uint64_t mi = 0; mi < adj_a->count; mi++) { |
| if (adj_a->edge_ids[mi] == eid) continue; |
| local_prob *= sheet_a->msg_in[mi].p[va]; |
| } |
|
|
| |
| double ef = mobius_edge_factor(edge, va, vb); |
| sum += local_prob * ef; |
| } |
|
|
| new_msg.p[vb] = sum; |
| } |
|
|
| |
| double msg_sum = 0.0; |
| for (int v = 0; v < MOBIUS_D; v++) msg_sum += new_msg.p[v]; |
| if (msg_sum > 1e-30) { |
| double inv = 1.0 / msg_sum; |
| for (int v = 0; v < MOBIUS_D; v++) new_msg.p[v] *= inv; |
| } |
|
|
| |
| MobiusProbMsg *old_msg = &ms->sheets[sb].msg_in[idx_a_in_b]; |
| double delta = 0.0; |
| for (int v = 0; v < MOBIUS_D; v++) { |
| double updated = MOBIUS_DAMPING * new_msg.p[v] + |
| (1.0 - MOBIUS_DAMPING) * old_msg->p[v]; |
| double diff = updated - old_msg->p[v]; |
| delta += diff * diff; |
| old_msg->p[v] = updated; |
| } |
| if (delta > max_delta) max_delta = delta; |
| ms->msg_updates++; |
| } |
|
|
| |
| { |
| MobiusProbMsg new_msg; |
| const MobiusSiteSheet *sheet_b = &ms->sheets[sb]; |
| const HPCAdjList *adj_b = &g->adj[sb]; |
|
|
| for (int va = 0; va < MOBIUS_D; va++) { |
| double sum = 0.0; |
|
|
| for (int vb = 0; vb < MOBIUS_D; vb++) { |
| double local_prob = g->locals[sb].edge_re[vb] * g->locals[sb].edge_re[vb] + |
| g->locals[sb].edge_im[vb] * g->locals[sb].edge_im[vb]; |
|
|
| for (uint64_t mi = 0; mi < adj_b->count; mi++) { |
| if (adj_b->edge_ids[mi] == eid) continue; |
| local_prob *= sheet_b->msg_in[mi].p[vb]; |
| } |
|
|
| |
| |
| |
| double ef = mobius_edge_factor(edge, va, vb); |
| sum += local_prob * ef; |
| } |
|
|
| new_msg.p[va] = sum; |
| } |
|
|
| double msg_sum = 0.0; |
| for (int v = 0; v < MOBIUS_D; v++) msg_sum += new_msg.p[v]; |
| if (msg_sum > 1e-30) { |
| double inv = 1.0 / msg_sum; |
| for (int v = 0; v < MOBIUS_D; v++) new_msg.p[v] *= inv; |
| } |
|
|
| MobiusProbMsg *old_msg = &ms->sheets[sa].msg_in[idx_b_in_a]; |
| double delta = 0.0; |
| for (int v = 0; v < MOBIUS_D; v++) { |
| double updated = MOBIUS_DAMPING * new_msg.p[v] + |
| (1.0 - MOBIUS_DAMPING) * old_msg->p[v]; |
| double diff = updated - old_msg->p[v]; |
| delta += diff * diff; |
| old_msg->p[v] = updated; |
| } |
| if (delta > max_delta) max_delta = delta; |
| ms->msg_updates++; |
| } |
| } |
|
|
| return max_delta; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| static inline void mobius_compute_beliefs(MobiusAmplitudeSheet *ms) |
| { |
| const HPCGraph *g = ms->graph; |
|
|
| for (uint64_t k = 0; k < ms->n_sites; k++) { |
| MobiusSiteSheet *s = &ms->sheets[k]; |
|
|
| |
| double belief[MOBIUS_D]; |
| double total = 0.0; |
| for (int v = 0; v < MOBIUS_D; v++) { |
| belief[v] = g->locals[k].edge_re[v] * g->locals[k].edge_re[v] + |
| g->locals[k].edge_im[v] * g->locals[k].edge_im[v]; |
|
|
| for (uint64_t mi = 0; mi < s->n_messages; mi++) |
| belief[v] *= s->msg_in[mi].p[v]; |
|
|
| total += belief[v]; |
| } |
|
|
| |
| if (total > 1e-30) { |
| for (int v = 0; v < MOBIUS_D; v++) |
| s->marginal[v] = belief[v] / total; |
| } else { |
| for (int v = 0; v < MOBIUS_D; v++) |
| s->marginal[v] = 1.0 / MOBIUS_D; |
| } |
|
|
| |
| |
| |
| |
| |
| for (int v = 0; v < MOBIUS_D; v++) { |
| double local_prob = g->locals[k].edge_re[v] * g->locals[k].edge_re[v] + |
| g->locals[k].edge_im[v] * g->locals[k].edge_im[v]; |
| if (local_prob > 1e-30) { |
| double scale = sqrt(s->marginal[v] / local_prob); |
| s->dressed_re[v] = g->locals[k].edge_re[v] * scale; |
| s->dressed_im[v] = g->locals[k].edge_im[v] * scale; |
| } else { |
| s->dressed_re[v] = 0.0; |
| s->dressed_im[v] = 0.0; |
| } |
| } |
|
|
| |
| double coh_re = 0.0, coh_im = 0.0; |
| double d_total = 0.0; |
| for (int v = 0; v < MOBIUS_D; v++) { |
| coh_re += s->dressed_re[v]; |
| coh_im += s->dressed_im[v]; |
| d_total += s->dressed_re[v] * s->dressed_re[v] + |
| s->dressed_im[v] * s->dressed_im[v]; |
| } |
| double coh_num = coh_re * coh_re + coh_im * coh_im; |
| s->coherence = (d_total > 1e-30) ? |
| coh_num / (MOBIUS_D * d_total) : 0.5; |
|
|
| s->vesica_valid = 0; |
| } |
| } |
|
|
| |
| |
| |
|
|
| static inline int mobius_converge(MobiusAmplitudeSheet *ms) |
| { |
| if (ms->graph->n_edges == 0) { |
| mobius_compute_beliefs(ms); |
| ms->converged = 1; |
| ms->iterations = 0; |
| ms->max_residual = 0.0; |
| return 0; |
| } |
|
|
| ms->converged = 0; |
| for (int iter = 0; iter < MOBIUS_BP_MAX_ITER; iter++) { |
| double residual = mobius_bp_iterate(ms); |
| ms->iterations = iter + 1; |
| ms->max_residual = residual; |
|
|
| if (residual < MOBIUS_BP_TOL) { |
| ms->converged = 1; |
| break; |
| } |
| } |
|
|
| mobius_compute_beliefs(ms); |
| if (!ms->converged && ms->max_residual < 1e-8) |
| ms->converged = 1; |
|
|
| return ms->iterations; |
| } |
|
|
| |
| |
| |
|
|
| static inline double mobius_marginal(const MobiusAmplitudeSheet *ms, |
| uint64_t site, uint32_t value) |
| { |
| return ms->sheets[site].marginal[value]; |
| } |
|
|
| |
| |
| |
| |
| |
|
|
| static inline void mobius_amplitude(const MobiusAmplitudeSheet *ms, |
| const uint32_t *indices, |
| double *out_re, double *out_im) |
| { |
| const HPCGraph *g = ms->graph; |
|
|
| |
| for (uint64_t k = 0; k < ms->n_sites; k++) { |
| if (ms->sheets[k].marginal[indices[k]] < 1e-30) { |
| *out_re = 0.0; |
| *out_im = 0.0; |
| return; |
| } |
| } |
|
|
| hpc_amplitude(g, indices, out_re, out_im); |
| ((MobiusAmplitudeSheet *)ms)->amplitude_queries++; |
| } |
|
|
| |
| |
| |
| |
| |
|
|
| static inline HPCSparseVector *mobius_surface_walk(const MobiusAmplitudeSheet *ms, |
| double threshold, |
| uint64_t max_entries) |
| { |
| const HPCGraph *g = ms->graph; |
| HPCSparseVector *sv = hpc_sv_create(g->n_sites, 256); |
| if (!sv) return NULL; |
| sv->threshold = threshold; |
|
|
| ((MobiusAmplitudeSheet *)ms)->surface_walks++; |
|
|
| uint32_t candidates[64][MOBIUS_D]; |
| uint32_t n_cand[64]; |
| uint64_t total_configs = 1; |
|
|
| uint64_t n = g->n_sites; |
| if (n > 64) n = 64; |
|
|
| for (uint64_t k = 0; k < n; k++) { |
| n_cand[k] = 0; |
| for (int v = 0; v < MOBIUS_D; v++) { |
| if (ms->sheets[k].marginal[v] >= threshold * 0.1) { |
| candidates[k][n_cand[k]++] = v; |
| } |
| } |
| if (n_cand[k] == 0) { |
| for (int v = 0; v < MOBIUS_D; v++) |
| candidates[k][n_cand[k]++] = v; |
| } |
| total_configs *= n_cand[k]; |
| } |
|
|
| uint32_t indices[64]; |
| for (uint64_t cfg = 0; cfg < total_configs && sv->count < max_entries; cfg++) { |
| uint64_t tmp = cfg; |
| for (uint64_t k = 0; k < n; k++) { |
| indices[k] = candidates[k][tmp % n_cand[k]]; |
| tmp /= n_cand[k]; |
| } |
|
|
| double re, im; |
| hpc_amplitude(g, indices, &re, &im); |
| double prob = re * re + im * im; |
|
|
| if (prob >= threshold) |
| hpc_sv_add(sv, indices, re, im); |
| } |
|
|
| return sv; |
| } |
|
|
| |
| |
| |
|
|
| static inline void mobius_vesica_decompose(MobiusAmplitudeSheet *ms, uint64_t site) |
| { |
| MobiusSiteSheet *s = &ms->sheets[site]; |
| if (s->vesica_valid) return; |
|
|
| for (int c = 0; c < 3; c++) { |
| s->vesica_re[c] = INV_SQRT2 * (s->dressed_re[c] + s->dressed_re[c + 3]); |
| s->vesica_im[c] = INV_SQRT2 * (s->dressed_im[c] + s->dressed_im[c + 3]); |
| s->wave_re[c] = INV_SQRT2 * (s->dressed_re[c] - s->dressed_re[c + 3]); |
| s->wave_im[c] = INV_SQRT2 * (s->dressed_im[c] - s->dressed_im[c + 3]); |
| } |
| s->vesica_valid = 1; |
| } |
|
|
| |
| |
| |
|
|
| static inline double mobius_interference_witness(const MobiusAmplitudeSheet *ms) |
| { |
| double total = 0.0; |
| for (uint64_t k = 0; k < ms->n_sites; k++) |
| total += ms->sheets[k].coherence; |
| return (ms->n_sites > 0) ? total / ms->n_sites : 0.0; |
| } |
|
|
| |
| |
| |
|
|
| static inline double mobius_bethe_free_energy(MobiusAmplitudeSheet *ms) |
| { |
| const HPCGraph *g = ms->graph; |
| double F = 0.0; |
|
|
| |
| for (uint64_t k = 0; k < g->n_sites; k++) { |
| const MobiusSiteSheet *s = &ms->sheets[k]; |
| int degree = (int)g->adj[k].count; |
| double site_entropy = 0.0; |
|
|
| for (int v = 0; v < MOBIUS_D; v++) { |
| double p = s->marginal[v]; |
| if (p > 1e-30) |
| site_entropy -= p * log(p); |
| } |
|
|
| F += (double)(degree - 1) * site_entropy; |
| } |
|
|
| |
| for (uint64_t eid = 0; eid < g->n_edges; eid++) { |
| const HPCEdge *edge = &g->edges[eid]; |
| uint64_t sa = edge->site_a, sb = edge->site_b; |
| const MobiusSiteSheet *sheet_a = &ms->sheets[sa]; |
| const MobiusSiteSheet *sheet_b = &ms->sheets[sb]; |
|
|
| double edge_entropy = 0.0; |
| double Z_edge = 0.0; |
| double pairwise[MOBIUS_D][MOBIUS_D]; |
|
|
| for (int va = 0; va < MOBIUS_D; va++) { |
| for (int vb = 0; vb < MOBIUS_D; vb++) { |
| double p_ab = sheet_a->marginal[va] * sheet_b->marginal[vb] * |
| mobius_edge_factor(edge, va, vb); |
| pairwise[va][vb] = p_ab; |
| Z_edge += p_ab; |
| } |
| } |
|
|
| if (Z_edge > 1e-30) { |
| for (int va = 0; va < MOBIUS_D; va++) { |
| for (int vb = 0; vb < MOBIUS_D; vb++) { |
| double p = pairwise[va][vb] / Z_edge; |
| if (p > 1e-30) |
| edge_entropy -= p * log(p); |
| } |
| } |
| } |
|
|
| F -= edge_entropy; |
| } |
|
|
| ms->bethe_free_energy = F; |
| return F; |
| } |
|
|
| |
| |
| |
|
|
| static inline void mobius_apply_cz(MobiusAmplitudeSheet *ms, |
| uint64_t site_a, uint64_t site_b) |
| { |
| hpc_cz((HPCGraph *)ms->graph, site_a, site_b); |
|
|
| for (int side = 0; side < 2; side++) { |
| uint64_t site = (side == 0) ? site_a : site_b; |
| MobiusSiteSheet *s = &ms->sheets[site]; |
| const HPCAdjList *adj = &ms->graph->adj[site]; |
|
|
| if (adj->count > s->msg_capacity) { |
| uint64_t new_cap = adj->count * 2; |
| s->msg_in = (MobiusProbMsg *)realloc(s->msg_in, |
| new_cap * sizeof(MobiusProbMsg)); |
| for (uint64_t i = s->msg_capacity; i < new_cap; i++) |
| for (int v = 0; v < MOBIUS_D; v++) |
| s->msg_in[i].p[v] = 1.0; |
| s->msg_capacity = new_cap; |
| } |
|
|
| uint64_t new_idx = adj->count - 1; |
| s->n_messages = adj->count; |
| for (int v = 0; v < MOBIUS_D; v++) |
| s->msg_in[new_idx].p[v] = 1.0; |
| } |
|
|
| ms->converged = 0; |
| mobius_converge(ms); |
| } |
|
|
| |
| |
| |
|
|
| static inline void mobius_apply_local_phase(MobiusAmplitudeSheet *ms, |
| uint64_t site, |
| const double phi_re[6], |
| const double phi_im[6]) |
| { |
| hpc_phase((HPCGraph *)ms->graph, site, phi_re, phi_im); |
| ms->converged = 0; |
| mobius_converge(ms); |
| } |
|
|
| static inline void mobius_apply_dft(MobiusAmplitudeSheet *ms, uint64_t site) |
| { |
| hpc_dft((HPCGraph *)ms->graph, site); |
| ms->converged = 0; |
| mobius_converge(ms); |
| } |
|
|
| |
| |
| |
|
|
| static inline uint32_t mobius_measure(MobiusAmplitudeSheet *ms, |
| uint64_t site, double random_01) |
| { |
| const MobiusSiteSheet *s = &ms->sheets[site]; |
| double cumul = 0.0; |
| uint32_t outcome = MOBIUS_D - 1; |
| for (int v = 0; v < MOBIUS_D; v++) { |
| cumul += s->marginal[v]; |
| if (random_01 <= cumul) { outcome = v; break; } |
| } |
|
|
| hpc_measure((HPCGraph *)ms->graph, site, random_01); |
|
|
| ms->converged = 0; |
| MobiusSiteSheet *collapsed = &ms->sheets[site]; |
| collapsed->n_messages = ms->graph->adj[site].count; |
| for (uint64_t mi = 0; mi < collapsed->n_messages; mi++) |
| for (int v = 0; v < MOBIUS_D; v++) |
| collapsed->msg_in[mi].p[v] = 1.0; |
|
|
| mobius_converge(ms); |
| return outcome; |
| } |
|
|
| |
| |
| |
|
|
| typedef struct { |
| double *probabilities; |
| double *coherences; |
| uint64_t n_sites; |
| double global_coherence; |
| double bethe_F; |
| } MobiusSurface; |
|
|
| static inline MobiusSurface *mobius_snapshot(MobiusAmplitudeSheet *ms) |
| { |
| MobiusSurface *surf = (MobiusSurface *)calloc(1, sizeof(MobiusSurface)); |
| if (!surf) return NULL; |
|
|
| surf->n_sites = ms->n_sites; |
| surf->probabilities = (double *)calloc(ms->n_sites * MOBIUS_D, sizeof(double)); |
| surf->coherences = (double *)calloc(ms->n_sites, sizeof(double)); |
|
|
| for (uint64_t k = 0; k < ms->n_sites; k++) { |
| for (int v = 0; v < MOBIUS_D; v++) |
| surf->probabilities[k * MOBIUS_D + v] = ms->sheets[k].marginal[v]; |
| surf->coherences[k] = ms->sheets[k].coherence; |
| } |
|
|
| surf->global_coherence = mobius_interference_witness(ms); |
| surf->bethe_F = mobius_bethe_free_energy(ms); |
|
|
| return surf; |
| } |
|
|
| static inline void mobius_surface_destroy(MobiusSurface *surf) |
| { |
| if (!surf) return; |
| free(surf->probabilities); |
| free(surf->coherences); |
| free(surf); |
| } |
|
|
| |
| |
| |
|
|
| static inline void mobius_print(const MobiusAmplitudeSheet *ms) |
| { |
| printf("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n"); |
| printf("β MΓΆbius Amplitude Sheet β\n"); |
| printf("β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£\n"); |
| printf("β Sites: %10lu β\n", ms->n_sites); |
| printf("β Converged: %10s β\n", |
| ms->converged ? "YES" : "NO"); |
| printf("β Iterations: %10d β\n", ms->iterations); |
| printf("β Max residual: %10.2e β\n", ms->max_residual); |
| printf("β Msg updates: %10lu β\n", ms->msg_updates); |
| printf("β Amp queries: %10lu β\n", ms->amplitude_queries); |
| printf("β Surface walks: %10lu β\n", ms->surface_walks); |
| printf("β Bethe F: %10.6f β\n", ms->bethe_free_energy); |
| printf("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n"); |
|
|
| uint64_t show = ms->n_sites; |
| if (show > 8) show = 8; |
| for (uint64_t k = 0; k < show; k++) { |
| const MobiusSiteSheet *s = &ms->sheets[k]; |
| printf(" Site %lu: marginals=[", k); |
| for (int v = 0; v < MOBIUS_D; v++) { |
| printf("%.4f", s->marginal[v]); |
| if (v < MOBIUS_D - 1) printf(", "); |
| } |
| printf("] coh=%.4f degree=%lu\n", s->coherence, s->n_messages); |
| } |
| if (ms->n_sites > 8) |
| printf(" ... (%lu more sites)\n", ms->n_sites - 8); |
| } |
|
|
| static inline void mobius_print_dressed(const MobiusAmplitudeSheet *ms, uint64_t site) |
| { |
| const MobiusSiteSheet *s = &ms->sheets[site]; |
| printf(" Site %lu dressed: [", site); |
| for (int v = 0; v < MOBIUS_D; v++) { |
| printf("%.4f%+.4fi", s->dressed_re[v], s->dressed_im[v]); |
| if (v < MOBIUS_D - 1) printf(", "); |
| } |
| printf("]\n"); |
| } |
|
|
| #endif |
|
|