letmaik
letmaik

Reputation: 3500

Mapping elements in 3D lower "triangle" to linear structure

This is the 3D version of an existing question.

A 3D array M[x,y,z] of shape (n,n,n) should be mapped to a flat vector containing only the elements with x<=y<=z in order to save space. So what I need is an expression similar to the 2D case (index := x + (y+1)*y/2). I tried to derive some formulas but just can't get it right. Note that the element order inside the vector doesn't matter.

Upvotes: 1

Views: 510

Answers (3)

BorjaEst
BorjaEst

Reputation: 756

In case someone interested, here is the code of @letmaik answer in python:

import math
from itertools import combinations_with_replacement

import numpy as np

ndim = 3  # The one you'd like
size = 4  # The size you'd like
array = np.ones([size for _ in range(ndim)]) * -1
indexes = combinations_with_replacement([n for n in range(size)], ndim)


def index(*args):
    acc = []
    for idx, val in enumerate(args):
        rx = np.prod([val + i for i in range(idx + 1)])
        acc.append(rx / math.factorial(idx + 1))
    return sum(acc)


for args in indexes:
    array[args] = index(*args)


print(array)

Although I must confess it could be improved as the order of the elements do not seem natural.

Upvotes: 0

letmaik
letmaik

Reputation: 3500

This is an extension of user3386109's answer for mapping an array of arbitrary dimension d with shape (n,...,n) into a vector of size size(d,n) only containing the elements whose indices satisfy X_1 <= X_2 <= ... <= X_d.

index

size

Upvotes: 3

user3386109
user3386109

Reputation: 34829

The 3D version of the equation is

index := (z * (z+1) * (z+2)) / 6 + (y * (y+1))/2 + x

Upvotes: 1

Related Questions