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
91 stars 41 forks source link

Update level_1.py #1

Closed Twenkid closed 6 years ago

Twenkid commented 7 years ago

pri_p was not defined in inc_rng: prip = ip[x-1] #T. x is supposed to be > 0 ...

boris-kz commented 7 years ago

Todor, this loop is conditional on x>0, see above.

That's what I say, it's > 0 thus it doesn't need a check before assignment. The added code is an assignment to pri_p which is not set in your code.

It's:

for x in range(W):

    p = ip_[x]  # better than pop()?
    if x > 0:
        pri_s, I, D, V, rv, p_, ow, alt_, pri_sd, Id, Dd, Vd, rd, d_, owd, dalt_, vP, dP_ = \
        comp(p, pri_p, fd, fv, W, x,  ...

pri_p is not an input parameter and is not defined.

On Jun 4, 2017 11:38 AM, "Twenkid" notifications@github.com wrote:

pri_p was not defined in inc_rng: prip = ip[x-1] #T. x is supposed to be > 0 ...

You can view, comment on, or merge this pull request online at:

https://github.com/boris-kz/CogAlg/pull/1 Commit Summary

  • Update level_1.py

File Changes

Patch Links:

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/boris-kz/CogAlg/pull/1, or mute the thread https://github.com/notifications/unsubscribe-auth/AUAXGXB6DRgfR7B4C6tQmIw3uYsEHjJ0ks5sAs-AgaJpZM4NvaDW .

Twenkid commented 7 years ago

Sorry, I had to add a new comment, but clicked Update. :)

Twenkid commented 7 years ago

OK, I saw what you mean, you update it using p after the comp. It's still less confusing if variables are defined linearly before use.

boris-kz commented 7 years ago

Todor, are you talking about Le1() or inc_rng()?

in inc_rng() pri_p is part of last tuple, with range defined x >=0: ... for x in range(r+1, W):

    p, fd, fv = ip_[x]       # compared to a pixel at x-r-1:
    pp, pfd, pfv = ip_[x-r]  # previously compared p(ignored), its fd, fv to next p
    fv += pfv  # fv is summed over extended-comp range
    fd += pfd  # fd is summed over extended-comp range

    pri_p, pri_fd, pri_fv = ip_[x-r-1]  # for comp(p, pri_p), pri_fd and pri_fv ignored

in Le1(), there already is an explicit x>0 and then assignment pri_p = p in the first run, when x=0.

boris-kz commented 7 years ago

Yes, I replied before I saw your last. It may be confusing but concise, which is my priority. The logic of it may be even more confusing with redundant assignments.

boris-kz commented 7 years ago

Sorry, it's not more concise than yours, which I already use in inc_rng(). But it's more logical and faster because you don't need to access memory. You can use yours in your fork :).

Twenkid commented 7 years ago

OK. You're probably right about the access (I don't know how it's actually cached, but a local variable should be faster than a list redirection).

Regarding the conciseness:

Something that I find confusing/mind-overloading in reading the code are the excessively long tuples + very short names, which makes following which assigns to which harder.

Usually it gets too much above a few or 5-7 parameters and they are bundled in classes/structs, or at least they have more suggestive names.

That allows for one, once she understands and knows all the members, to stop getting distracted by thinking and glancing over each element every time. It's a "complexity hiding" refactoring operation.

We talked about the short identifiers, that's confusing/overloading also due to the lack of discrimination detail. The code looks "the same" or almost repeating.

So, I'll think about trying to convert the code to simple holder-classes.

Something like: ...

class NPattern: init(s, fd=0, fv=0, r=0, x=0, vP=[], dP=[]): s.fd = fd; s.fv = fv; s.r = r; s.x = x; s.vP = vP; s.dP = [];

etc.

(s is short for "self")

Then:

nP = NPattern() #default values

Then:

nP = NPattern(); vP = VPattern(); dP = DPattern();

There could be a bundle of all:

class Pattern: init(s, NPattern nP, VPattern vP, DPattern dP): s.nP = nP; s.vP = vP; s.dP = dP;

init(s): #default s.nP = NPattern(); s.vP = VPattern(); s.dP = s.DPattern();

class InputVars: init(s, p=0, pri_p=0, _p = [], ... ) s.p = p; s.pri_p = pri_p; ... # _p, _d, _m, fd, fv, dy, my, x, y, _x, W, r, A,

also

class Compared:

....

pri_s, I, D, V, rv, p_, ow, alt_, \
            pri_sd, Id, Dd, Vd, rd, d_, owd, dalt_, \
            _x, _ip_, vP_, dP_, _vP_, _dP_= \

class Queues:

...

Then:

P = Pattern() input = InputVars() queues = ...

if x > 0: compared = comp(input, vP, dP, queues)

Otherwise we care for details such as are we sending the vars in the right order, is it small or capital p/v. ...

The accesses to members with the "." is also suggestive/helpful for the programmers to remind them where the var belongs:

nP.fd = ... nP.fv = ...

As of efficiency - I assume that we are after correct and intelligible code for now. That goes for other new contributors, too. Otherwise we are making confused decisions - ancient-Assembly-style-like commands and identifiers in a very high level language.

I suspect that you find the tuples convenient for your style, but if you know how much and what types of variables you will send/receive, I think classes will do the same.

The tuples are more "careless", one doesn't have to define explicit types and set names to them.

boris-kz commented 7 years ago

Frankly, I hate OOP. It hides relevant info that I want to have at a glance. Because the code not fixed in stone, I improve all the time. I segment variables into groups by splitting declarations into multiple lines, and put group names and expanded variable names in comments. You can split them into more lines with expanded comments, but black-boxing will practically insure that people won't know what's inside. That's not intelligible, and it makes the code way too rigid.

On Sun, Jun 4, 2017 at 4:21 PM, Twenkid notifications@github.com wrote:

OK. You're probably right about the access (I don't know how it's actually cached, but a local variable should be faster than a list redirection).

Regarding the conciseness:

Something that I find confusing/mind-overloading in reading the code are the excessively long tuples + very short names, which makes following which assigns to which harder.

Usually above a few or 5-7 parameters it gets too much and they are bundled in classes/structs, or at least they have more suggestive names.

That allows when one understands and knows all the members not to get distracted by thinking of each element every time, it's "complexity hiding".

We talked about the short identifiers, that's confusing/overloading also due to the lack of "discrimination detail". The code looks "the same".

So, I'll think about trying to convert the code to simple holder-classes.

Something like: ...

class NPattern: init(s, fd=0, fv=0, r=0, x=0, vP=[], dP=[]): s.fd = fd; s.fv = fv; s.r = r; s.x = x; s.vP = vP; s.dP = [];

etc.

(s is short for "self")

Then:

nP = NPattern() #default values

Then:

nP = NPattern(); vP = VPattern(); dP = DPattern();

There could be a bundle of all:

class Pattern: init(s, NPattern nP, VPattern vP, DPattern dP): s.nP = nP; s.vP = vP; s.dP = dP;

init(s): #default s.nP = NPattern(); s.vP = VPattern(); s.dP = s.DPattern();

class InputVars: init(s, p=0, pri_p=0, _p = [], ... ) s.p = p; s.pri_p = pri_p; ... # _p, _d, _m, fd, fv, dy, my, x, y, _x, W, r, A,

also

class Compared:

....

pris, I, D, V, rv, p, ow, alt_, prisd, Id, Dd, Vd, rd, d, owd, dalt, x, ip, vP, dP, vP, dP= \

class Queues:

...

Then:

P = Pattern() input = InputVars() queues = ...

if x > 0: compared = comp(input, vP, dP, queues)

Otherwise we care for details such as are we sending the vars in the right order, is it small or capital p/v. ...

The accesses to members with the "." is also suggestive/helpful for the programmers to remind them where the var belongs:

nP.fd = ... nP.fv = ...

As of efficiency - I assume that we are after correct and intelligible code for now. That goes for other new contributors, too. Otherwise we are making confused decisions - ancient-Assembly-style-like commands and identifiers in a very high level language.

I suspect that you find the tuples convenient for your style, but if you know how much and what types of variables you will send/receive, I think classes will do the same.

The tuples are more "careless", one doesn't have to define explicit types and set names to them.

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

Twenkid commented 7 years ago

To me that's too many almost-the-same-name variables with "," for a glance and repetitive code; rather that syntax is hiding the actual processing.

OOP (or just Structured programming) is not black boxing, it's also at a glance (after F12 in PyCharm or others) and you can change the content all the time, it's not in stone.

It hides the low level details only on site of usage at a higher level of abstraction, the low level implementation code of the classes is always there and you should understand it/read it first of course.

With PyCharm you go there with F12. It's in one place and you can always change the implementation details, while keeping the overall interface design, and one change will reflect all sites of usage (unlike retyping it). And when you want to create a new item, you won't type

p, ps, pd, ... = (0, 0, 0, 0, ... [], []) but just:

pD = PD()

If you want to change the default values - click, F12, change whatever and now on all sites it would be (0,1,1, 0, ... [1], [0]) or whatever.

It also sets explicit and "active" names (not optional comments), which programmer has to use (and remember) and that suggests thinking of these operations/sets of data together as a whole.

...

Well, if I don't get used to your style, I'll have to create a converter.

boris-kz commented 7 years ago

To me that's too many almost-the-same-name variables with "," for a glance and repetitive code,

It looks almost-the-same until you know what they mean, and repetition forces you to learn it.

to me your code is hiding the actual processing with the syntax...

It's just as important to know what's being processed.

OOP (or just Structured programming) is not black boxing, it's also at a glance (after F12 in PyCharm or others) and you can change it all the time. It hides the low level details only on site of usage at a higher level of abstraction, the low level implementation code of the classes is always there and you should understand it/read it first of course.

It's a matter of degree. It will get more structured with tuples on higher levels, but there is a difference between being able to look and change, vs. having it in your face all the time. The reality is that you won't learn and change low-level details unless you have to look at them.

It's not stopping you for changing it, with PyCharm you go there with F12. It's in one place and you can always change the implementation details, while keeping the overall interface design, and one change will reflect all sites of usage (unlike retyping it). And when you want a fresh item, you won't type p, ps, pd, ... = (0, 0, 0, 0, ... [], []) but just pD = PD(). If you want to change the default values - click, F12, change - and now on all sites it would be (0,1,1, 0, ... [1], [0]) or whatever.

You don't have to type, there is a copy-paste. I will use tuples, etc., but the first level is where you have to focus on everything. And right now I am using it to design level_1_2D, where I do have to review every variable at every step.

Well, if I don't get used to your style, I'll have to create a converter.

Go ahead, but make sure you understand it first. You are right that there should be simplified, more structured representation for beginners, but I don't need it because it's already in my mind. And it's very easy to do with tuples, I don't see any reason for added complexity of classes.

Twenkid commented 7 years ago

You don't have to type, there is a copy-paste.

It's not the point, there's Intellisense etc. Copy-paste is distracting and a bad programming style. Usually it's done due to speed hacking/laziness to structure it.

This is a specific case, you have your preferred style and choices, but in general I think having 35 parameters and commas of hardly visually distinguishable identifiers makes you count commas and stare, rather than think about the semantics, which might be very simple with another notation, but now hidden or made harder to follow due to the comma_underscore overload.

https://en.wikipedia.org/wiki/Duplicate_code

boris-kz commented 7 years ago

You can do it in your fork, Todor, I will take a look.

On Mon, Jun 5, 2017 at 7:55 AM, Twenkid notifications@github.com wrote:

You don't have to type, there is a copy-paste.

It's not the point, there's Intellisense etc. Copy-paste is distracting and a bad programming style. Usually it's done due to speed hacking/laziness to structure it.

This is a specific case, you have your preferred style and choices, but in general I think having 35 parameters and commas of hardly visually distinguishable identifiers makes you count commas and stare, rather than think about the semantics, which might be very simple with another notation, but now hidden or made harder to follow due to the comma_underscore overload.

https://en.wikipedia.org/wiki/Duplicate_code

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

aloschilov commented 7 years ago

Interesting discussion. In context of OOP, I would say that for algorithms it is hardly a good match. Notion of type classes is more natural for description of the world. In context of readability, I would say that yes, it should be improved, but everything from algorithm point of view it is possible to define in algebraic way, topological way (algebraic or not, doesn't matter). The fair point, that intermediate experiments could be carried out any possible way. I like, for example, graph representation for its simplicity, that is why I deeply interested in spectral graph theory and relevant approaches. We would like groups, then explain it on graphs, we would like to deal with topology — define it as graph. Result of level 1 is essentially a graph. @boris-kz approach goes from low level to high level, guys in «Normalized Cuts and Image Segmentation» the other way trying to get global impression of an image.

I think that once formulated rigorously it would be possible to prove, that those approaches end up in the same results using mathematical induction.

boris-kz commented 7 years ago

@aloschilov , how would you improve level 1?

Twenkid commented 7 years ago

A small suggestion:

I think the "if x > 0" checks are not needed inside the cycle, they fail in all but the first pass.

It's better:

p = ip_[0] prip = p for x in range(1,X): # cross-compares consecutive pixels, outputs sequence of d, m, v: p = ip[x] # new pixel, for comp to prior pixel, could use pop()? pri_s, I, D ... = comp(p, pri_p, ... ) pri_p = p

if X < 1, the cycle will be skipped on its own, and 2 pixels are needed for a comparison anyway

Twenkid commented 7 years ago

Regarding Alexander's point - I also'd like different auxiliary or main representations and visualizations of the algorithm; shorter/generalized and also longer (more verbose, more justified); flowcharts, various graphs/call graphs and views, and AST - https://en.wikipedia.org/wiki/Abstract_syntax_tree - or other more abstract, obvious and "meta" models that would generate that code and justify the existence of the variables step-by-step from other simple representations and other kind of search.

It could be some custom-type specifically induced AST model, appropriate for the semantics of that code. It may possibly be something like an editor/IDE that's adjusted and it generates code, schematics. I'm digging in these directions in order to improve productivity.

Saying "schematics" - I think the enormous amount of parameters in calls is appropriate for digital logic designs, thus if you don't want to compress them in the notation, I think block diagrams/tables with connection lines and tuples as "buses" may feel more clear and easier to read and remember.

https://www.google.bg/search?q=block+diagram+cpu+pins&biw=1455&bih=756&tbm=isch&imgil=9xb8r2L6l0r_CM%253A%253BXvM1MJUX7GMTtM%253Bhttps%25253A%25252F%25252Fwww.tutorialspoint.com%25252Fcomputer_logical_organization%25252Fcpu_architecture.htm&source=iu&pf=m&fir=9xb8r2L6l0r_CM%253A%252CXvM1MJUX7GMTtM%252C_&usg=__aYBkU5hQEHG7RQJRrbeTArQhZaY%3D#imgrc=_

boris-kz commented 7 years ago

Thanks Todor! @Twenkid
You are right, except that it should be direct prip = ip[0]. I just updated it, also did some refactoring. BTW, does "if x > 0" incur any performance penalty on current microprocessors? Regarding schematics, I personally don't need them, but if it helps others, great. Let me know when you have something, or want to talk.

Twenkid commented 7 years ago

You are right, except that it should be direct prip = ip[0].

Right. I kept p = ip[0] in order not to hide the sequence of transferring the value.

BTW, does "if x > 0" incur any performance penalty on current microprocessors?

I don't know. We may consider basic profiling tests, it's not complicated, a few "time" routines.

It's possible that the interpreter/compiler figures out that x only grows so that it stops checking it. Also it's a tiny fraction of the computation, comp() and the inc_... functions are the core, so it won't make a big difference for now.

One of the biggest performance bottlenecks IMO is the usage of so many parameters to the functions, that's not only a readability issue.

I'm not sure about Python's internals, Python is slow anyway, but in bare-metal calls in C/C++ setting (x86, 64-bit), the calls to subroutines that have more than 4 input parameters on Windows, and 6 integers + more floats under Linux, access the stack (RAM, probably L1 or L2 cache) instead of direct passing through the registers.

boris-kz commented 7 years ago

Those parameters are future selection criteria. They are partly redundant, but which ones are pruned should depend on evaluation on higher levels. It's an upfront investment in the quality of subsequent selection, which will speed-up higher levels.

On Sat, Jun 10, 2017 at 6:01 AM, Todor Arnaudov notifications@github.com wrote:

You are right, except that it should be direct prip = ip[0].

Right. I kept p = ip[0] in order not to hide the sequence of transferring the value.

BTW, does "if x > 0" incur any performance penalty on current microprocessors?

I don't know. We may consider basic profiling tests, it's not complicated, a few "time" routines.

It's possible that the interpreter/compiler figures out that x only grows so that it stops checking it. Also it's a tiny fraction of the computation, comp() and the inc_... functions are the core, so it won't make a big difference for now.

One of the biggest performance bottlenecks IMO is the usage of so many parameters to the functions, that's not only a readability issue.

I'm not sure about Python's internals, Python is slow anyway, but in bare-metal calls in C/C++ setting (x86, 64-bit), the calls to subroutines that have more than 4 input parameters on Windows, and 6 integers + more floats under Linux, access the stack (RAM, probably L1 or L2 cache) instead of direct passing through the registers.

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

Twenkid commented 7 years ago

My point was not about not sending them. If they are packed and sent as references/pointers, the parameters will occupy one or a few addresses and will be sent by registers, instead of as a line of values pushed to the stack, then read back in the beginning of the function that's called a million time per image.

Performance-wise, for the parts without recursion, some functions could be put inline in order to save on calls and unnecessary transfers of the values of parameters, but that's better done after the algorithm is clear, or if we manage to automate it.

(Usually recursion could be "unrolled" as well, but it might be more complicated and require us to build an artificial stack to store and retrieve the intermediate results.)

https://en.wikipedia.org/wiki/Inline_expansion

boris-kz commented 7 years ago

Yes, I will pack them into formal tuples. It's just a bit too fluid at this point, and actual code will be in level_1_2D.

aloschilov commented 7 years ago

@boris-kz

There is some sense in https://en.wikipedia.org/wiki/Cosine_similarity, especially taking into consideration https://ru.wikipedia.org/wiki/Коэффициент_Отиаи . This would allow you to get a rid of dimensions issue. At least such measure could allow to compare patterns.

What to compare on pixels level? <x, y, weight> treating it as special case of feature vector.

Going further similarity could be closer to the second link provided.

It would allow to address clustering in context of similarity measure and would allow to address classification all the same, since allow to measure possibility, probability.

The main drawback of current implementation of level 1 from what I see, that grouping only consequent elements would not meet criteria of noise stability, the same is true for gradient approach, which guys used at ski learn kit example. According to the first impression noise instability also impacts https://en.wikipedia.org/wiki/Convolutional_neural_network.

It would guarantee fuzziness you was interested in.

boris-kz commented 7 years ago

Alexander,

Appreciate your interest!

On Mon, Jun 12, 2017 at 10:16 PM, Alexander Loschilov < notifications@github.com> wrote:

@boris-kz https://github.com/boris-kz

There is some sense in https://en.wikipedia.org/wiki/Cosine_similarity, especially taking into consideration https://ru.wikipedia.org/wiki/ Коэффициент_Отиаи . This would allow you to get a rid of dimensions issue. At least such measure could allow to compare patterns.

What to compare on pixels level? <x, y, weight> treating it as special case of feature vector.

Going further similarity could be closer to the second link provided.

It would allow to address clustering in context of similarity measure and would allow to address classification all the same, since allow to measure possibility, probability.

The main drawback of current implementation of level 1 from what I see, that grouping only consequent elements would not meet criteria of noise stability, the same is true for gradient approach, which guys used at ski learn kit example. According to the first impression noise instability also impacts https://en.wikipedia.org/wiki/Convolutional_neural_network.

It would guarantee fuzziness you was interested in.

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

boris-kz commented 7 years ago

OK, I did some packing / unpacking with vP and dP in ycomp() of level_1_2D.py, how does it look?

Twenkid commented 7 years ago

Thanks. :)

Twenkid commented 7 years ago

Boris, I don't understand the intent of this code: @boris-kz

def ycomp(t_, t, fd, fv, x, y, X, Y, a, r, vP, dP, vP, dP_, vP, dP): ... dolp_ = dP[8]

...

dP is defined as a hash table:

def Le1(f): ,,, fd, fv, x, y, vP, dP, vP, dP_, vP, dP, F_ = 0,0,0,0, {},{}, [],[],[],[],[]

However:

dolp_ = dP[8]

... is reading the 8-th element from an expected list.

dolp_ also is supposed to be a list (by the naming convention), so if you want to use it like that, it should be declared:

dolp_ = []

Then:

dolp_.append(...)

Or maybe it's supposed to be:

dolp = dP[8]

the 8-th element of dP_ is supposed to be a list (an array) itself?

?

boris-kz commented 7 years ago

Todor,

...

dolp_ = dP[8]

...

dP is defined as a hash table:

def Le1(f): ,,, fd, fv, x, y, vP, dP, vP, dP, vP, dP, F = 0,0,0,0, {},{}, [],[],[],[],[]

I thought that's a tuple, is that the same? Tuple elements can also be accessed by position? PyCharm doesn't give me an error, though I didn't try to run it.

However:

dolp_ = dP[8]

... is reading the 8-th element from an expected list.

I meant it as 9th element, starting from 0?

dolp_ also is supposed to be a list (by the naming convention), so if you

want to use it like that, it should be declared:

dolp_ = []

Yes, I had that before switching to tuples. Not sure it's necessary, I don't get an error and already have it in line 100:

Id, Dd, Ddy, Md, Mdy, Dq, d, dolp, olp, dolp = 0,0,0,0,0,0, [],[], 0,0 # init. dP and olp

Then:

dolp = dP[8]

the 8-th element of dP_ is supposed to be an array itself?

I guess I can always convert a tuple into list, if that's necessary. The only difference is security: tuples are immutable.

Twenkid commented 7 years ago

That:

fd, fv, x, y, vP, dP, vP, dP_, vP, dP, F_ = 0,0,0,0, {},{}, [],[],[],[],[]

