Program to find expected sum of subarrays of a given array by performing some operations in Python


Program to find expected sum of subarrays of a given array by performing some operations

Suppose we have an array A whose size is n and two values p and q. We can perform these operations on A.

  • Randomly select two indexes (l, r) where l < r, then exchange A[l] and A[r]
  • Randomly select two indexes (l, r) where l < r, then reverse subarray of A form index l to r.

After performing first operation p number of times and the second operation q times, we randomly select two indices l & r where l < r and calculate the S = sum of all elements of the sub array A[l..r], then we have to find the expected value of S.

So, if the input is like A = [1,2,3] p = 1 q = 1, then the output will be 4.667 because

Step 1: we have three choices −

  • swap(0, 1) so the array will be 2 1 3

  • swap(0, 2) so the array will be 3 2 1

  • swap(1, 2) so the array will be 1 3 2

Step 2: we have three choices again for each outcome −

  • [2 1 3] to [1 2 3], [3 1 2], [2 3 1]

  • [3 2 1] to [2 3 1], [1 2 3], [3 1 2]

  • [1 3 2] to [3 1 2], [2 3 1], [1 2 3]

There are 9 possible arrays so probability is 1/9. So each of the 9 arrays will have 3 possible sums with equal probability. For an instance, [1 2 3], we can get 1+2, 2+3 and 1+2+3. And there are 27 outcome in total for this input, the expected value can be calculated by finding sum of all 27S and dividing it by 27.

To solve this, we will follow these steps −

  • Define a function matmul() . This will take a, v, n
  • toret := an array of size n and fill with 0
  • for i in range 0 to n - 1, do
    • for j in range 0 to n - 1, do
      • toret[i] := toret[i] + a[i, j]*v[j]
  • return toret
  • From the main method, do the following:
  • n := size of A
  • temp := a new list
  • swp := (n - 3) /(n - 1)
  • swapvalp := ((swp^p)*(n - 1) + 1) /n
  • swapvalm :=(1 - (swp^p)) /n
  • rev := a new empty list
  • dotv := a new empty list
  • for i in range 0 to n - 1, do
    • swaprow := a new empty list
    • revrow := a new empty list
    • for j in range 0 to n - 1, do
      • insert swapvalm at the end of swaprow
      • insert 2*(minimum of i, j, (n-i-1) and (n-j-1+1)/(n*(n - 1)) at the end of revrow
    • swaprow := a new empty list
    • revrow := a new empty list
    • for j in range 0 to n - 1, do
    • swaprow[i] := swapvalp
    • revrow[i] := 1.0 - 2*((i + 1)*(n - i) - minimum of (i+1) and (n - i))/(n*(n-1))
    • insert swaprow at the end of temp
    • insert revrow at the end of rev
    • insert 2*((i+1)*(n-i) - 1)/(n*(n-1)) at the end of dotv
  • A := matmul(temp, A, n)
  • for i in range 0 to q, do
    • A := matmul(rev, A, n)
  • tot := 0.0
  • for i in range 0 to n, do
    • tot := tot + dotv[i]*A[i]
  • return tot

Example

Let us see the following implementation to get better understanding −

def matmul(a, v, n):
   toret = [0]*n
   for i in range(n):
      for j in range(n):
         toret[i] += a[i][j]*v[j]
   return toret

def solve(A, p, q):
   n = len(A)
   temp = []
   swp = (n - 3)/(n - 1)
   swapvalp = (pow(swp, p)*(n - 1) + 1)/n
   swapvalm = (1 - pow(swp, p))/n
   rev = []
   dotv = []
   for i in range(n):
      swaprow = []
      revrow = []
      for j in range(n):
         swaprow.append(swapvalm)
         revrow.append(2*(min(i, j, n - i - 1, n - j - 1) + 1)/(n*(n - 1)))
      swaprow[i] = swapvalp
      revrow[i] = 1.0 - 2*((i + 1)*(n - i) - min(i + 1, n - i))/(n*(n - 1))
      temp.append(swaprow)
      rev.append(revrow)
      dotv.append(2*((i + 1)*(n - i) - 1)/(n*(n - 1)))

   A = matmul(temp, A, n)
   for _ in range(q):
      A = matmul(rev, A, n)

   tot = 0.0
   for i in range(n):
      tot += dotv[i]*A[i]

   return tot

A = [1,2,3]
p = 1
q = 1
print(solve(A, p, q))

Input

[1,2,3], 1, 1

Output

0.0

Updated on: 11-Oct-2021

200 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements