|
| 1 | +# Copyright (c) 2023 - 2025 Eric Sabo |
| 2 | +# All rights reserved. |
| 3 | +# |
| 4 | +# This source code is licensed under the BSD-style license found in the |
| 5 | +# LICENSE file in the root directory of this source tree. |
| 6 | + |
| 7 | +############################# |
| 8 | + # simple cycles |
| 9 | +############################# |
| 10 | + |
| 11 | +""" |
| 12 | +$TYPEDSIGNATURES |
| 13 | +
|
| 14 | +Return a bar graph and dictionary of (length, count) pairs for the unique simple cycles up to |
| 15 | +length `len` of the Tanner graph of `L`. If `len` is `-1`, then all simple cycles will be |
| 16 | +enumerated. An empty figure and dictionary are returned when there are no cycles. |
| 17 | +
|
| 18 | +# Note |
| 19 | +- Simple cycles do not contain the same vertex twice. |
| 20 | +- This function calls `enumerate_simple_cycles(L, len = len)`, which could be expensive if not |
| 21 | + already cached. |
| 22 | +- Run `using Makie` to activate this extension. |
| 23 | +""" |
| 24 | +function CodingTheory.simple_cycle_length_distribution_plot(L::AbstractLDPCCode; len::Int = -1) |
| 25 | + dist = simple_cycle_length_distribution(L, len = len) |
| 26 | + x_data = collect(keys(dist)) |
| 27 | + y_data = collect(values(dist)) |
| 28 | + |
| 29 | + fig = Figure(); |
| 30 | + ax = Axis(fig[1, 1], xlabel = "Cycle Length", ylabel = "Occurrences", |
| 31 | + title = "Simple Cycle Counts", xticks = x_data, yticks = y_data) |
| 32 | + barplot!(ax, x_data, y_data, strokewidth = 1) |
| 33 | + display(fig) |
| 34 | + return fig |
| 35 | +end |
| 36 | + |
| 37 | +""" |
| 38 | +$TYPEDSIGNATURES |
| 39 | +
|
| 40 | +Return bar graph and a dictionary of (node, count) pairs for the unique simple cycles up to length |
| 41 | +`len` of the Tanner graph of `L`. If `len` is `-1`, then all simple cycles will be enumerated. An |
| 42 | +empty figure and dictionary are returned when there are no cycles. |
| 43 | +
|
| 44 | +# Note |
| 45 | +- Simple cycles do not contain the same vertex twice. |
| 46 | +- This function calls `enumerate_simple_cycles(L, len = len)`, which could be expensive if not |
| 47 | + already cached. |
| 48 | +- Run `using Makie` to activate this extension. |
| 49 | +""" |
| 50 | +function CodingTheory.simple_cycle_distribution_by_variable_node_plot(L::AbstractLDPCCode; |
| 51 | + len::Int = -1) |
| 52 | + |
| 53 | + dist = simple_cycle_distribution_by_variable_node(L, len = len) |
| 54 | + collect(keys(dist)) |
| 55 | + collect(values(dist)) |
| 56 | + |
| 57 | + fig = Figure(); |
| 58 | + ax = Axis(fig[1, 1], xlabel = "Variable Node Index", ylabel = "Occurrences", |
| 59 | + title = "Simple Cycles By Variable Node", xticks = x_data, yticks = y_data) |
| 60 | + barplot!(ax, x_data, y_data, strokewidth = 1) |
| 61 | + display(fig) |
| 62 | + return fig |
| 63 | +end |
| 64 | + |
| 65 | +############################# |
| 66 | + # short cycles |
| 67 | +############################# |
| 68 | + |
| 69 | +""" |
| 70 | +$TYPEDSIGNATURES |
| 71 | +
|
| 72 | +Return a bar graph and dictionary of (length, count) pairs for the unique short cycles up to |
| 73 | +length `len` of the Tanner graph of `L`. If `len` is `-1`, then all short cycles will be |
| 74 | +enumerated. An empty figure and dictionary are returned when there are no cycles. |
| 75 | +
|
| 76 | +# Note |
| 77 | +- Short cycles are defined to be those with lengths between ``g`` and ``2g - 2``, |
| 78 | + where ``g`` is the girth. |
| 79 | +- This function calls `enumerate_simple_cycles(L, len = len)`, which could be expensive if not |
| 80 | + already cached. |
| 81 | +- Run `using Makie` to activate this extension. |
| 82 | +""" |
| 83 | +function CodingTheory.short_cycle_length_distribution_plot(L::AbstractLDPCCode; len::Int = -1) |
| 84 | + dist = short_cycle_length_distribution(L, len = len) |
| 85 | + x_data = collect(keys(dist)) |
| 86 | + y_data = collect(values(dist)) |
| 87 | + |
| 88 | + fig = Figure() |
| 89 | + ax = Axis(fig[1, 1], xlabel = "Cycle Length", ylabel = "Occurrences", |
| 90 | + title = "Short Cycle Counts", xticks = x_data, yticks = y_data) |
| 91 | + barplot!(ax, x_data, y_data, strokewidth = 1) |
| 92 | + display(fig) |
| 93 | + return fig |
| 94 | +end |
| 95 | + |
| 96 | +""" |
| 97 | +$TYPEDSIGNATURES |
| 98 | +
|
| 99 | +Return bar graph and a dictionary of (node, count) pairs for the unique short cycles up to length |
| 100 | +`len` of the Tanner graph of `L`. If `len` is `-1`, then all short cycles will be enumerated. An |
| 101 | +empty figure and dictionary are returned when there are no cycles. |
| 102 | +
|
| 103 | +# Note |
| 104 | +- Short cycles are defined to be those with lengths between ``g`` and ``2g - 2``, |
| 105 | + where ``g`` is the girth. |
| 106 | +- This function calls `enumerate_simple_cycles(L, len = len)`, which could be expensive if not |
| 107 | + already cached. |
| 108 | +- Run `using Makie` to activate this extension. |
| 109 | +""" |
| 110 | +function CodingTheory.short_cycle_distribution_by_variable_node_plot(L::AbstractLDPCCode; |
| 111 | + len::Int = -1) |
| 112 | + |
| 113 | + dist = short_cycle_distribution_by_variable_node(L, len = len) |
| 114 | + x_data = collect(keys(dist)) |
| 115 | + y_data = collect(values(dist)) |
| 116 | + |
| 117 | + fig = Figure(); |
| 118 | + ax = Axis(fig[1, 1], xlabel = "Variable Node Index", ylabel = "Occurrences", |
| 119 | + title = "Short Cycles By Variable Node", xticks = x_data, yticks = y_data) |
| 120 | + barplot!(ax, x_data, y_data, strokewidth = 1) |
| 121 | + display(fig) |
| 122 | + return fig |
| 123 | +end |
| 124 | + |
| 125 | +############################# |
| 126 | + # lollipops |
| 127 | +############################# |
| 128 | + |
| 129 | + |
| 130 | +# one for short cycles which cuts off stems at the correct lengths |
| 131 | +# one for doing all of them |
| 132 | + |
| 133 | + |
| 134 | + |
| 135 | + |
| 136 | + |
| 137 | +############################# |
| 138 | + # ACE |
| 139 | +############################# |
| 140 | + |
| 141 | +""" |
| 142 | +$TYPEDSIGNATURES |
| 143 | +
|
| 144 | +Return an interactive figure and data for the ACE spectrum of the Tanner graph of `C`. |
| 145 | +
|
| 146 | +# Note |
| 147 | +- Run `using Makie` to activate this extension. |
| 148 | +""" |
| 149 | +function CodingTheory.ACE_spectrum_plot(C::AbstractLDPCCode) |
| 150 | + vs_ACEs, _ = ACE_distribution(C, collect(1:C.n)) |
| 151 | + grth = girth(C) |
| 152 | + # TODO: remove WGLMakie as a default use and only use for interactive plots |
| 153 | + fig = Figure(); |
| 154 | + ax = Axis(fig[1, 1], xlabel = "ACE", ylabel = "Occurrences", title = "ACE Spectrum") |
| 155 | + sg = SliderGrid(fig[2, 1], (label = "Cycle Length", range = grth:2:2 * grth - 2, |
| 156 | + startvalue = 4)) |
| 157 | + |
| 158 | + x_max = maximum(reduce(vcat, vs_ACEs)) |
| 159 | + y_max = 0 |
| 160 | + counts = ACE_spectrum(C) |
| 161 | + X_data = Observable(Vector{Int}()) |
| 162 | + Y_data = Observable(Vector{Int}()) |
| 163 | + barplot!(ax, X_data, Y_data, strokewidth = 1, xticks = X_data, yticks = Y_data) |
| 164 | + for (k, l) in enumerate(grth:2:2 * grth - 2) |
| 165 | + |
| 166 | + ys = collect(values(counts[k])) |
| 167 | + y_max = maximum([y_max; ys]) |
| 168 | + |
| 169 | + on(sg.sliders[1].value) do val |
| 170 | + if to_value(val) == l |
| 171 | + X_data.val = collect(keys(counts[k])) |
| 172 | + Y_data.val = ys |
| 173 | + notify(X_data) |
| 174 | + notify(Y_data) |
| 175 | + end |
| 176 | + end |
| 177 | + end |
| 178 | + |
| 179 | + GLMakie.limits!(0, x_max + 1, 0, y_max + 2) |
| 180 | + display(fig) |
| 181 | + return fig, counts |
| 182 | +end |
0 commit comments