would be a tuple if there's an assignment:

t = fd, fv, x, y, vP, dP, vP, dP_, vP, dP, F_ = 0,0,0,0, {},{}, [],[],[],[],[] t (0, 0, 0, 0, {}, {}, [], [], [], [], []) t[9] [] t[8] [] t[5] {} t[4] {}

However dP is defined as a dictionary {}

Without an assignment, that's a declaration and initialization of many variables in one line:

fd, fv, x, y, vP, dP, vP, dP_, vP, dP, F_ = 0,0,0,0, {},{}, [],[],[],[],[] fd 0 dP {}

Yes, the 9-th, if you count [0]as "the first", I thought of it as the "0-th"...

boris-kz commented 7 years ago

As an initial comprehension, is there any difference between tuple and dictionary? Assignment follows comprehension, in this case in line 100. I didn't initialize it in the beginning because PyCharm did not show it as an error, so I thought it can figure what it is with multi-pass.

On Fri, Jun 16, 2017 at 9:08 PM, Todor Arnaudov notifications@github.com wrote:

That:

fd, fv, x, y, vP, dP, vP, dP, vP, dP, F = 0,0,0,0, {},{}, [],[],[],[],[]

would be a tuple if there's an assignment:

t = fd, fv, x, y, vP, dP, vP, dP, vP, dP, F = 0,0,0,0, {},{}, [],[],[],[],[] t (0, 0, 0, 0, {}, {}, [], [], [], [], []) t[9] [] t[8] [] t[5] {} t[4] {}

However dP is defined as a dictionary {}

Without an assignment, that's declaration and initialization of many variables in one line:

fd, fv, x, y, vP, dP, vP, dP, vP, dP, F = 0,0,0,0, {},{}, [],[],[],[],[] fd 0 dP {}

Yes, the 9-th, if you count [0]as "the first", I thought of it as the "0-th"...

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

Twenkid commented 7 years ago

Yes. Tuples are an ordered list of variables, where the identifiers are not saved.

A dictionary (hash table) is an unordered set of key-value pairs. The value is normally read by the key.

d = {} d['some'] = 734

or d['fd'] = 0 ("fd" is a string literal, if a variable is given it will be evaluated and its value applied as an accessor)

