簡體   English   中英

在ASCII中壓縮稀疏圖的最有效方法?

[英]Most efficient way of compressing sparse graph in ASCII?

我正在開發處理稀疏矩陣的軟件。 它們不是很大(從15x15到〜300x300之間的任何地方)。 我希望能夠以短字符串形式存儲矩陣的表示形式,以便將其作為值存儲在CSV文件中(以及許多其他東西)。

到目前為止,我已經嘗試將矩陣視為二進制字符串,然后轉換為base62

import numpy as np
import networkx as nx

def graphToHash(a,numnodes):
  def baseN(num,b,numerals="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"):
      return ((num == 0) and numerals[0]) or (baseN(num // b, b, numerals).lstrip(numerals[0]) + numerals[num % b])
  return str(numnodes) + '!' + baseN(int(''.join([str(i) for i in flatten_list(a)]),2), 62)

def flatten_list(l):
    l1=[item for sublist in l if isinstance(sublist,list) or isinstance(sublist,np.ndarray) for item in sublist]
    l=l1+[item for item in l if not isinstance(item,list) and not isinstance(item,np.ndarray)]
    return l

# example
import sys
sys.setrecursionlimit(10000)
a=np.array(nx.to_numpy_matrix(nx.connected_watts_strogatz_graph(160,8,.3,1000))).astype(int)
hash=graphToHash(a,160)
len(hash) # ~4300 characters

這適用於小型圖(30個節點約為150個字符)。 但是,較大的圖有點笨拙(160個節點約為4300個節點,需要我增加遞歸限制)。

因為該圖是二進制且稀疏的,所以我知道我可以做得更好。 理想情況下,我想繼續使用{0-9,az,AZ}的字符串,因為我知道這些不會在CSV文件中造成任何問題。

壓縮二進制稀疏矩陣的最有效方法是什么?

經過長時間的討論后,我記得這是一個二進制數組... derp運行長度編碼:

def brle(decoded): #binary run length encoding
    run = 0
    encoded = []
    for i in decoded:
        if i:
            encoded.append(run)
            run = 0
        else:
            run += 1
    return encoded

def brld(encoded): #binary run length decoding
    decoded = np.zeros(sum(encoded)+len(encoded)+1) #random trickery to get original length of flat list
    pos = 0
    for run in encoded:
        pos += run
        decoded[pos] = 1
        pos += 1
    return decoded

沒有任何字母數字編碼...

a=np.array(nx.to_numpy_matrix(nx.connected_watts_strogatz_graph(160,4,.3,1000))).astype(int)
b = flatten_list(a)
encoded = brle(b)

len(';'.join([str(x) for x in encoded])) # ==1706 chars

c = brld(encoded)
assert(all(b==c)) # passes

使用utf-8編碼:

s = ''.join(unichr(x).encode('utf-8') for x in encoded) #711 bytes in memory
assert(encoded == [ord(x) for x in s.decode('utf-8')]) # passes

如何使用sparse6格式? 它使用可打印的ASCII字符。 http://users.cecs.anu.edu.au/~bdm/data/formats.txt

import networkx as nx
G = nx.connected_watts_strogatz_graph(160,4,.3,1000)
s = nx.generate_sparse6(G)
print(len(s))
print(s)

505
>>sparse6<<:~?A__O??K@?SA?[B__D_kE?{F@CH`KI@[J`_L`gM`{NACOaGQ`?QA[R_oIAcTAsUA{VBCWBKXBSHBOZbW[ac\BsSBo^cO_CKacOb_?bCcccgedGfd?hdSiD[jDcldsmdwo_GTE?peGqe[rEcsEktb_^E{vcGwfGyfg{d_{FkAFg}_ObFs~gKgFH@GS\DhAG\BglDGtEG{AG|GhSmHPJhXKhkuHlNiO?CPOIKMILQI\RIdSIlTItUI|VJDMJ@XjHYbwjJPZcxZ_WPc`\Js`FX^_`__`CKL`k\bKc\IXcKldKsbDpfk|WLLhdPeLPjl[nHHllhmf`fLpnl{lMLCMLqM[?Eprm`tmtuM|vNDwNLxNTyN\rN[mKH{i@|n{~LP~OCeDI?oUA_YBOeBOcMOiEosjOyGpAHghZPUIh@sNYKeIKhqMpiNcwzPyO`QOQMS??~QQR`iRql{QsXQqVpqVjhmREXRSyR\NNqZRc?@a[Rk@Jq]

由於期望該圖是稀疏的,因此我將對它的基於鄰接列表的表示進行編碼。 這樣的事情(請注意,我重用了您的baseN()版本,但是我將其替換為迭代版本):

#!/usr/bin/env python3

def baseN(num,b,numerals="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"):
      return ((num == 0) and numerals[0]) or (baseN(num // b, b, numerals).lstrip(numerals[0]) + numerals[num % b])

def encode_graph(g):
    # the leading 'a' is needed to protect the leading zero (if any)
    s = 'a' + 'a'.join(['a'.join(map(str,x)) for x in g])
    n = int(s, 11)
    return baseN(n, 62)

print(encode_graph([(0,1), (1,5), (1,23), (5,23)])) # outputs 64wc3BssnTd

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM