There are lots of questions about how to analyze the running time of algorithms (see, e.g., runtime-analysis and algorithm-analysis). Many are similar, for instance those asking for a cost analysis of nested loops or divide & conquer algorithms, but most answers seem to be tailor-made.
On the o...
@heather What's the question? Even though I may not answer it, since I have to leave in a few minutes, someone else later will see it here and, eventually, try to answer it.
specifically, I want to know a. whether or not this algorithm is polynomial time and b. whether or not this algorithm is more or less efficient than another. the algorithm in question being the third here, compared to the first on the same question
from my conversation with dmckee in hbar it seems that the third is slower than the first, but may still be in polynomial time
@heather Maybe you should also number the lines of the pseudocode in your question. That GOTO 1 isn't understandable (or at least one can't be sure about its meaning) in that context...
The "thing that is computable" is computing a vector that is multiplied by a matrix and when added to another vector should equal another vector. The vector elements are concentrations of chemicals. The matrix contains the net change of various reactions.
@heather your code still differs, unless some checks are ommited. With complexity, they differ by constant, but to optimise it the mere loops are not enough. It depends on the functions called and execution time taken.
Anyway, the conditions differ. Also the code seems a bit like busy waiting. The two versions differ where in fact it spends the not productive time. If you have some change in external scope that indicates the change that some reactions are computable then run it, otherwise it essentially loops utilizing CPU
goto was created for one important reason: if you have a dozen of nested loops and the innermost one is to find some solution, when it finds it all outter loops must be communicated, e.g. by variable "running". So it makes a control flow polluted by checks.
After finding solution goto to escape loop is preffered (by those who accept it as proper instruction). But goto in some languages allows to go backward or jump into nested loop. This is hard to read and check. Then it is a disaster.
I recently wrote a function decorator that enables goto in Python, just like that:
from goto import with_goto
@with_goto
def range(start, stop):
i = start
result = []
label .begin
if i == stop:
goto .end
result.append(i)
i += 1
goto .begin
label .end
...
no, but not because of "goto" itself, but because of busy wait. Both solutions are looping like crazy. I assume that there are some dependencies on external state (even time). So after executing instructions like some_potential_computable_may_appear();
Invoke the function from there
Also, if there are some uncomputable reactions (like never), you will not mannage to do it without threads
No clue, it depends on what you compute and how long it takes. But the flow is bad.
E1: dosomething(); goto E1; is the same as while(true) dosomething();
while(true) is ok for server, for something that must run forever (until interrupt or shutdown), but it is not that good to run computations
For example oxygen is needed, but it is lacking right now. Take your code and without goto pack it into a function (let me call it probableReaction). Now some event or call resources.onNewStuff = probableReaction. Somewhere call resources.add(oxygen)
So the loop does not run all the time, one check after some event, if this is more complicated put some variable e.g. changed = false, and when there was actual computation, flug it and run once more.
Ok, but it was a pseudocode? Anyway, I may translated it poorly, your second code has a nice stop property, after each iteration one reaction was eliminated, either computed or not, but I changed it assuming it was not intentional.
if not computable, it is eliminated completely, if computed, it is moved to a second list.
(and removed from the first)
the original, it is merely run until everything that cannot be computed is eliminated, but I didn't know how to do that w/o a GOTO, so I used the length check and moved to a different list.
Mhm, ok, so the both codes will run exactly reactions.length times, so these are the same, but the "while" one is nicer.
So in that case, don't use goto, because it is really that bad practice everyone mentions.
It is a simple loop in disguise, so it is the case when normal loop should be used.
Mhm, no, there is no escape from goto, the goto code runs forever, while code doesn't. To make it work there should be check if no more reactions goto E2, E2 label placed after the code. So you have a winner.
No, the original is broken, yours is not. If you fix the original these works similar, yours pushes the reactions to some list, so it is a constant time operation * number of elements.
it restarts everytime it hits upon something not computable, but that uncomputable thing is removed, so eventually it will be able to run all the way through, either because the list is empty or everything in the list is computable.
1 eliminate stuff from a list called reactions 2 for each element in reactions: 3 if one thing is computable: 4 compute it 5 else: 6 eliminate element from reactions, GOTO 1
@heather no. These are only loops, that execute the same number if times. They differ by number of checks and push onto list. It really does not make any difference. If you want to speed it up, you have to rewrite actuall computation, use threads, GPU, or something else, change the accuracy.
If foreach works as intended, the goto is in fact not needed, it will only restart the foreach loop, if elements are at the end of the list, it is bad idea. Sorry, now read it without line folds. It is essentially superflous.
Just put eliminate in else clause, after discarding goto, and it seems ok
@Evil but it is necessary - so the removing elements from the list works, actually - i think there might be a problem with that.
eliminate stuff from a list called reactions
while len(reactions) > 0:
while thing is computable:
for i in reactions:
relevant_reactions.append(compute whatever)
reactions.del(i)
reactions.del(i)
^if i do it like this, in python
i'm not sure the loop will work, because it deletes the value in (i) so the value that was in i+1 moves to i, so it skips something