Freivalds Algorithm은 행렬 A,B 그리고 C가 있을 때 가 True/False인지 의 시간복잡도로 판별하는 알고리즘이다.
일반적인 행렬 곱셈을 이용하면 의 시간이 걸리고
Strassen(슈트라센) 행렬곱을 이용하면 의 시간이,
Coppersmith–Winograd(코퍼스미스-위노그라드) 행렬곱을 이용해도 의 시간이 걸린다.
설명에 앞서 행렬곱은 아래와 같이 정의된다.

비결정론적 알고리즘인 프리발즈 알고리즘은 아래와 같은 절차를 거친다.
0과 1로 랜덤하게 채워진 열벡터 을 생성하고
인지 아닌지 확인한다.



위 수식이 한 번이라도 False가 나오면 는 False가 되고,
위 방법을 k번 반복하여 모두 일치했다면 는 True라고 가정한다.
(의 오답률을 가진다.)
먼저, 만약 라면 당연히 이다.
이제 이 True여도 실제 는 False일 수 있다. 그럴 확률이 어떻게 나오는지 계산해보자.
라고 정의하자, 이제 (D는 영행렬이 아니면서)
이면서 (은 열벡터)인 상황인 경우의 확률을 찾아야 한다.
여기서 이기 때문에 행렬 D의 원소 중 하나 이상은 반드시 0이 아니게 된다.
하지만 이기 때문에, 이 되어야 한다.
(Dr의 모든 원소가 0이 되어야 하기 때문)
은 열벡터 모두가 0이 될 확률이고,
은 열벡터의 원소 1개가 0일 확률이다.
따라서, < 가 된다.
여기서 우항을 에 대한 식으로 바꾸어 보면 아래와 같다.
위 식은 가 어떠한 값을 가질 확률인데 는 0또는 1의 값만 가질 수 있다. 따라서 과 은 각각 이다.
결론적으로, < 이므로 이를 k번 반복하게 되면 오답률은 로 줄어든다.
using Mat = vector<vector<int>>;
bool Freivalds(Mat& A, Mat& B, Mat& C, int K, int x, int y) {
int t = 20;
while (t--) {
vector<int> r(K);
generate(r.begin(),r.end(), []()->int {return rand() % 2; });
vector<int> Br(K);
for (int i = 0; i < K; i++) {
Br[i]=inner_product(r.begin(), r.end(), B[y+i].begin()+x, 0);
}
for (int i = 0; i < K; i++) {
if (inner_product(Br.begin(), Br.end(), A[i].begin(), 0) - inner_product(r.begin(), r.end(), C[i].begin(), 0) != 0)
return false;
}
}
return true;
}
x와 y는 무엇을 의미하나요?