Ваши проблемы не имеют ничего общего с точностью или нет pinv
.
Если вы заметите, что ваши матрицы имеют недостаточный ранг, m1
имеет ранг 4 или менее, m2
ранг 3или менее.Следовательно, ваша система m1@x = m3
крайне недоопределена, и восстановить невозможно m2
.
Даже если мы добавим все, что знаем, о структуре m2
, то есть первых двух столбцах 3 и2, остальные 500, считая вверх, есть комбинаторно большое количество решений.
Сценарий ниже находит их все, если есть достаточно времени.На практике я не смотрел дальше матриц 32х32, которые в приведенном ниже прогоне дали 15093381006 различных действительных реконструкций m2'
, которые удовлетворяют m1@m2' = m3
, и структурных ограничений, которые я только что упомянул.
import numpy as np
import itertools
def make(n, offset=500):
offset -= 2
res1 = np.add.outer(np.arange(n), np.arange(offset, offset+n))
res1[:2] = np.random.randint(2, 4, (2, n))
res2 = np.add.outer(np.zeros(n, int), np.arange(offset, offset+n))
res2[:, :2] = np.random.randint(2, 4, (n, 2))
return res1, res2
def subsets(L, n, mn, mx, prepend=[]):
if n == 0:
if mx >= mn:
yield prepend
elif n == 1:
for l in L[L.searchsorted(mn):L.searchsorted(mx, 'right')]:
yield prepend + [l]
else:
ps = L.cumsum()
ps[n:] -= ps[:-n]
ps = ps[n-1:]
for i in range(L.searchsorted(mn - np.sum(L[len(L)-n+1:])),
ps.searchsorted(mx, 'right')):
yield from subsets(L[i+1:], n-1, mn - L[i], mx - L[i],
prepend = prepend + [L[i]])
def solve(m1, m3, ci=0, offset=500):
n, n = m1.shape
col = m3.T[ci]
n3s = col[3] - col[2] - 2 * n
six = col[2] - offset * (col[3] - col[2]) - n * (n-1)
idx = np.lexsort(m1[:2])
m1s = m1[:2, idx]
sm = m1s[1].searchsorted(2.5)
sl = m1s[0, :sm].searchsorted(2.5)
sr = sm + m1s[0, sm:].searchsorted(2.5)
n30 = n - sl - sr + sm
n31 = n - sm
n330 = col[0] - 4*n - 2*n3s - 2*n30
n331 = col[1] - 4*n - 2*n3s - 2*n31
for n333 in range(max(0, n330 - sm + sl, n331 - sr + sm),
min(n - sr, n330, n331) + 1):
n332 = n330 - n333
n323 = n331 - n333
n322 = n3s - n332 - n323 - n333
mx333 = six - idx[sl:sl+n332].sum() - idx[sm:sm+n323].sum() \
- idx[:n322].sum()
mn333 = six - idx[sm-n332:sm].sum() - idx[sr-n323:sr].sum() \
- idx[sl-n322:sl].sum()
for L333 in subsets(idx[sr:], n333, mn333, mx333):
mx332 = six - np.sum(L333) - idx[sm:sm+n323].sum() \
- idx[:n322].sum()
mn332 = six - np.sum(L333) - idx[sr-n323:sr].sum() \
- idx[sl-n322:sl].sum()
for L332 in subsets(idx[sl:sm], n332, mn332, mx332,
prepend=L333):
mx323 = six - np.sum(L332) - idx[:n322].sum()
mn323 = six - np.sum(L332) - idx[sl-n322:sl].sum()
for L323 in subsets(idx[sm:sr], n323, mn323, mx323,
prepend=L332):
ex322 = six - np.sum(L323)
yield from subsets(idx[:sl], n322, ex322, ex322,
prepend=L323)
def recon(m1, m3, ci=0, offset=500):
n, n = m1.shape
nsol = nfp = 0
REC = []
for i3s in solve(m1, m3, ci, offset):
rec = np.full(n, 2)
rec[i3s] = 3
if not np.all(m3.T[ci] == m1@rec):
print('!', rec, m3.T[ci], m1@rec)
nfp += 1
else:
nsol += 1
REC.append(rec)
print('col', ci, ':', nsol, 'solutions,', nfp, 'false positives')
return np.array(REC)
def full_recon(m1, m3, offset=500, subsample=10):
n, n = m1.shape
col0, col1 = (recon(m1, m3, i, offset) for i in (0, 1))
yield col0.shape[0], col1.shape[0]
if not subsample is None:
col0, col1 = (col[np.random.choice(col.shape[0], subsample)]
if col.shape[0] > subsample else col
for col in (col0, col1))
print('col 0', col0)
print('col 1', col1)
for c0, c1 in itertools.product(col0, col1):
out = np.add.outer(np.zeros(n, int), np.arange(offset-2, offset+n-2))
out[:, :2] = np.c_[c0, c1]
yield out
def check(m1, m3, offset=500, subsample=10):
for cnt, m2recon in enumerate(full_recon(m1, m3, offset, subsample)):
if cnt == 0:
tot0, tot1 = m2recon
continue
assert np.all(m3 == m1@m2recon)
print(cnt, 'solutions verified out of', tot0, 'x', tot1, '=', tot0 * tot1)
Пример прогона:
>>> m1, m2 = make(32)
>>> check(m1, m1@m2)
col 0 : 133342 solutions, 0 false positives
col 1 : 113193 solutions, 0 false positives
col 0 [[2 2 3 2 2 2 3 2 3 3 3 3 3 2 3 3 2 2 2 2 2 3 3 3 2 2 2 2 2 2 2 2]
[2 2 3 2 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 3 3 3 2 2 2 3 2 3 2 2 2 2]
[2 3 3 2 3 3 2 2 2 3 2 3 3 2 2 2 2 3 3 3 2 2 2 2 3 2 2 2 2 2 2 3]
[2 2 3 3 2 2 3 3 3 2 2 3 2 3 3 3 2 2 2 2 2 2 2 3 2 3 3 2 2 2 2 2]
[2 3 3 3 2 3 3 2 2 2 2 3 2 2 3 3 2 2 3 2 2 3 2 2 2 2 2 2 3 3 2 2]
[3 2 2 2 3 2 3 3 3 2 3 2 2 2 2 3 3 3 2 2 2 2 3 3 2 3 2 2 2 2 2 2]
[2 2 2 3 3 3 2 2 3 3 3 3 3 2 2 2 2 3 2 2 2 3 2 2 2 3 2 2 3 2 2 2]
[2 2 2 3 3 2 3 3 3 2 3 2 2 3 3 3 2 3 2 2 2 2 2 2 2 2 2 3 2 3 2 2]
[3 2 3 3 2 2 3 2 2 3 2 3 3 2 2 2 3 2 3 2 2 2 2 3 2 3 2 2 3 2 2 2]
[3 2 2 3 3 2 3 3 2 2 2 3 2 3 2 2 3 2 3 3 2 2 2 2 2 3 2 2 2 2 2 3]]
col 1 [[2 2 2 2 3 3 3 3 3 3 3 3 2 2 3 2 2 2 3 3 2 3 2 2 2 3 2 3 2 2 2 3]
[2 3 3 2 3 3 2 2 2 3 3 3 2 2 3 3 2 3 2 3 2 2 3 2 2 2 2 3 3 2 2 3]
[3 2 3 2 2 3 3 2 2 3 3 3 2 2 3 2 3 2 3 2 3 2 3 3 2 2 2 2 2 3 3 2]
[2 2 3 2 3 3 3 2 3 3 2 3 2 3 2 3 2 3 2 2 3 2 3 2 2 3 2 3 2 2 2 3]
[3 3 2 2 2 2 3 2 3 3 3 3 2 3 3 2 2 3 3 2 2 2 2 2 3 2 2 3 3 3 2 2]
[3 3 2 3 2 2 2 3 3 3 2 2 2 3 2 2 2 3 3 3 3 2 3 3 2 2 2 3 3 2 2 2]
[2 3 2 3 2 2 3 3 2 3 3 3 2 3 2 2 3 3 2 3 2 2 3 2 3 2 2 3 2 2 3 2]
[2 3 2 3 2 3 3 3 3 3 3 2 2 2 2 2 3 2 3 2 2 2 3 2 2 3 3 2 3 2 2 3]
[3 2 3 2 2 3 3 3 2 2 3 3 2 2 3 3 2 3 2 2 3 2 2 3 2 2 3 2 3 2 2 3]
[3 2 3 3 2 3 2 2 2 3 3 3 2 3 3 2 2 2 3 2 3 2 2 3 2 2 3 2 2 2 3 3]]
100 solutions verified out of 133342 x 113193 = 15093381006