boris-kz / CogAlg

This project is a Computer Vision implementation of general hierarchical pattern discovery principles introduced in README
http://www.cognitivealgorithm.info
MIT License
90 stars 42 forks source link

init = 0 if select_ == 1 else 0 is always == 0 #3

Closed Twenkid closed 6 years ago

Twenkid commented 6 years ago

Shouldn't it be: init = 1 if select_ == 1 else 0

Twenkid commented 6 years ago

Or rather ?

init = 1 if len(select_) == 1 else 0 or

init = 1 if len(select_) > 0 else 0

Because select_ == 1 (a list) in a console test seems == 1 either if it's empty [] or if it has elements.

boris-kz commented 6 years ago

Thanks Todor, so you are saying list != len(list)? I was told otherwise.

Twenkid commented 6 years ago

Yes, at least I think so and this is what my tiny code tests show (run it if you wish):

https://github.com/Twenkid/CogAlg/commit/83f82422c30fe3c460b72919803d30adc840d567

I haven't seen your syntax, so I wasn't sure if it were a rarely used feature - e.g. type inferring as lenght when there were a comparison with scalar. To me it's not reasonable, though. Even if it's "None" it seems to return "1".

There's similar syntax in C/C++, for a dynamic variable (pointer) which has not allocated memory yet and is set initially to 0 (NULL).

Then Var==0 would return TRUE (which is 1 in C) and after allocating memory, the expression would return FALSE, because the pointer would hold a valid address.

boris-kz commented 6 years ago

Thanks Todor, I corrected it. Also note that I sometimes have operations that directly change values in tuples, which is not legal. I guess I have to either unpack and repack these tuples, or convert them into lists.

Twenkid commented 6 years ago

Right, this is a test with sample reassignment: https://github.com/Twenkid/CogAlg/blob/master/test.py

It's the expressions: dP[7]=, vP[7]=, alt_P[7] ...

Also if alt: semantics was suspicious, similarly to if selection_, I assume you meant "any of the components is different than 0". Tests confirmed, it's always True even if it's 0,0,0, see also the cases in test.py**.

Another solution for such cases when you watch for any change is to have a separate flag "changed".

boris-kz commented 6 years ago

Thanks, I changed: if alt: to: if alt[0]: Is that ok? Is there an easy way to convert tuples to lists?

Twenkid commented 6 years ago

