ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 주문을 변경하지 않고 제품의 최소 합계 찾기
    카테고리 없음 2020. 8. 13. 21:13

    질문

    길이가 다른 두 개의 배열이 있습니다.

    A = np.array([7,6,5,4,3,2,1])
    B = np.array([37.97, 34.45, 32.41, 32.17, 35.48, 35.91, 33.81, 32.23, 33.46,
           35.35, 33.03, 37.36, 32.18, 29.29, 30.23, 30.94, 34.26, 31.74,
           29.24, 25.93, 29.26, 33.64, 33.28])

    A의 내적이 가장 작도록 B에서 7 개의 숫자를 선택해야합니다. 또는 min (7x1 6x2 5x3 ... 2x6 x7) . 두 배열의 순서를 변경해서는 안됩니다. 예를 들어 x1 = 32.41 (색인 2)인 경우 x2 는 이전 색인이 아니어야합니다.

    A와 B의 길이는 실제로 예제보다 길기 때문에 무차별 대입 대신 효율적인 알고리즘을 찾고 있습니다.

    편집 : 순서를 변경하지 않음으로써 인덱스 2에서 요소를 선택하면 다음 항목은 인덱스 5 또는 10이 될 수 있지만 인덱스 0 또는 1이 아닐 수 있습니다. 인덱스 2,3,4와 같이 연속적 일 필요가 없습니다. 5 ....

    답변 업데이트 : 그래서 이것은 @templatetypedef 및 @Damien 답변을 기반으로 지금까지 한 것입니다.

    def min_dot_product(A,B,m,n):
        P = np.zeros((n,m))
        A_ = np.zeros((n,m))
        B_ = np.zeros((n,m))
        #P[0,0] = 0 
        P[1,1] = A[1]*B[1]
        S[1,1] = 1
        for k in range(2,m):
            P[1,k] = np.inf
        for i in range(2,n):
            P[i,0] = 0
            for k in range(1,m):
                P[i,k] = min (P[i-1,k], P[i-1,k-1] + B[i] * A[k])    
                if (P[i-1,k] > P[i-1,k-1] + B[i] * A[k]):
                    A_[i,k] = A[k]
                    B_[i,k] = B[i]
                    S[i,k] = 1
    
        return P,A_,B_,S
    A = np.array([0,7,6,5,4,3,2,1]) # -> Insert 1 dummy value at the first position
    B = np.array([0,37.97, 34.45, 32.41, 32.17, 35.48, 35.91, 33.81, 32.23, 33.46,
           35.35, 33.03, 37.36, 32.18, 29.29, 30.23, 30.94, 34.26, 31.74,
           29.24, 25.93, 29.26, 33.64, 33.28]) # -> Insert 1 dummy value at the first position
    m = len(A)
    n = len(B)
    mat,A_,B_,S = min_dot_product(A,B,m,n)
    Out:
    mat
    array([[  0.  ,   0.  ,   0.  ,   0.  ,   0.  ,   0.  ,   0.  ,   0.  ],
           [  0.  , 241.15,    inf,    inf,    inf,    inf,    inf,    inf],
           [  0.  , 226.87, 435.61,    inf,    inf,    inf,    inf,    inf],
           [  0.  , 225.19, 419.89, 596.46,    inf,    inf,    inf,    inf],
           [  0.  , 225.19, 419.89, 596.46, 738.38,    inf,    inf,    inf],
           [  0.  , 225.19, 419.89, 596.46, 738.38, 846.11,    inf,    inf],
           [  0.  , 225.19, 419.89, 588.94, 731.7 , 839.81, 913.73,    inf],
           [  0.  , 225.19, 418.57, 581.04, 717.86, 828.39, 904.27, 945.96],
           [  0.  , 225.19, 418.57, 581.04, 714.88, 818.24, 895.31, 937.73],
           [  0.  , 225.19, 418.57, 581.04, 714.88, 818.24, 888.94, 930.66],
           [  0.  , 225.19, 418.57, 581.04, 713.16, 813.97, 884.3 , 921.97],
           [  0.  , 225.19, 418.57, 581.04, 713.16, 813.97, 884.3 , 921.66],
           [  0.  , 225.19, 418.27, 579.47, 709.76, 809.7 , 878.33, 916.48],
           [  0.  , 205.03, 400.93, 564.72, 696.63, 797.63, 868.28, 907.62],
           [  0.  , 205.03, 386.41, 552.08, 685.64, 787.32, 858.09, 898.51],
           [  0.  , 205.03, 386.41, 541.11, 675.84, 778.46, 849.2 , 889.03],
           [  0.  , 205.03, 386.41, 541.11, 675.84, 778.46, 846.98, 883.46],
           [  0.  , 205.03, 386.41, 541.11, 668.07, 771.06, 841.94, 878.72],
           [  0.  , 204.68, 380.47, 532.61, 658.07, 755.79, 829.54, 871.18],
           [  0.  , 181.51, 360.26, 510.12, 636.33, 735.86, 807.65, 855.47],
           [  0.  , 181.51, 357.07, 506.56, 627.16, 724.11, 794.38, 836.91],
           [  0.  , 181.51, 357.07, 506.56, 627.16, 724.11, 791.39, 828.02],
           [  0.  , 181.51, 357.07, 506.56, 627.16, 724.11, 790.67, 824.67]])
    
    A_
    array([[0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 7., 6., 0., 0., 0., 0., 0.],
           [0., 7., 6., 5., 0., 0., 0., 0.],
           [0., 0., 0., 0., 4., 0., 0., 0.],
           [0., 0., 0., 0., 0., 3., 0., 0.],
           [0., 0., 0., 5., 4., 3., 2., 0.],
           [0., 0., 6., 5., 4., 3., 2., 1.],
           [0., 0., 0., 0., 4., 3., 2., 1.],
           [0., 0., 0., 0., 0., 0., 2., 1.],
           [0., 0., 0., 0., 4., 3., 2., 1.],
           [0., 0., 0., 0., 0., 0., 0., 1.],
           [0., 0., 6., 5., 4., 3., 2., 1.],
           [0., 7., 6., 5., 4., 3., 2., 1.],
           [0., 0., 6., 5., 4., 3., 2., 1.],
           [0., 0., 0., 5., 4., 3., 2., 1.],
           [0., 0., 0., 0., 0., 0., 2., 1.],
           [0., 0., 0., 0., 4., 3., 2., 1.],
           [0., 7., 6., 5., 4., 3., 2., 1.],
           [0., 7., 6., 5., 4., 3., 2., 1.],
           [0., 0., 6., 5., 4., 3., 2., 1.],
           [0., 0., 0., 0., 0., 0., 2., 1.],
           [0., 0., 0., 0., 0., 0., 2., 1.]])
    
    B_
    array([[ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ],
           [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ],
           [ 0.  , 32.41, 32.41,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ],
           [ 0.  , 32.17, 32.17, 32.17,  0.  ,  0.  ,  0.  ,  0.  ],
           [ 0.  ,  0.  ,  0.  ,  0.  , 35.48,  0.  ,  0.  ,  0.  ],
           [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  , 35.91,  0.  ,  0.  ],
           [ 0.  ,  0.  ,  0.  , 33.81, 33.81, 33.81, 33.81,  0.  ],
           [ 0.  ,  0.  , 32.23, 32.23, 32.23, 32.23, 32.23, 32.23],
           [ 0.  ,  0.  ,  0.  ,  0.  , 33.46, 33.46, 33.46, 33.46],
           [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  , 35.35, 35.35],
           [ 0.  ,  0.  ,  0.  ,  0.  , 33.03, 33.03, 33.03, 33.03],
           [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  , 37.36],
           [ 0.  ,  0.  , 32.18, 32.18, 32.18, 32.18, 32.18, 32.18],
           [ 0.  , 29.29, 29.29, 29.29, 29.29, 29.29, 29.29, 29.29],   x7
           [ 0.  ,  0.  , 30.23, 30.23, 30.23, 30.23, 30.23, 30.23],   x6
           [ 0.  ,  0.  ,  0.  , 30.94, 30.94, 30.94, 30.94, 30.94],
           [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  , 34.26, 34.26],
           [ 0.  ,  0.  ,  0.  ,  0.  , 31.74, 31.74, 31.74, 31.74],
           [ 0.  , 29.24, 29.24, 29.24, 29.24, 29.24, 29.24, 29.24],   x5
           [ 0.  , 25.93, 25.93, 25.93, 25.93, 25.93, 25.93, 25.93],   x4
           [ 0.  ,  0.  , 29.26, 29.26, 29.26, 29.26, 29.26, 29.26],   x3
           [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  , 33.64, 33.64],   x2
           [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  , 33.28, 33.28]])  x1
    

    따라서 min = P [n-1] [m-1] = 824.67 = [7,6,5,4,3,2,1] * [33.28,33.64,29.26,25.93,29.24,30.23,29.29]

    A_ 및 B_를 반대로하려면 :

    def reverse(S,A_,B_):
        n,m = S.shape
        state = m-1
        pos = []
        if state >= 0:
            for i in range(n-1,0,-1):
                if (S[i][state] == 1):
                    state = state - 1
                    pos.append([i,state+1])
    
        new_B = np.zeros(B_.shape)
        new_A = np.zeros(A_.shape)
        for p in pos:
            new_B[p[0],p[1]] = B_[p[0],p[1]]
            new_A[p[0],p[1]] = A_[p[0],p[1]]
    
        return new_B,new_A

    답변1

    여기서 해결하려는 문제의 형식은 다음과 같습니다.

    길이가 m과 n 인 두 시퀀스 A와 B가 숫자 k와 함께 주어지면, A와 가장 낮은 내적을 갖는 길이 m의 B의 하위 시퀀스를 찾습니다.

    원래 문제에서는 m = 7이지만 더 일반적으로 7은 임의의 숫자로 대체 될 수 있다고 생각합니다.

    이 문제에는 멋진 동적 프로그래밍 솔루션이 있습니다. 그 배후의 직감은 다음과 같습니다. m 요소 벡터의 첫 번째 요소로 사용할 배열 B에서 숫자를 선택한다고 가정합니다. 그런 다음 나머지 m-1 요소가 무엇인지 결정해야합니다. 생각해 보면 A의 마지막 m-1 요소와 m-1 요소의 내적이 가능한 한 작도록 선택하는 것이 좋습니다. 그러면 질문은 "첫 번째 항목이 무엇인지 어떻게 결정합니까"와 "후속 항목을 어떻게 선택합니까?"가됩니다.

    이를 수행하는 한 가지 방법은 재귀 검색을 사용하는 것입니다. 아이디어는 다음과 같습니다.

    • B의 길이가 A의 길이와 같으면 B의 모든 요소를 순서대로 선택할 수밖에 없습니다.
    • 그렇지 않으면 선택권이 있습니다. 한 가지 옵션은 B의 첫 번째 요소를 제외하는 것입니다. 이렇게하면 B의 나머지 요소에서 m 요소를 선택하여 A와 함께 가장 작은 내적을 얻습니다. 다른 옵션은 다음의 첫 번째 요소를 선택하는 것입니다. B, 즉 A의 m-1 꼬리 요소로 내적을 최소화하는 것을 목표로 나머지 B에서 m-1 요소를 선택하려고합니다. 따라서 두 옵션을 모두 평가 한 다음 더 나은 것을 선택하십시오.

    이 접근 방식은 효과가 있지만 작성된대로 실용적 이기에는 너무 느립니다. 다행히도 동적 프로그래밍 솔루션으로 멋지게 변환됩니다. 각 재귀 호출은 다음 형식의 문제를 해결하는 것으로 구성 될 수 있습니다.

    A에 대한 인덱스 i와 B에 대한 인덱스 j가 주어 졌을 때, 위치 j에서 시작하는 B의 하위 시퀀스와 위치 i에서 시작하는 A의 하위 벡터를 형성 할 수있는 가장 작은 내적은 무엇입니까?

    여기서 i와 j가 취할 수있는 가능한 값은 O (mn) 뿐이므로 해당 크기의 표를 채우는 것으로이 문제에 접근 할 수 있습니다. 구체적으로 T [i, j]를 테이블로합시다. 다음과 같이 입력합니다.

    • i = m이면 T [i, j] = 0입니다. 즉, A의 요소를 사용할 수없는 경우 내적은 0의 빈 합계가됩니다.
    • T [i, j] = n-j < m-i 인 경우 무한대. 즉, B에 남아있는 요소가 A에 남아있는 것보다 적 으면 내적을 형성 할 수도 없습니다. 따라서 대답은 "너무 큰 것이므로 절대 고르지 못할 것"이라고 가정합니다.
    • 그렇지 않으면 T [i, j] = min (T [i, j 1], A [i] * B [j] T [i 1, j 1]). 즉, 두 가지 선택이 있습니다. 벡터에 B의 j 번째 요소를 포함하지 마십시오.이 경우 위치 j 1에서 시작하는 B의 하위 배열에서 선택할 요소를 찾아야합니다. 또는 B의 j 번째 요소를 내적에 A의 i 번째 요소로 곱한 다음 남은 요소를 최소화합니다.

    각 테이블 항목을 채우는 데는 시간 O (1)가 걸리므로 시간 O (mn)에 테이블을 채울 수 있습니다. 거기에서 표준 DP 테이블 워킹 알고리즘을 사용하여 포함 할 정확한 항목 집합을 재구성 할 수 있습니다. (우리는 요소의 m 2 이 무한대이므로 전체 테이블을 채울 필요가없는 길이 m의 B의 하위 시퀀스가 필요하기 때문에 실제로 속도를 높일 수 있습니다. 우리는 그것들을 채우는 것을 건너 뛸 수 있습니다. 그것은 O (m (n-m 1)))의 runtime을 제공합니다.



    답변2

    문제는 @templatetypedef의 답변으로 다시 작성되었습니다.

    "길이가 m과 n 인 두 개의 시퀀스 A와 B가 주어지면, A와 가장 낮은 내적을 갖는 길이 m의 B의 하위 시퀀스를 찾으십시오."

    여기서 접근 방식은 순방향 절차를 사용하여 가장 가능성이 높은 은닉 상태 시퀀스를 찾기위한 동적 프로그래밍 알고리즘을 고려하는 것입니다.

    여기서 i위치의 상태는이 위치에서 잠재적으로 사용되는 A 의 요소 수에 해당합니다. 여기서 i 는 < code> B배열. 그런 다음 총 가능성 수를 그래프로 표시 할 수 있습니다.이 그래프의 경로에 해당하는 최상의 솔루션입니다.

    이 방법은 주로 두 개의 배열을 사용합니다.

    P [i] [k]: 를 가정하고 A 의 첫 번째 i값을 고려하여 현재 내적 (최소)의 최상의 값 B배열의 k값이 사용되었습니다.

    S [i] [k]각 주 k 에 대해 i단계에서 내린 결정을 암기합니다.
    k 는 기본 격자의 상태에 해당합니다.

    순방향 반복 : 경로 측정 항목 계산

    초기화 :

    P[1][0] = 0             -> case B[1] is not used
    P[1][1] = A[1]*B[1]     -> case B[1] is used
    P[1][k] = infinite for k = 2..m
    S[1][0] = 0
    S[1][1] = 1

    P [i] [k] 의 재귀 계산

    Do i = 2 to n
        P[i][0] = 0
        S[i][0] = 0
        Do k = 1 to m
            P[i][k] = min (P[i-][k], P[i-1][k-1] + B[i] * A[k])
            S[i][k] = 0 in the first case       -> B[i] is not used
            S[i][k] = 1 in the second case      -> B[i] is used

    내부 루프에서 최대 k값을 m대신 min (i, m) 으로 설정하여 쓸모없는 계산.

    역방향 반복 : 솔루션 읽기

    Minimum dot product = P[n][m]

    (n, m)위치에서 시작하여 역순으로 격자를 통과하고 i위치를 기록하여 해당하는 최상의 A값을 얻습니다. S [i] [state] = 1 입니다. 그래프의 최적 경로는 state 의 연속 값에 해당합니다.

    state = m;
    Do i = n to 1
        if (S[i][state) == 1)
            state = state - 1
            B[i] (or index i) is added to the solution set S[]
        else
            state unchanged

    프로세스가 끝날 때 배열 S [] 에는 B [i] 의 최적 시퀀스가 역순으로 포함됩니다.

    글로벌 시간 및 공간 복잡성은 O (nm)입니다.

    이 동적 접근 방식은 @templatetypedef의 답변에 게시 된 것과 유사합니다. 차이점은 다른 접근 방식에서 암시 적이었을 때 은닉 상태를 명시 적으로 도입하여 얻은 것입니다.

    또 다른 차이점은 재귀 솔루션 대신 루프 솔루션을 얻는다는 것입니다.



    답변3

    됐습니다. 편집 : 죄송합니다. 알고리즘이 필요하다는 것을 알았습니다. 그것이 중요하다면 그것을 실행하는 데 오래 걸리지 않습니다. 길이가 1,000과 1,000,000 인 배열의 경우 1.57 초가 걸렸습니다. 선형 복잡도를 가지고 있으며 알고리즘 사용이 왜 보장되는지 모르겠습니다.

    import numpy as np
    
    A = np.array([7,6,5,4,3,2,1])
    B = np.array([37.97, 34.45, 32.41, 32.17, 35.48, 35.91, 33.81, 32.23, 33.46,
           35.35, 33.03, 37.36, 32.18, 29.29, 30.23, 30.94, 34.26, 31.74,
           29.24, 25.93, 29.26, 33.64, 33.28])
    
    def return_smallest(short, long):
       f = list()
       len_small = short.shape[0]
       len_long = long.shape[0]
       for x in [long[i:i+len_small] for i in range(0, len_long-len_small)]:
          f.append(np.dot(short, x))
       i = np.argmin(f)
       return long[i:i+len_small]
    
    return_smallest(A, B)

    Out [1] : array ([29.29, 30.23, 30.94, 34.26, 31.74, 29.24, 25.93])



     

     

     

     

    출처 : https://stackoverflow.com/questions/58922053/find-smallest-sum-of-products-without-changing-the-order

    댓글

Designed by Tistory.