Sverchok / SverchokRedux

A reimplementation of Sverchok
GNU General Public License v3.0
4 stars 2 forks source link

Types and broadcast #15

Open ly29 opened 8 years ago

ly29 commented 8 years ago

With bootstrapping done and creating nodes being super easy, the biggest obstacle right now is types and broadcasting.

Types

While np.ndarray is the type of a numpy array it does not specify the dtype of the array nor the dimensions.

For our purposes some nodes simply need the arrays of have shape = N,3 or N,4. This should be possible to derive from the type info.

Certain nodes need to be able to work on a list of np.ndarray, or a complete leaf of the data tree. Basically this is makes us need a more complete type system, supporting at least some limited form of generics to be viable as we introduce more data types... Luckily such frameworks exist in python.

Broadcasting as defined in numpy.

When operating on two arrays, NumPy compares their shapes element-wise. It starts with the trailing > dimensions, and works its way forward. Two dimensions are compatible when

they are equal, or one of them is 1

Broadcast

Furthermore non existent dimensions are implied. A simple check would be some like this.

def is_broadcastable(a, b):
    return all((x == 1 or y == 1 or x == y) for x, y in zip(a.shape[::-1], b.shape[::-1]))

Failing this check the arrays would be expanded according to the list match rules defined in Sverchok but being aware of the numpy concept. With the default being match_long_repeat but with cycle and match shortest being available. Forcing a match type could be as simple as introducing a node on link with the node being interpreted as changing the match type on the relevant elements. (Of course complete data three matching should also be possible)

Sockets

Of course the socket ties into this as well.

ly29 commented 8 years ago

Notes: https://docs.python.org/3/library/functools.html?highlight=singledispatch#functools.singledispatch

zeffii commented 8 years ago

I think I see where this is going. If you/we get this to work efficiently SvRx will seem like magic :)

ly29 commented 8 years ago

It is the inner loop brings that biggest benefits, numpy arrays as leaves in the data tree does that.

ly29 commented 8 years ago

Exceptions from data matching in Sverchok.

Both are quite usable exceptions, but are they worth being exceptions? I am not convinced either way.

ly29 commented 8 years ago

Matching as described above doesn't work everywhere, it ties together with the type system, A simple match between edges and vertices for creating a mesh is an obvious[*] example.

[*] But for some reason it escaped me for a short while.

zeffii commented 8 years ago

not sure I understand why matching would need to happen between Verts and Edges. Maybe automatically cull those edge keys that refer to vertex indices that are higher than len(Verts)? Seems like a heavy op.

Mostly I think we'll want to have checks in place to avoid creating out of bounds indices, difficult... it seems like whatever you do it will slow down things. At least for one execution..

zeffii commented 8 years ago

Maybe the system can behave in a way like the Display list of openGL. first do a slow check, then save some information about the state.

meaning that if the check was run once, and subsequently executed ok, and the tree hasn't updated in some respects compared to the previous execution, then take the leap of faith .

zeffii commented 8 years ago

I dunno. maybe the find max value of nparrays is still faster than all the 'paranoid' checking code we could throw at it...

zeffii commented 8 years ago

i don't know if it's fast to do ' make a view of the current nparray that ommits all rows which contain values above x `

ly29 commented 8 years ago

The type of check of course matters a lot. In creating a mesh some safety checks sooner or later will be needed of course, as late as possible, opengl viewer or mesh creation. I have some ideas about minimizing the tree rebuilding needed.

Of course no automatic matching needs to happen between edges and vertices, in weak moment I didn't consider this and was surprised when things didn't work out...

But it would be nice if the system could take care of matching as needed. Some info is needed for the nodes, a first sane step could be automatic matching between sockets of the same type. This should be possible to override in different ways.

nortikin commented 8 years ago

more types we have more i disoriented. Numpy with python and different python and munpy. and tree check in case of python data, but storing tree structure in case of numpy data... It makes me crazy \0_0> :no_bicycles: adding separated types of 4v, 3v or 2v + different trees v and than how to find if polygon is 4v or diversed to calc faster with numpy or python? It is friday. maybe it is about friday :clock11:

