2017-12-04 35 views
0

と値を行に単位変位(シフト)を使用して、これらの5つの2x2 2D配列を作成します。分割行からアレイを作成2Dアレイは、私はこのように2次元アレイを分割する単一変位

np.array([[1,2],[3,4]]) 
np.array([[4,5],[6,7]]) 
np.array([[7,8],[9,10]]) 
np.array([[10,11],[12,13]]) 
np.array([[13,14],[15,16]]) 

一般NXN 2D配列(正方形配列)から、可能な限り多くのMXM形状のY 2次元配列を作成します。

もっと正確に言えば、出力配列を作成するには、必ずしも行のすべての値から出力配列を作成する必要はありません。

例:私は2次元の2x2アレイにこの配列を分割する場合は、2D 8×8アレイから

は、1から64までの値で、8×8のアレイからの最初の行は、1から8までの行であると最初の出力2D 2x2配列はnp.array([[1,2]、[3,4]])になり、2番目の出力2D 2x2配列はnp.array([[4,5]、[6] 7]])...最後の出力2D配列まで、np.array([[61,62]、[63,64]])まで続きます。各2D 2x2アレイが行のすべての値で満たされていないことを確認します(正解)。そしてそれは、前の配列から次の配列への単一の変位(シフト)が存在する。

これを行うナンシーメソッドがありますか?

ここでMSeifertが答えました(How to split an 2D array, creating arrays from "row to row" values)。この質問のほぼ95%を解決する質問ですが、単位変位(シフト)部分を除きます。

したがって、4×4の2次元アレイの例から:

np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]) 

代わりの(単一シフト/変位なし)これら四つの2×2の二次元アレイの作成:(

np.array([[1,2],[3,4]]) 
np.array([[5,6],[7,8]]) 
np.array([[9,10],[11,12]]) 
np.array([[13,14],[15,16]]) 

は、これらの5つの2x2の2次元アレイを作成しますユニタリシフト/変位あり):

np.array([[1,2],[3,4]]) 
np.array([[4,5],[6,7]]) 
np.array([[7,8],[9,10]]) 
np.array([[10,11],[12,13]]) 
np.array([[13,14],[15,16]]) 

そしてもちろん、それは一般的なca Y MXM正方形の2D配列を作成するために正方形のNXN 2D配列が与えられています。

例:60x60正方形の2次元配列から、Y MXM正方形の2次元配列(たとえば10x10)を作成します。

プラス:元の正方形の2D配列(この例では4x4の2D配列)のポイント数と、ミニ四角形の2次元配列(2x2の2次元配列)のポイント数をどのように関連付けるかを知る必要があります。例)。この場合、16ポイント(4×4 2D配列)が与えられた場合、5×2×2D配列(それぞれ4ポイント)を作成することが可能です。

+1

この問題に述べたように不良設定です。任意の形状の入力配列に対してMxMに一般化することはできません。どのように元のサンプル配列から3x3配列を作成しますか?この例は、N = M^2であるためにのみ有効です。[[1 2 3] [4 5 6] [7 8 9]]、[[9 10 11] [12 13 14] [15 16 ??たとえば、10x10ブロックの60x60配列動作しません。 –

+0

@AlexanderReynolds確かに私は一般化することができません、私はちょうど私が働くことができるスケール(ミニ配列)で元の2D配列が与えられている。私の例では、4x4の2D配列があれば、2x2の2D配列を生成することができます。 – Marco

+0

@AlexanderReynolds ので... 2つの質問: 1)私は、アルゴリズムは、ミニ配列を生成してください、私はミニ2D配列を生成することができスケール(およびそのための2D配列を指定して、(数学的ルール)、、、知ることができますどのように引用された変位/シフトを伴う)? 2)上記の問題に関して、数学的ルールがあることを考慮すると、可能なスケール(ミニアレイの生成)を考えれば、このスケールで生成できるミニアレイの数はどれくらいですか? – Marco

答えて

3

サブアレイが正確に収まる条件は(M+1)*(M-1)(N+1)*(N-1)で割る条件です。サブアレイの数はこれらの数値の商です。これらの数値はM*M-1N*N-1に等しいことに注意してください。この形式では、規則は非正方行列にも適用されます。

M  N  M*M-1 N*N-1 Y 
----------------------------- 
3  5  8  24  3 
3  7  8  48  6 
5  7  24  48  2 
4  11  15  120 8 

実装:これは、元の配列に重複ビューを返すことに注意してください。それらを変更する場合は、コピーを作成することができます。また、この実装はフィットする数のサブクラスに適合し、大きな行列の残りの要素はすべて削除されます。

