0

I have a program that takes user input in the form of an integer, lets call it k. Three other numbers are known, a,b and c. My task is to find all positive integer solutions {x,y,z} such that ax + by + cz = k. I wrote a method that I call on objects that have a,b and c built in. There is an additional constraint that says that x + y + z cannot be greater than a known integer p.

    def find_all_solutions(self, k):
        for x in range(0, k/c +1):
            for y in range(0, k/c +1):
                for z in range(0,k/c +1):
                    if x+y+z <= self.p and self.a*x+self.b*y+self.c*z == k:
                        one_solution = [x,y,z]
                        list_of_combinations.insert(END,"x: {0}, y: {1}, z: {2} ".format(one_solution[0], one_solution[1], one_solution[2]))
    K = IntVar()
    KassaBox= Entry(TeaterGUI, relief=GROOVE,textvariable=Kassa,width="15")
    KassaBox.place(x="400",y="240")


    KombinationsKnapp = Button(TeaterGUI, text="Tryck har for att visa alla mojliga kombinationer", command= lambda: TeaterLista[Teater_Index.get()].find_all_solutions(K.get()))
    KombinationsKnapp.place(x="400",y="260")

This works when k is somewhat small (<100000), although as it exceeds 3 digits the interpreter freezes for a couple of seconds as it does its calculations, but eventually it does what its supposed to.

My problem is that if k is larger, the amount of combinations that have to be checked becomes too many to handle for the python interpreter.

So I was thinking that maybe a way of avoiding these crashes is to, instead of the program finding all solutions and adding them all at once, to make the program find each solution and add it one-by-one to the listbox, so as to avoid the computer storing to much information in its RAM before its used. However, with tkinters .insert method seeming like the only way of appending the listbox with info, I don't know how to do this.

Any help would be greatly appreciated!

1 Answers1

-1

instead of this line:

list_of_combinations.insert(END,"x: {0}, y: {1}, z: {2} ".format(one_solution[0], one_solution[1], one_solution[2]))

you could do:

yield "x: {0}, y: {1}, z: {2} ".format(one_solution[0], one_solution[1], one_solution[2])

then to add to the listbox you could do a simple iterative loop:

for solution in find_all_solutions(k):
    listbox.insert("end", solution)

this will get your generator function to yield one answer at a time and allow you to add them one after another to the listbox.

however as the program never reaches the mainloop while this is taking place, the window is never updated. you could manually call window.update() between every insert, but this would slow down your computation.

some better options would be:
1) before you enter this computation loop, add a function like this:

def myupdate():
    window.update()
    window.after(100, myupdate)

and then just before you start the loop add a line like:

window.after(100, myupdate)

you will effectively start a threaded update loop, where the window would update roughly every 100ms

2) add a separate subloop to update the window after every so many inserts

eg:

a = 0
for solution in find_all_solutions(k):
    listbox.insert("end", solution)
    a += 1
    if a == 10: #would update every 10 inserts
        window.update()
        a = 0
James Kent
  • 5,763
  • 26
  • 50
  • Not sure if a generator would help in this instance considering `one_solution` is being constantly overwritten and not taking up any additional memory per iteration. The biggest issue is that Tkinter has to store all of these values somewhere. I do believe a generator would help here but I would suggest changing the `range` methods to `xrange` so as not to hold such a large range in memory three times. –  Sep 09 '14 at 14:52
  • 1
    no, he says he is generating all solutions at once and then adding them to the GUI, so the delay comes from the time taken to compute the solutions, by breaking this out one by one the GUI shouldn't freeze while the results are computed. – James Kent Sep 09 '14 at 14:54
  • quote from the question: "So I was thinking that maybe a way of avoiding these crashes is to, instead of the program finding all solutions and adding them all at once" – James Kent Sep 09 '14 at 15:01
  • Ah, fair enough. Was under the misconception that `.insert` added them before returning as it went through the loop last time I checked. After double checking you are indeed correct. Then yes, this would definitely be a better solution. –  Sep 09 '14 at 15:02
  • @JamesKent Thank you very much! this helped plently and I'm very grateful. However, there is still a problem when k is even larger, say 1 million (that is the maximum value that the program is required to work for). If u have any other suggestions that could make the code run more smoothly, it would be very much appreciated! – Tom Richter Sep 11 '14 at 16:11
  • @Tom Richter could you elaborate please? what sort of problem are you experiencing? could you describe exactly what is happening? edit your question if neccesary – James Kent Sep 12 '14 at 08:01
  • after thinking about it i think i know what the problem is, although you are adding the items to the listbox one by one, the GUI probably still freezes as the window is not being updated, you could manually call window.update(), however this will significantly slow down you computation if you call it between every insert. a better option would be to add a little sub loop to update periodicly, see my revised answer. – James Kent Sep 12 '14 at 08:36