After quite some time without good ideas about how to speed up the code, I managed to make it three times faster.
First, I found out that removing the np prefix from the functions inside the for loop made it about 10% faster. Then, I made the problem more symmetric by making both pinions and wheels share the same starting and ending number of teeth. This allowed me to halve the number of divisions since the ones that would yield less than one can be easily avoided. Finally, I realised I didn't really need to call "nonzero" and "logical_and" functions. After making the necessary changes to remove them, it was ~30% faster.
I also did a bit of a clean-up, added a function that predicts how long it will take to finish crunching and rewrote functions so that the now accept the number of wheels/pinions as a parameter.
The results are just printed on the terminal, maybe you'd like to have them saved to a file too?
I ran the attached script (teeth range 330-360, 10 gears) and the best result has five times less error than the previous best:
And while writing this post, I also ran the script with number=6, wi=340 and wf=360, and it returned a much better set of wheels:
Wheels: [338, 341, 342, 357, 358]
Pinions: [336, 343, 344, 353, 359]
Ratio - 2000_true_ratio: -1.8919e-11
Wheels: [345, 349, 349, 355, 355, 359]
Pinions: [344, 351, 351, 353, 354, 358]
Ratio - 2000_true_ratio: -1.811e-12