import struct
import sys
import numpy as np
import scipy.sparse as sp
from scipy.sparse.linalg import svds
def read_graph(path):
with open(path, "rb") as f:
(n, nnz) = struct.unpack("<QQ", f.read(16))
rec = np.frombuffer(f.read(nnz * 16), dtype=np.dtype([("i", "<u4"), ("j", "<u4"), ("w", "<f8")]))
phi = np.frombuffer(f.read(8 * n), dtype="<f8").astype(np.float64)
return n, rec["i"].astype(np.int64), rec["j"].astype(np.int64), rec["w"].astype(np.float64), phi
def main():
gpath, spath = sys.argv[1], sys.argv[2]
n, ii, jj, ww, phi = read_graph(gpath)
a = sp.csr_matrix((ww, (ii, jj)), shape=(n, n))
ds = np.sqrt(phi)
m = sp.diags(ds) @ (a + 0.5 * (a @ a)) @ sp.diags(ds)
k = min(64, n - 2)
u, s, vt = svds(m.astype(np.float64), k=k, which="LM", maxiter=2000, tol=1e-10)
order = np.argsort(-s)
s = s[order]
u = u[:, order]
v = vt.T[:, order]
print(f"mirror svd: sigma[:8]={np.array2string(s[:8], precision=4)}", file=sys.stderr)
print(f"mirror svd: sigma[8:16]={np.array2string(s[8:16], precision=4)}", file=sys.stderr)
with open(spath, "wb") as f:
f.write(struct.pack("<Q", k))
f.write(s.astype("<f8").tobytes())
f.write(np.ascontiguousarray(u, dtype="<f8").tobytes())
f.write(np.ascontiguousarray(v, dtype="<f8").tobytes())
if __name__ == "__main__":
main()