Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Shor Algorithm #6067

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
57 changes: 57 additions & 0 deletions src/main/java/com/thealgorithms/others/ShorAlgorithm.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.thealgorithms.others;

import java.math.BigInteger;
import java.util.Random;

// The algorithm is referred from
// https://www.geeksforgeeks.org/shors-factorization-algorithm/
public class ShorAlgorithm {
// trying to find the order of exponent given the base and the number
private int exponent(BigInteger base, BigInteger number) {
BigInteger result = BigInteger.ONE;
int increment = 0;
while (!result.equals(BigInteger.ONE) || increment == 0) {
result = result.multiply(base).mod(number);
increment++;
}
return increment;
}

// implementing the shor algorithm
public BigInteger[] shorAlgorithm(BigInteger number) {
if (number.mod(new BigInteger("2")).equals(BigInteger.ZERO)) {
BigInteger p = number.divide(new BigInteger("2"));
BigInteger q = new BigInteger("2");
return new BigInteger[] {p, q};
}

Random random = new Random();
BigInteger base = BigInteger.ZERO;
do {
base = new BigInteger(number.bitLength(), random);
} while (base.compareTo(BigInteger.ZERO) <= 0 || base.compareTo(number) >= 0);

BigInteger hcf = base.gcd(number);
if (hcf.compareTo(BigInteger.ONE) > 0) {
return new BigInteger[] {hcf, number.divide(hcf)};
}

int result = exponent(base, number);
if (result % 2 != 0) {
return null;
}

BigInteger congruentResult = base.modPow(BigInteger.valueOf(result / 2), number);
if (congruentResult.equals(number.subtract(BigInteger.ONE))) {
return null;
}

BigInteger p = congruentResult.add(BigInteger.ONE).gcd(number);
BigInteger q = congruentResult.subtract(BigInteger.ONE).gcd(number);

if (!p.equals(BigInteger.ONE) && !q.equals(BigInteger.ONE)) {
return new BigInteger[] {p, q};
}
return null;
}
}
49 changes: 49 additions & 0 deletions src/test/java/com/thealgorithms/others/ShorAlgorithmTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.thealgorithms.others;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;

import java.math.BigInteger;
import org.junit.jupiter.api.Test;

public class ShorAlgorithmTest {
@Test
public void testFactorizationOfEvenNumber() {
ShorAlgorithm shor = new ShorAlgorithm();
BigInteger number = new BigInteger("15");
BigInteger[] factors = shor.shorAlgorithm(number);

assertNotNull(factors, "Factors should not be null for composite numbers.");
assertEquals(2, factors.length, "There should be two factors.");

BigInteger p = factors[0];
BigInteger q = factors[1];

assertEquals(number, p.multiply(q), "Factors should multiply to the original number.");
}

@Test
public void testFactorizationOfPrimeNumber() {
ShorAlgorithm shor = new ShorAlgorithm();
BigInteger number = new BigInteger("13");
BigInteger[] factors = shor.shorAlgorithm(number);

assertNull(factors, "Factors should be null for prime numbers.");
}

@Test
public void testFactorizationOfEvenCompositeNumber() {
ShorAlgorithm shor = new ShorAlgorithm();
BigInteger number = new BigInteger("20");
BigInteger[] factors = shor.shorAlgorithm(number);

assertNotNull(factors, "Factors should not be null for composite numbers.");
assertEquals(2, factors.length, "There should be two factors.");

BigInteger p = factors[0];
BigInteger q = factors[1];

assertEquals(number, p.multiply(q), "Factors should multiply to the original number.");
}
}
Loading