1
\$\begingroup\$

This is a fun exercise that tries to answer the following question: if the elements from a square matrix are randomly chosen from 0 to 9, is it more like that the determinant would be even or odd?

I'm pretty sure there are different ways of optimizing this piece of code. The first one that comes to my mind is to use only generators (maybe?) and not use the for loop to fill values.

import itertools
import math
import matplotlib.pyplot as plt
import numpy as np
n = 4
lst = list(itertools.product([0, 1], repeat=n))
algo = list(itertools.product(lst, repeat=n))
determinants = np.abs(np.linalg.det(algo))
determinants = np.where(determinants % 2 == 0, 0, 1)
square = math.ceil((math.sqrt(len(determinants)))) ** 2
# fill with generic value if not a perfect square
for num in range(square - len(determinants)):
 determinants = np.append(determinants, -1) 
matrix = np.reshape(determinants, (int(math.sqrt(square)), int(math.sqrt(square))))
fig, ax = plt.subplots() # or
ax.imshow(matrix, cmap="Greens")
plt.show()

All suggestions are welcome :D

Reinderien
70.9k5 gold badges76 silver badges256 bronze badges
asked Aug 23, 2022 at 16:18
\$\endgroup\$
2
  • 3
    \$\begingroup\$ What's the purpose of the code? What shall it do? \$\endgroup\$ Commented Aug 23, 2022 at 16:19
  • \$\begingroup\$ It's just an fun exercise that tries to answer the following question: if the elements from a square matrix are randomly chosen from 0 to 9. Is it more like that the determinant would be even or odd? \$\endgroup\$ Commented Aug 23, 2022 at 16:29

1 Answer 1

1
\$\begingroup\$

The n you care about isn't really 4, it's 4**2 = 16.

Don't use lists, itertools or for loops in a Numpy context.

Don't use np.where in this case; you can replace that entire operation with % 2 alone.

Don't use math.* methods when there are Numpy equivalents.

Don't concatenate-append. Instead, just use slices on a pre-allocated array.

When you reshape to your matrix, leave one of the dimensions implied as -1.

Suggested

The fill step could look like

side = round(np.ceil(np.sqrt(len(determinants))))
filled = np.empty(side**2)
filled[:len(determinants)] = determinants
filled[len(determinants):] = -1

but your operation will always be a perfect square, so just delete that, leaving this code which is equivalent to your original:

import matplotlib.pyplot as plt
import numpy as np
n = 16
lst = np.arange(2**n)
as_bytes = np.stack(
 (np.right_shift(lst, n//2), lst),
 axis=-1,
).astype(np.uint8)
algo = np.unpackbits(
 as_bytes, axis=1,
).reshape((-1, 4, n//4))
determinants = np.abs(np.linalg.det(algo)) % 2
side = round(np.ceil(np.sqrt(len(determinants))))
matrix = determinants.reshape((side, -1))
fig, ax = plt.subplots()
ax.imshow(matrix, cmap="Greens")
plt.show()

Output

imshow result

answered Aug 24, 2022 at 1:03
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.