I'm working on a function that takes in a NumPy array containing only mutually distinct positive square numbers. I want the function to pick an element at random, find if there is a lower positive square number than the number selected: (1) if there is, return the array with the lower positive square number in place of the original element (2) if there isn't, return a copy of the original array.
The reason I'm developing this function is to create a simulated annealing solution to the Magic Square of Squares Puzzle, and this function would serve as one of the mutations to the candidate solution.
I've had a go at the implementation:
def last_square(x): xcopy = x.copy() index_1 = np.random.randint(0, x.shape), np.random.randint(0, x.shape) c = x[index_1]-1 while np.sqrt(c) != int(np.sqrt(c)) or c in set(x.flatten()): if c < 2: return xcopy else: c -= 1 x[index_1] = c return x
Will my function always have the behaviour I've specified?
I've been asked some clarifying questions that I'll address here. There were very helpful in getting me to see what else I still had to explain.
Why are you iterating through all possible numbers less than the chosen one, instead of just iterating through the array itself?
I am looking for the next smallest positive square number below the one that was randomly selected from the array that is not in the array.
Why do you care about
last_square at all? Taking the square root of the elements will not change their ordering.
I agree that removing the square too that not change the ordering of the the square numbers currently within the array, nor does it change the position of a candidate square number
c among all positive square numbers.
I care about checking if
np.sqrt(c) != int(np.sqrt(c)) because a number whose square root is an integer is a square number.
Do you care whether the lower number is chosen non-deterministically? What should happen if there is more than one lower number? Currently it looks like you've implemented a lookup for the next lowest number closest to the chosen number, which is not what you described in the question.
The randomized selection of an element in the array is of course random, but taking that element being chosen, I'm aiming for the rest of the behaviour of the function to be deterministic. That is to say, given the array and the randomly selected element, then the function will always give the same return.
I want to preserve the mutual distinctness of the positive square numbers within the array, so my goal is to find the next lowest positive square number that is not in the array. I was trying to acheive this by inclusively disjoining
c in set(x.flatten()) to the header of the loop, thereby keeping the loop going when
c is still a number within the array.
As written, if you find a lower number and copy it to the chosen location, your claim that the array's elements are mutually distinct will be violated.
Using the following
if c < 2: return xcopy else: c -= 1
I am checking if
c has gone too low, in which case I return a copy of the original array. If I break from the loop, the following lines will change the original array and return the array with the substitution completed.
x[index_1] = c return x
I think what I am having trouble with in part may be when calling
c without checking if
c is non-negative. I'll work on correcting that and editing the code when I've resolved that issue.
Let me know if there are further questions. I'm happy to clarify.