if alt[0]: Yes. (I didn't know yet for which exact element you expected a non-zero value.)

Tuples: Yes, there are direct commands. A discussion and answers: https://stackoverflow.com/questions/16296643/convert-tuple-to-list-and-back

alt = 1,0,0 alt_list = list(alt) alt_tuple = tuple(alt_list)

There are examples for more complex cases, tuple of tuples.

If there is a complex structure with mixed tuples, lists, tuples of tuples etc., however I don't know could it be so straight or an explicit type-reflection would be needed (slow), that may require more checking. (But repetitive conversion may hit performance.)

Twenkid commented 6 years ago

Also, besides numpy, if it can't be installed for some reason in a Pypy environment for example, there are also simple Python "array" module, but it holds same-type elements, like for input images: https://docs.python.org/3/library/array.html

boris-kz commented 6 years ago

Thanks. I guess I could just initialize all tuples as lists (=[]), and they will stay lists after assignment? But that should be a lot slower. Is there a structure that is fixed-length, contains different types, but mutable?

Twenkid commented 6 years ago

Would lists stay lists after a tuple is assigned to the variable a = []? AFAIK - no. This code snippet turns a list into a tuple:

b = []

d = 56; g = 67; k=4 b = d, g, k b (56, 67, 4)

b = [2,5,6] b = d,g,k b (56, 67, 4)

(Except if the type hints, TypeAlias, NewType don't work for it with some special constraining usage - see below).

However assignment of the components from lists seems the same:

def f4(): alt = [1, 45, 24] alt_len, alt_vG, alt_dG = alt print(alt) print(alt_len, alt_vG, alt_dG)

[1, 45, 24] 1 45 24

The structure - well, I think the closest is Class, maybe not exactly as you asked, as of being sure that all instances are same-size, maybe they would, but I don't know would be of much advantage, because they would be likely to be complex objects with dynamic variables with dynamic size and their attributes may be not locally allocated in contiguous RAM-block, I don't know.

Actually lists and even int are also instances of classes. Formally class is dynamic, it could be potentially extended in run-time and if it has lists or other dynamic size variables, it won't be same size.

Type hints, type aliases and NewType can be used, though, but I don't have experience with them, maybe it may serve as building a more C-like/C++ structures/classes: https://docs.python.org/3/library/typing.html

However it's not yet clear does strict type-checking is applied or forced type-conversion when a not appropriate type is assigned.

One simple tests didn't do: It returns float when float is sent: def set(i: int) -> int: ... b = i ... return b ...

set(3) 3 set(3.57) 3.57

...

Also, I think performance-wise and precision-wise care should be taken about int/float mixing. I noticed that in some places you use integer division //. There is also a Numpy dump with types, like "i4" (that's int 4 bytes): https://docs.scipy.org/doc/numpy-1.13.0/reference/arrays.dtypes.html On the other hand the standard division / produces floats. When float/int are mixed, the type assigned to the result variable will be float, even if integer division was used:

c = 8.53 // 5 c 1.0 c = 5 // 3.32 c 1.0 c = 5 // 5.98 c 0.0

(There would be type conversions + the calculations and the other overhead).

In current implementation, the image input is int, but once division kicks in: comp_P, fork_eval, the variables become float unless they were explicitly converted to int with int(...) c = int(a/b).

Such type conversion may apply also if the variables are class-attributes, also potentially change the type/recreate the variable (which itself is a class instance).

One way to partially limit this is to filter all accesses to class' attributes through methods (functions), however Python class elements by default are "public", there is a convention for "private" by adding underscores: classname, but it's for the developers, technically they are also accessible. See 9.6. Private Variables.

Twenkid commented 6 years ago

I missed to mention the "struct" (import struct) - because it requires pack/unpack to binary representation of C-types and it seems cumbersome.

http://www.learntosolveit.com/python/design_struct_example.html https://docs.python.org/3/library/struct.html

Also, do you know about the named tuples?

https://docs.python.org/dev/library/collections.html#namedtuple-factory-function-for-tuples-with-named-fields

boris-kz commented 6 years ago

I don't get it. A list can take anything, why would assignment change it to tuple? Do you get a type error if you try append, +=, list[n] = x, etc., after assigning list = a,b,c? I use // because match from division is defined as an integer part of ratio, not just to avoid floats. Miss is a modulo, I compute indirectly, but probably should use % to avoid messing with a sign.

Twenkid commented 6 years ago

list+= doesn't produce a type error, but the tuple is flatten and the items in the tuple are added as individual ones. I assume that the k[]; k = (1,2,3) type-change is due to the assignment operator - perhaps the type on the right hand has a higher priority.

l+=(5,6,4) l [1, 0, 0, 5, 6, 4]

Append and addressing an index work as expected intuitively:

alt (1, 0, 0) l.append(alt) l [1, 0, 0, 5, 6, 4, (1, 0, 0)] l[0] = alt l [(1, 0, 0), 0, 0, 5, 6, 4, (1, 0, 0)]

l[5]=alt l [(1, 0, 0), 0, 0, 5, 6, (1, 0, 0), (1, 0, 0)]

Error if out of range:

l[10] = alt Traceback (most recent call last): File "", line 1, in IndexError: list assignment index out of range ...

boris-kz commented 6 years ago

So, it seems that there is no type change, it's mutable, so it is still a list. Anyway, I will just convert it to list if it gives me an error.

On Fri, Feb 2, 2018 at 4:51 PM, Todor Arnaudov notifications@github.com wrote:

list+= doesn't produce a type error, but the tuple is flatten and the items in the tuple are added as individual ones. I assume that the k[]; k = (1,2,3) type-change is due to the assignment operator - perhaps the type on the right hand has a higher priority.

l+=(5,6,4) l [1, 0, 0, 5, 6, 4]

Append and addressing an index work as expected intuitively:

alt (1, 0, 0) l.append(alt) l [1, 0, 0, 5, 6, 4, (1, 0, 0)] l[0] = alt l [(1, 0, 0), 0, 0, 5, 6, 4, (1, 0, 0)]

l[5]=alt l [(1, 0, 0), 0, 0, 5, 6, (1, 0, 0), (1, 0, 0)]

Error if out of range:

l[10] = alt Traceback (most recent call last): File "", line 1, in IndexError: list assignment index out of range ...

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/boris-kz/CogAlg/pull/3#issuecomment-362718188, or mute the thread https://github.com/notifications/unsubscribe-auth/AUAXGVmvyadWmowUTyMiz8y_VbFn5hCeks5tQ4NXgaJpZM4RxwEc .

Twenkid commented 6 years ago

No, I think there is a type change when there's a direct assignment of a tuple to a var declared as list. At least that's the behaviour I see:

a = [1,2] alt = 5,6,7 a = alt a (5, 6, 7) a+=5 Traceback (most recent call last): File "", line 1, in TypeError: can only concatenate tuple (not "int") to tuple a (5, 6, 7) a+=(10,9,8) a (5, 6, 7, 10, 9, 8)

It turns into a tuple.

Yes, if you append to a list, or insert into it, it's still a list.

boris-kz commented 6 years ago

Ok, it's append or insert then.

On Fri, Feb 2, 2018 at 5:22 PM, Todor Arnaudov notifications@github.com wrote:

No, I think there is a type change when there's a direct assignment of a tuple to a var declared as list. At least that's the behaviour I see:

a = [1,2] alt = 5,6,7 a = alt a (5, 6, 7) a+=5 Traceback (most recent call last): File "", line 1, in TypeError: can only concatenate tuple (not "int") to tuple a (5, 6, 7) a+=(10,9,8) a (5, 6, 7, 10, 9, 8)

It turns into a tuple.

Yes, if you append to a list, or insert into it, it's still a list.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/boris-kz/CogAlg/pull/3#issuecomment-362725226, or mute the thread https://github.com/notifications/unsubscribe-auth/AUAXGWOtzXoP0F69FxKUwVGboOcDClRNks5tQ4qIgaJpZM4RxwEc .