pyGD.dynamics module

Continuous phase dynamics on graphs.

This module ports the MATLAB Kuramoto and KuramotoCG classes to Python. Both consume a networkx.Graph directly; the adjacency matrix is pulled once as a SciPy sparse (CSR) matrix and the hot loop is the sparse mat-vec A @ exp(i*theta), mirroring the MATLAB G.adjacency multiply.

Kuramoto

The base environment, Eq. (1) of Sowinski, Frank & Ghoshal, PRR 6, 043188 (2024): dtheta_i/dt = omega_i + sigma * sum_j A_ij sin(theta_j - theta_i).

KuramotoCG

The coarse-grained stochastic variant, Eq. (7): the intervening agent is integrated out (Appendix B) into a degree-modulated frequency shift plus a Wiener fluctuation. Kept as an independent class, mirroring the MATLAB.

class pyGD.dynamics.Kuramoto(sigma, G, omegas, r0=0.0, dt=0.0625, rng=None)[source]

Bases: object

Kuramoto oscillators on the nodes of a graph.

Ported from Kuramoto.m. Each node carries a phase theta_i; the global order parameter is Z = mean(exp(i*theta)) with magnitude r and mean phase phi. The per-node complex local field is krexp = (A @ exp(i*theta)) * conj(exp(i*theta)).

Parameters:
  • sigma (float) – Coupling strength.

  • G (networkx.Graph) – Interaction graph. Adjacency is extracted once as sparse CSR.

  • omegas (array_like) – Natural frequencies, one per node (node order = list(G.nodes())).

  • r0 (float, optional) – Initial spread of phases; theta = (2*U - 1)*pi*(1 - r0) with U ~ Uniform[0,1). r0 = 0 gives fully random phases (default).

  • dt (float, optional) – Timestep. Default 0.0625 (= 1/16), matching the MATLAB.

  • rng (numpy.random.Generator, optional) – Random source; defaults to numpy.random.default_rng().

thetas

Current phases, wrapped to (-pi, pi].

Type:

ndarray

Z, r, phi

Global order parameter, its magnitude, and its angle.

Type:

complex, float, float

krexp

Complex per-node local field (updated by compute_mean_field()).

Type:

ndarray

word

Sign bits of imag(krexp) via Heaviside (0.5 at exactly 0), matching the MATLAB compute_word.

Type:

ndarray

Examples

>>> import networkx as nx, numpy as np
>>> G = nx.erdos_renyi_graph(50, 0.1, seed=0)
>>> rng = np.random.default_rng(0)
>>> env = Kuramoto(0.5, G, rng.standard_normal(G.number_of_nodes()), rng=rng)
>>> env.run(10)
>>> bool(0.0 <= env.r <= 1.0)
True
compute_mean_field()[source]

Recompute the complex per-node local field krexp.

compute_word()[source]

Recompute the sign-bit word from imag(krexp).

update_order_parameter()[source]

Refresh Z, r, phi and recompute mean field + word.

evolve()[source]

Advance one Euler step. Mirrors the MATLAB evolve exactly.

run(n_steps, record=False)[source]

Advance n_steps steps.

Parameters:
  • n_steps (int) – Number of steps.

  • record (bool, optional) – If True, call update_order_parameter() each step and return the array of r values. Default False (faster; no measurement).

Returns:

The r history if record else None.

Return type:

ndarray or None

neighbors(i)[source]

Neighbor node indices of i from the CSR adjacency.

plot_phases(ax=None, pos=None, cmap='twilight')[source]

Draw the graph with nodes colored by phase (viz helper).

Requires matplotlib. Uses a spring layout unless pos is given.

class pyGD.dynamics.KuramotoCG(sigma, G, omegas, ab, dt=0.0625, rng=None)[source]

Bases: object

Coarse-grained (stochastic) Kuramoto dynamics, Eq. (7).

Ported from KuramotoCG.m. The intervening agent is integrated out into (i) a degree-modulated shift of the natural frequencies and (ii) a Wiener fluctuation whose amplitude scales with node degree. See Appendix B of the paper; the two agent parameters enter only through their product ab (= alpha*beta). This is the continuum limit of a Kuramoto environment driven by a Yokai agent, but is kept as an independent class.

Parameters:
  • sigma (float) – Coupling strength.

  • G (networkx.Graph) – Interaction graph.

  • omegas (array_like) – Base natural frequencies, one per node.

  • ab (float) – The product alpha*beta (kick strength times hop speed).

  • dt (float, optional) – Timestep. Default 0.0625.

  • rng (numpy.random.Generator, optional) – Random source; defaults to numpy.random.default_rng().

thetas, Z, r, phi, krexp, word

As in Kuramoto.

fluc

Per-node fluctuation amplitude sqrt(dt * ab * deg/mean(deg)).

Type:

ndarray

compute_mean_field()[source]

Recompute the complex per-node local field krexp.

compute_word()[source]

Recompute the sign-bit word from imag(krexp).

update_order_parameter()[source]

Refresh Z, r, phi and recompute mean field + word.

evolve()[source]

Advance one Euler-Maruyama step. Mirrors the MATLAB evolve.

run(n_steps, record=False)[source]

Advance n_steps steps. See Kuramoto.run().