Вы можете сформировать левое обратное:
import numpy as np
import numpy.linalg as lin
B = np.array([[2],[4]])
b = np.array([[4],[4]])
B_linv = lin.solve(B.T.dot(B), B.T)
c = B_linv.dot(b)
print('c\n', c)
Результат:
c
[[ 1.2]]
На самом деле, мы можем просто запустить решатель один раз, не формируя обратное, например:
c = lin.solve(B.T.dot(B), B.T.dot(b))
print('c\n', c)
Результат:
c
[[ 1.2]]
.... как и раньше
Почему? Потому что:
Имеем:

Умножить на B.T
, дает нам:

Теперь B.T.dot(B)
- квадрат, полный ранг, имеет обратное. И поэтому мы можем умножить на обратное значение B.T.dot(B)
или использовать решатель, как указано выше, чтобы получить c
.