ly29 commented 8 years ago

Yeah I also got a bit confused. But I think I will make clear soon. And if it works out the headache will go away. For all

zeffii commented 8 years ago

I look forward to writing nodes again. :)

nortikin commented 8 years ago

hope you know what to do, @ly29 . I believe in you.

ly29 commented 8 years ago

Going with to motto don't be afraid to start over I will start with this following structure in mind, not all of implemented directly. I am sure there will be reason to amend and change things. Data is stored in a tree structure, with the data in the leaves only. This gives increased flexibility compared to the old data structure where when parsing and the added knowledge of data being encoded inte the types.

Socket Data type
Topology np.ndarray, either with shape, (n,2), (n, 3), (n, 4), np.ndarray(dtype=object)
Vertices np.ndarray, either with shape (n, 3) or (n, 4)
Number np.ndarray, with dtype={np.float64, np.int32} or compatible type. Plain float/int?
String str
Color np.ndarray shape (n,{3,4})
Object blender object reference, either direct or with some meta data
Dict Dict of any type, key must obviously be support hash.
Mesh Either bmesh or a simpler mesh structure only packing the data into a simple class, possibly converted into bmesh when needed. Sort of a delayed bmesh_from_pydata.
Generic Anything goes, however for now tuple and list are reserved for data structure.

A tree manipulation node has to be aware of the data structure and the data type, but looking a some layouts most level finding seems to be to find the right leaves to work with. Of course some manipulations makes sense only in certain context.

I have some additional ideas about whole thing but will let form a bit more.

nortikin commented 8 years ago

topology is it polygons with edges? than >n4 needed. all of this will be in sockets or just inside core? Mesh need to be bmesh and not just mesh. always converting. pipeline seems to be ugly if bmesh + objects + vertices & topology doing the same. How can we reduce count of this stuff? Or let it be?

ly29 commented 8 years ago

@nortikin topology data is can be in many formats according to this principle. n bigger than 4 is allowed. why would it not? I am not so sure that mesh always needs to be bmesh, I have some cases in mind. anyway, conversion would be kept minimal.

pipeline seems to be ugly if bmesh + objects + vertices & topology doing the same

I am not sure if I follow this. an object can either be decomposed and acted upon in its independent parts or composed and be a higher order, like a mesh. anyway, this is for the experiment. if it fails, we change it.

nortikin commented 8 years ago

@ly29 I SEE SKETCHUP EXAmple in front of me, they made splines, mesh and nurbs the same edit principle, so user can make his own, not looking to format. Is it correct way of doing? if we plug i.e. one bmesh and than operating inside node with decompose/compose, so every node can eat bmesh and output it. Objects operations it is other principle at all, Sketchup has not idea of pivot point (origin), wich makes it harder to model. Maybe we really should delegate conversion of formats to user...

PS. current beauty of Sverchok in three sockets types, and all operations occure inside nodes, but if we apply this principle of stratification between besh and so on, we need separate nodes for bmesh operations. i think it is mistake, and Ko made that nodes added disorder in initial clean Sverchok paradigm. I sencerely hate that class of nodes. Personally.

ly29 commented 8 years ago

I disagree, but I will experiment and we can look at it.

there are many useful deviations from the three socket types, like text output etc which is wrapped in crazy way.

How the object and mesh sockets issues where handled and the nodes dealing with them is less than optimal in many ways.

nortikin commented 8 years ago

ok, i see. it is stupid for some data indeed.

ly29 commented 8 years ago

Okay, so the obvious solution is having type aliases for numpy functions depending on which socket type it would generate.

ly29 commented 8 years ago

Introduced a simple system of type aliases, thereby breaking everything. Progress.

Still have to do simple generics so everything will remain broken for a while.

ly29 commented 8 years ago
import numpy as np
from ..svtyping import Number

def add(x: Number = 0.0, y: Number = 1.0) -> [("res", Number)]:
    return x + y

SvRxFunc = [add]