OK, I assume you mean that (it's line 102 in my view)

        _o = len(dP_), dolp  # len(dP_) is index of current dP, dolp formed by comb_P()
        olp_.append(o)  # index and dolp of terminated dP is buffered at current vP_

        Id, Dd, Ddy, Md, Mdy, Dq, d_, **dolp_,** olp, dolp = 0,0,0,0,0,0, [],[], 0,0  # init. dP and olp

Then:

dP = prisd, Id, Dd, Ddy, Md, Mdy, Dq, d, dolp, dolp_

Thus:

dP[8] holds dolp_, an empty list

Some error messages with tuples from my console as an example of what they accept:

t[dP] Traceback (most recent call last): File "", line 1, in TypeError: tuple indices must be integers or slices, not dict t["dP"] Traceback (most recent call last): File "", line 1, in TypeError: tuple indices must be integers or slices, not str

boris-kz commented 7 years ago

Ok, so there is no comprehension for tuples, I just declared vP and dP in Le1(). Is this vP and dP packing actually worth it, either for speed or for clarity?

Twenkid commented 7 years ago

I don't know, if you mean this:

t = (a,b) = (1,2)

It does, this keeps both a,b as separate identifiers, and their values go to the tuple as t[0], t[1].

Clarity - yes, speed - I don't know.

BTW, I noticed that: ycomp() returns the lists of patterns:

return vP, dP # or vC2, dC2 formed by comb_P and then cons_P2?

However the values are not fetched from the caller side:

for y in range(1, Y):

    p_ = f[y, :]  # y is index of new line ip_
    t_ = comp(p_, X)
    **ycomp(t_, _t_, fd, fv, _x, y, X, Y, a, r, vP, dP, vP_, dP_, _vP_, _dP_)**
    # internal comb_P()) cons_P2(): triggered by P2) C2 termination
    _t_ = t_

Lists are sent by address, so the content is changed anyway.

Is the return for clarity or for future calls from other functions?

A small test:

s = [1,2,4,8]

def f(a): a.append(16) return(a)

f(s) [1, 2, 4, 8, 16] s [1, 2, 4, 8, 16] s = f(s) s [1, 2, 4, 8, 16, 16]

boris-kz commented 7 years ago

return vP, dP # or vC2, dC2 formed by comb_P and then cons_P2?

However this value is not fetched from the caller side:

Yes, I just changed this to:

vP, dP = ycomp(t_, t, fd, fv, x, y, X, Y, a, r, vP, dP, vP, dP_, vP, dP)

I didn't pay much attention to this because I am still figuring comb_P2(), which is called from ycomp() when the patterns are terminated. There is an issue of possible "forking" into multiple same-sign patterns and how to account for resulting redundancy. Are you available to talk about it?

Twenkid commented 7 years ago

I'm afraid I'm not prepared yet, I lack the needed intuition.

I still haven't resolved the task for rendering better-representations-for-me - have been researching graph visualisation / automatic parser generators / call graph generators (eventually making a custom IDE for CogAlg), but haven't applied one/reached to a working set/hesitating on choices/the amount of efforts.

I've been also improving my computer vision/openCV/numpy/... expertise.

boris-kz commented 7 years ago

Intuition doesn't fall from the sky, that's why we need to talk. I don't think you need visualisation, either of the code or of the results. My approach is almost immediately symbolic, you need to understand the symbols and the reasoning behind them. That's what theory-first means.

On Sun, Jun 18, 2017 at 9:12 AM, Todor Arnaudov notifications@github.com wrote:

I'm afraid I'm not prepared yet, I lack the needed intuition.

I still haven't resolved the task for rendering better-representations-for-me - have been researching graph visualisation / automatic parser generators / call graph generators (eventually making a custom IDE for CogAlg).

I've been also improving my computer vision/openCV/numpy/... expertise.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/boris-kz/CogAlg/pull/1#issuecomment-309276951, or mute the thread https://github.com/notifications/unsubscribe-auth/AUAXGXfznVGjYCz4QMMQmXy5h4-UKk_Nks5sFSJEgaJpZM4NvaDW .

Twenkid commented 7 years ago

Yes, by intuition I mean experience with the code so that I can "see" what's going on; I've not read it much, so let me do it.

Visualizations, graphs etc. are to make it easier and faster and to refactor and convert the code. I want it more connected with obvious sequences of relations and transformations.

Twenkid commented 7 years ago

As of the comment:

for x in range(1, X): # cross-compares consecutive pixels

    **p = p_[x]  # new pixel, comp to prior pixel, pop() is faster?**

Pop() removes the last element (p_[X-1]) and will reduce the length at each step.

f=[1,2,3] d = f.pop() d 3 f [1, 2]

With an index, it's like this:

f=[1,2,3] d = f.pop(1) f [1, 3]

So the query would be:

p = p_.pop(1)

... for all steps.

Then the index would be const, however there's a deletion, too.

In general, once we have complete code, I think we (me) should convert it to C/C++.

boris-kz commented 7 years ago

I am pretty sure pop() is faster, because index has a fixed increment (doesn't need to be computed). Deletion is probably not performed, this is more like a mapping operation in functional programming.

That's the point of these built-in functions: they are optimized for speed. BTW, it's p = p_.pop(), increment is assumed to be 1 unless otherwise specified.

I think there are plenty of tools for conversion to C (or maybe Go), but they work better if python code is optimized.

On Sun, Jun 18, 2017 at 5:24 PM, Todor Arnaudov notifications@github.com wrote:

As of the comment:

for x in range(1, X): # cross-compares consecutive pixels

**p = p_[x]  # new pixel, comp to prior pixel, pop() is faster?**

Pop() removes the last element (p_[X-1]) and will reduce the length at each step.

f=[1,2,3] d = f.pop() d 3 f [1, 2]

With an index, it's like this:

f=[1,2,3] d = f.pop(1) f [1, 3]

So the query would be:

p = p_.pop(1)

... for all steps.

I doubt a deletion of an internal element would be faster than reading, it requires addressing it anyway, then deletion.

In general, once we have complete code, I think we (me) should convert it to C/C++.

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

Twenkid commented 7 years ago

The docs and my example show it removes the last element, thus if you use .pop() the input has to be stored and scanned in reverse order.

https://docs.python.org/3.6/tutorial/datastructures.html

list.pop([i]) Remove the item at the given position in the list, and return it. If no index is specified, a.pop() removes and returns the last item in the list. (The square brackets around the i in the method signature denote that the parameter is optional, not that you should type square brackets at that position. You will see this notation frequently in the Python Library Reference.)


The fast Python is Cython: http://cython.org/#documentation

http://notes-on-cython.readthedocs.io/en/latest/std_dev.html

boris-kz commented 7 years ago

The docs and test show it removes the last element, thus if you use .pop() the input has to be stored and scanned in reverse order.

That's fine, I won't be reusing initial input queue. Those inputs will be stored in p_ per new pattern anyway.


The fast Python is Cython: http://cython.org/#documentation

http://notes-on-cython.readthedocs.io/en/latest/std_dev.html

That's cool, but not urgent. I think built-in functions are already in C anyway. And PyPy may come along obviate it soon enough.

You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/boris-kz/CogAlg/pull/1#issuecomment-309411087, or mute the thread https://github.com/notifications/unsubscribe-auth/AUAXGSz1czoYQSNOiQE9b4hk4vcJ8p2Iks5sFlkggaJpZM4NvaDW .

Twenkid commented 7 years ago
comb_P( ... 
  _P_.reverse(); _P_ += x_buff_; _P_.reverse() # front concat for next P comp

1. _P_.append(x_buff_) ?

In the draft part:

if m_dw_ddx > a: _S /= cos (ddx)

  1. _S is not defined. Is it something among these (m_dw, ... ) / ddx?

  2. Or it should be initialized with 1 or something?

  3. What's the name behind "S"? It appears near "s" code?, but more likely related to "coS"?

  4. Also this "a" (average) is supposed to fed/computed from somewhere, isn't it?

def cons_P2(P): # at CP2 term, sub-level 4? ...

  1. I see it is a draft, what it's supposed to return?
boris-kz commented 7 years ago

comb_P( ... P.reverse(); P += xbuff; P.reverse() # front concat for next P comp

you deleted the underscores, it is:

P.reverse(); P += xbuff; P.reverse() # front concat for next P comp

  1. P.append(xbuff) ?

No, you can't append a list to a list

In the draft part:

if m_dw_ddx > a: _S /= cos (ddx)

1.

_S is not defined. Is it something among these (m_dw, ... ) / ddx?

S is my generic term for summed variables: I, D, M...

1.

Also this "a" (average) is supposed to fed/computed from somewhere, isn't it?

Yes, this is an average specific to a given variable, I haven't fully defined it yet

def cons_P2(P): # at CP2 term, sub-level 4? ...

I see it is a draft, what it's supposed to return?

cons_P2() is supposed to normalize P2s (2D patterns) for the angle of scanning, by */ cos(dx) and possibly re-scanning the blob. So, it will return replacement P2s.

This is why we need to talk, Todor.

Twenkid commented 7 years ago

Boris, please stop with the "surely careless nonsense" priming.

you deleted the underscores, it is: P.reverse(); P += xbuff; P.reverse() # front concat for next P comp

Why should I delete the underscores? They are used by the editor as a markup symbol with the star, I put the code in "code" section once I found it a minute later, you've seen the draft.

OK, in Python + for a list is append.

cons_P2() is supposed to normalize P2s (2D patterns) for the angle of scanning, by */ cos(dx) and possibly re-scanning the blob. So, it will return replacement P2s.

This is why we need to talk, Todor.

I'll attend that "lecture", but the less I've studied the code, the more it would be a listening. It could be this afternoon, I'll be in the hangouts if I'm available.

boris-kz commented 7 years ago

you deleted the underscores, it is: P.reverse(); P += xbuff; P.reverse() # front concat for next P comp

Why should I delete the underscores? They are used by the editor as a markup symbol with the star,

You did it again, get a better editor.

Twenkid commented 7 years ago

It's just a quote of your answer, that's automatically converted. "Get a better editor" - blame github.

Twenkid commented 7 years ago

Blame also your naming convention, underscores in the beginning and the end of an identifier is a bad style, it's usually used only for automatically generated code or at least with a number or a name, а_1, а_2, а_3, but not as a last or first character.

boris-kz commented 7 years ago

So github converts it when you quote code? That's nuisance. I want to keep the underscores, it's the least cluttering symbol.

Twenkid commented 7 years ago

Yes:

_P_

Becomes

P

They are kept with the <> section - insert code.

boris-kz commented 7 years ago

Thanks.

Twenkid commented 7 years ago

The markdowns might be useful, though: https://guides.github.com/features/mastering-markdown/ https://help.github.com/articles/basic-writing-and-formatting-syntax/

function fancyAlert(arg) {
  if(arg) {
    $.facebox({div:'#foo'})
  }
}

(but it seems not to color the Python?)

Unordered

Ordered

  1. Item 1
  2. Item 2
  3. Item 3
    1. Item 3a
    2. Item 3b

Task Lists