更新:私は、与えられたNと計算される2つの関数を追加しました。その逆も同様です。

出力:

# Testing predictions ... 
# ok 

# M = 105 
# solutions: [105, 1273, 1377, 4135, 4239, 5407, 5511, 5513] 
# this pattern repeats at offsets 5512, 11024, 16536, ... 

# N = 1000001 
# solutions: [2, 3, 4, 5, 7, 9, 11, 31, 49, 1000001] 

# example N, M = (5, 3) 
# [[[ 0 1 2] 
# [ 3 4 5] 
# [ 6 7 8]] 

# [[ 8 9 10] 
# [11 12 13] 
# [14 15 16]] 

# [[16 17 18] 
# [19 20 21] 
# [22 23 24]]] 

コード:

import numpy as np 
import sympy 
import itertools as it 
import functools as ft 
import operator as op 

def get_subsquares(SqNN, M0, M1=None): 
    M1 = M0 if M1 is None else M1 
    N0, N1 = SqNN.shape 
    K = (N0*N1-1) // (M0*M1-1) 
    SqNN = SqNN.ravel() 
    s, = SqNN.strides 
    return np.lib.stride_tricks.as_strided(SqNN, (K, M0, M1), 
              (s*(M0*M1-1), s*M1, s)) 


def get_M_for_N(N): 
    """Given N return all possible M 
    """ 
    assert N >= 2 
    f = 1 + (N & 1) 
    factors = sympy.factorint((N+1)//f) 
    factors.update(sympy.factorint((N-1)//f)) 
    if f == 2: 
     factors[2] += 2 
    factors = [ft.reduce(op.mul, fs) for fs in it.product(
     *([a**k for k in range(n+1)] for a, n in factors.items()))] 
    return [fs + 1 for fs in sorted(set(factors) & set(fs - 2 for fs in factors)) if (N*N-1) % (fs * (fs+2)) == 0] 

def get_N_for_M(M): 
    """Given M return all possible N in the form period, smallest 

    smallest is a list of all solutions between M and M*M if M is even 
    and between M and (M*M+1)/2 if M is odd, all other solutions can be 
    obtained by adding multiples of period 
    """ 
    assert M >= 2 
    f = 1 + (M & 1) 
    factors = sympy.factorint((M+1)//f) 
    factors.update(sympy.factorint((M-1)//f)) 
    factors = [k**v for k, v in factors.items()] 
    rep = (M+1)*(M-1) // f 
    f0 = [ft.reduce(op.mul, fs) for fs in it.product(*zip(it.repeat(1), factors))] 
    f1 = [rep // (f*a) for a in f0] 
    inv = [f if b==1 else f*b + 2 if a==1 else 2 * sympy.mod_inverse(a, b) 
      for a, b in zip(f1, f0)] 
    if f==1: 
     inv[1:-1] = [a%b for a, b in zip(inv[1:-1], f0[1:-1])] 
    return rep, sorted(a*b - 1 for a, b in zip(f1, inv)) 

def test_predict(N): 
    def brute_force(a, b): 
     return [i for i in range(a, b) if (i*i-1) % (a*a-1) == 0] 
    for x in range(2, N+1): 
     period, pred = get_N_for_M(x) 
     assert brute_force(x, period*4+2) \ 
      == [a + b for b in range(0, 4*period, period) for a in pred] 
    def brute_force(b): 
     return [i for i in range(2, b+1) if (b*b-1) % (i*i-1) == 0] 
    for x in range(2, N+1): 
     assert brute_force(x) == get_M_for_N(x) 
    print('ok') 

# test 
print("Testing predictions ...") 
test_predict(200) 
print() 
# examples 
M = 105 
period, pred = get_N_for_M(M) 
print(f"M = {M}") 
print(f"solutions: {pred}") 
print(f"this pattern repeats at offsets {period}, {2*period}, {3*period}, ...") 
print() 
N = 1000001 
pred = get_M_for_N(N) 
print(f"N = {N}") 
print(f"solutions: {pred}") 
print() 
N, M = 5, 3 
SqNN = np.arange(N*N).reshape(N, N) 
print(f"example N, M = ({N}, {M})") 
print(get_subsquares(SqNN, M)) 
+2

ストライドは素晴らしいソリューションです!それについても考えなかった。私は私の答えを削除します---これははるかに良いです。 –

+0

@Paul、ありがとう。完璧な数学的ルールとアルゴリズム。アルゴリズムは複雑ですが、私の意見では、これらのソリューションだけを考えることはできませんでした。 – Marco

+0

@AlexanderReynolds、あなたの努力に感謝します。 – Marco

関連する問題