Last active
October 18, 2025 14:01
-
-
Save MurageKibicho/92b7cbad071f234dd01e0e84db704629 to your computer and use it in GitHub Desktop.
Big Integer Index Calculus till RREF using FLINT and LibGMP in C. Needs FLINT 3.4 or greater for fmpz_mod_mat
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ////Complete walkthrough: https://leetarxiv.substack.com/p/row-reduction-over-finite-fields | |
| #include <stdio.h> | |
| #include <stdint.h> | |
| #include <string.h> | |
| #include <stdlib.h> | |
| #include <assert.h> | |
| #include <stdbool.h> | |
| #include <time.h> | |
| #include <math.h> | |
| #include <gmp.h> | |
| #include <flint/flint.h> | |
| #include <flint/fmpz.h> | |
| #include <flint/fmpz_factor.h> | |
| #include <flint/fmpz_mod_mat.h> | |
| #include <flint/fmpz_mod.h> | |
| #define STB_DS_IMPLEMENTATION | |
| #include "stb_ds.h" | |
| //clear && gcc FMPZ_IndexCalculus.c -lm -lflint -lgmp -lmpfr -o m.o && ./m.o | |
| struct system_struct | |
| { | |
| fmpz_t prime; | |
| fmpz_t primeMinusOne; | |
| fmpz_t primitiveRoot; | |
| fmpz_t temp0; | |
| fmpz_t temp1; | |
| flint_rand_t randomState; | |
| fmpz_factor_t factorization; | |
| fmpz_mod_ctx_t moduloContext; | |
| fmpz_mod_mat_t rrefSolver; | |
| fmpz_mod_mat_t relations; | |
| fmpz_t **crtSolutions; | |
| fmpz_t *crtDividends; | |
| fmpz_t *crtInverses; | |
| fmpz_t *combinedCRT; | |
| int smoothnessBound; | |
| int factorBaseLength; | |
| int extraRelations; | |
| int *factorBase; | |
| int *primitiveRoots; | |
| slong *rank; | |
| }; | |
| typedef struct system_struct System[1]; | |
| double OdlyzkoBound(int N) | |
| { | |
| double logBase2 = (double) N; | |
| double c = 1 / (4 * log(2)); | |
| c = sqrt(c); | |
| double B = c * sqrt(logBase2 * log(logBase2)); | |
| B = pow(2, B); | |
| return B; | |
| } | |
| bool FindGenerator(fmpz_t testGenerator, fmpz_t prime, fmpz_t primeMinusOne, fmpz_factor_t factorization) | |
| { | |
| bool result = false; | |
| fmpz_t testResult, exponent; | |
| fmpz_init(testResult); | |
| fmpz_init(exponent); | |
| for(slong i = 0; i < factorization->num; i++) | |
| { | |
| fmpz_divexact(exponent, primeMinusOne, &factorization->p[i]); | |
| fmpz_powm(testResult, testGenerator, exponent, prime); | |
| if(fmpz_cmp_ui(testResult, 1) == 0) | |
| { | |
| result = false; | |
| fmpz_clear(exponent); | |
| fmpz_clear(testResult); | |
| return result; | |
| } | |
| } | |
| fmpz_clear(exponent); | |
| fmpz_clear(testResult); | |
| result = true; | |
| return result; | |
| } | |
| void System_CreateFactorBase(System system) | |
| { | |
| mpz_t prime,current; | |
| mpz_inits(prime,current,NULL); | |
| int primeHolder = 0; | |
| int count = 0; | |
| mpz_set_ui(prime,1); | |
| if(system->factorBaseLength == 0) | |
| { | |
| while(primeHolder < system->smoothnessBound) | |
| { | |
| mpz_nextprime(prime, prime); | |
| primeHolder = mpz_get_ui(prime); | |
| arrput(system->factorBase, primeHolder); | |
| system->factorBaseLength += 1; | |
| } | |
| system->smoothnessBound = system->factorBase[system->factorBaseLength - 1]; | |
| system->factorBaseLength = arrlen(system->factorBase); | |
| } | |
| else | |
| { | |
| while(count < system->factorBaseLength) | |
| { | |
| mpz_nextprime(prime, prime); | |
| primeHolder = mpz_get_ui(prime); | |
| system->smoothnessBound = primeHolder; | |
| arrput(system->factorBase, primeHolder); | |
| count += 1; | |
| } | |
| } | |
| assert(arrlen(system->factorBase) == system->factorBaseLength); | |
| mpz_clears(prime,current,NULL); | |
| } | |
| void System_InitFromInteger(System system, int prime, int smoothnessBound, int primitiveRootCount, int factorBaseLength, int extraRelations) | |
| { | |
| assert(prime > 0); | |
| assert(primitiveRootCount > 0); | |
| assert(extraRelations > 0); | |
| system->smoothnessBound = (int)ceil(OdlyzkoBound(log2(prime))); | |
| if(smoothnessBound > 0){system->smoothnessBound = smoothnessBound;} | |
| system->factorBaseLength = factorBaseLength; | |
| system->extraRelations = extraRelations; | |
| system->factorBase = NULL; | |
| system->primitiveRoots = NULL; | |
| fmpz_init(system->prime); | |
| fmpz_init(system->primeMinusOne); | |
| fmpz_init(system->primitiveRoot); | |
| fmpz_init(system->temp0); | |
| fmpz_init(system->temp1); | |
| flint_rand_init(system->randomState); | |
| fmpz_factor_init(system->factorization); | |
| fmpz_set_ui(system->prime, prime); | |
| fmpz_sub_ui(system->primeMinusOne,system->prime, 1); | |
| fmpz_factor(system->factorization, system->primeMinusOne); | |
| System_CreateFactorBase(system); | |
| fmpz_mod_ctx_init(system->moduloContext, system->primeMinusOne); | |
| fmpz_mod_mat_init(system->relations, arrlen(system->factorBase) + system->extraRelations, arrlen(system->factorBase) + 1, system->moduloContext); | |
| fmpz_mod_mat_init(system->rrefSolver, arrlen(system->factorBase) + system->extraRelations, arrlen(system->factorBase) + 1, system->moduloContext); | |
| //Find primitive roots | |
| bool isPrimitiveRoot = false; | |
| for(int i = 3; i < 10000; i++) | |
| { | |
| fmpz_set_ui(system->primitiveRoot, i); | |
| isPrimitiveRoot = FindGenerator(system->primitiveRoot, system->prime, system->primeMinusOne, system->factorization); | |
| if(isPrimitiveRoot) | |
| { | |
| arrput(system->primitiveRoots, i); | |
| primitiveRootCount -= 1; | |
| if(primitiveRootCount == 0){break;} | |
| } | |
| } | |
| //Create rank and crt holders | |
| system->rank = calloc(system->factorization->num, sizeof(slong)); | |
| system->crtSolutions = malloc(system->factorization->num * sizeof(fmpz_t *)); | |
| for(slong i = 0; i < system->factorization->num; i++) | |
| { | |
| system->crtSolutions[i] = malloc(arrlen(system->factorBase) * sizeof(fmpz_t)); | |
| for(int j = 0; j < arrlen(system->factorBase); j++) | |
| { | |
| fmpz_init(system->crtSolutions[i][j]); | |
| } | |
| } | |
| system->combinedCRT = malloc(arrlen(system->factorBase) * sizeof(fmpz_t)); | |
| for(int j = 0; j < arrlen(system->factorBase); j++) | |
| { | |
| fmpz_init(system->combinedCRT[j]); | |
| } | |
| system->crtDividends = malloc(system->factorization->num * sizeof(fmpz_t)); | |
| system->crtInverses = malloc(system->factorization->num * sizeof(fmpz_t)); | |
| for(int i = 0; i < system->factorization->num; i++) | |
| { | |
| fmpz_init(system->crtDividends[i]); | |
| fmpz_init(system->crtInverses[i]); | |
| fmpz_divexact(system->crtDividends[i], system->primeMinusOne, &system->factorization->p[i]); | |
| fmpz_invmod(system->crtInverses[i], system->crtDividends[i],&system->factorization->p[i]); | |
| } | |
| } | |
| void CollectDiscreteLogRelations(System system, int primitiveRootIndex) | |
| { | |
| int trialsMax = 10000; | |
| int trials = trialsMax; | |
| int found = 0; | |
| assert(primitiveRootIndex > -1); | |
| assert(primitiveRootIndex < arrlen(system->primitiveRoots)); | |
| fmpz_set_ui(system->primitiveRoot, system->primitiveRoots[primitiveRootIndex]); | |
| fmpz_mod_ctx_set_modulus(system->moduloContext, system->primeMinusOne); | |
| while(found < arrlen(system->factorBase) + system->extraRelations && trialsMax > -1) | |
| { | |
| bool foundSmooth = false; | |
| while(!foundSmooth && trials > -1) | |
| { | |
| fmpz_randm(system->temp1, system->randomState, system->primeMinusOne); | |
| fmpz_mod_set_fmpz(fmpz_mod_mat_entry(system->relations, found, arrlen(system->factorBase)), system->temp1, system->moduloContext); | |
| fmpz_powm(system->temp0, system->primitiveRoot, system->temp1, system->prime); | |
| for(size_t j = 0; j < arrlen(system->factorBase); j++) | |
| { | |
| int power = 0; | |
| while(fmpz_mod_ui(system->temp1,system->temp0, system->factorBase[j]) == 0) | |
| { | |
| fmpz_set_ui(system->temp1, system->factorBase[j]); | |
| fmpz_divexact(system->temp0, system->temp0, system->temp1); | |
| power += 1; | |
| } | |
| fmpz_mod_set_ui(fmpz_mod_mat_entry(system->relations, found, j), power, system->moduloContext); | |
| } | |
| if(fmpz_cmp_ui(system->temp0, 1) == 0) | |
| { | |
| foundSmooth = true; | |
| found += 1; | |
| break; | |
| } | |
| trials -= 1; | |
| } | |
| trialsMax -= 1; | |
| } | |
| if(found != arrlen(system->factorBase) + system->extraRelations ) | |
| { | |
| assert(found == arrlen(system->factorBase) + system->extraRelations); | |
| } | |
| } | |
| void System_FindRREF(System system) | |
| { | |
| for(slong i = 0; i < system->factorization->num; i++) | |
| { | |
| fmpz_mod_ctx_set_modulus(system->moduloContext, system->primeMinusOne); | |
| fmpz_mod_mat_set_fmpz_mat(system->rrefSolver, system->relations, system->moduloContext); | |
| fmpz_mod_ctx_set_modulus(system->moduloContext, &system->factorization->p[i]); | |
| _fmpz_mod_mat_reduce(system->rrefSolver, system->moduloContext); | |
| system->rank[i] = fmpz_mod_mat_rref(system->rrefSolver, system->rrefSolver, system->moduloContext); | |
| if(system->rank[i] != arrlen(system->factorBase)) | |
| { | |
| printf("Maybe increase no. of relations(Rank: %lu, FactorBase: %lu)\n", system->rank[i], arrlen(system->factorBase)); | |
| assert(system->rank[i] == arrlen(system->factorBase)); | |
| } | |
| else | |
| { | |
| for(size_t j = 0; j < arrlen(system->factorBase); j++) | |
| { | |
| fmpz_set(system->crtSolutions[i][j], fmpz_mod_mat_entry(system->rrefSolver, j, arrlen(system->factorBase))); | |
| } | |
| } | |
| } | |
| //Combine solutions without lifting (assumes all powers are 1) | |
| for(size_t i = 0; i < arrlen(system->factorBase); i++) | |
| { | |
| fmpz_set_ui(system->combinedCRT[i], 0); | |
| for(slong j = 0; j < system->factorization->num; j++) | |
| { | |
| fmpz_mul(system->temp0, system->crtInverses[j], system->crtDividends[j]); | |
| fmpz_mul(system->temp0, system->temp0, system->crtSolutions[j][i]); | |
| fmpz_add(system->combinedCRT[i], system->combinedCRT[i], system->temp0); | |
| } | |
| fmpz_mod(system->combinedCRT[i], system->combinedCRT[i], system->primeMinusOne); | |
| } | |
| } | |
| void System_Clear(System system) | |
| { | |
| fmpz_clear(system->prime); | |
| fmpz_clear(system->primeMinusOne); | |
| fmpz_clear(system->primitiveRoot); | |
| fmpz_clear(system->temp0); | |
| fmpz_clear(system->temp1); | |
| flint_rand_clear(system->randomState); | |
| fmpz_factor_clear(system->factorization); | |
| fmpz_mod_mat_clear(system->relations, system->moduloContext); | |
| fmpz_mod_mat_clear(system->rrefSolver, system->moduloContext); | |
| fmpz_mod_ctx_clear(system->moduloContext); | |
| for(int j = 0; j < arrlen(system->factorBase); j++) | |
| { | |
| fmpz_clear(system->combinedCRT[j]); | |
| } | |
| free(system->combinedCRT); | |
| arrfree(system->factorBase); | |
| arrfree(system->primitiveRoots); | |
| free(system->rank); | |
| for(slong i = 0; i < system->factorization->num; i++) | |
| { | |
| for(int j = 0; j < arrlen(system->factorBase); j++) | |
| { | |
| fmpz_clear(system->crtSolutions[i][j]); | |
| } | |
| free(system->crtSolutions[i]); | |
| } | |
| free(system->crtSolutions); | |
| for(int i = 0; i < system->factorization->num; i++) | |
| { | |
| fmpz_clear(system->crtDividends[i]); | |
| fmpz_clear(system->crtInverses[i]); | |
| } | |
| free(system->crtDividends); | |
| free(system->crtInverses); | |
| } | |
| void System_PrintIntArray(int length, int *array) | |
| { | |
| for(int i = 0; i < length; i++) | |
| { | |
| printf("%3d, ", array[i]); | |
| } | |
| printf("\n"); | |
| } | |
| void PrintSystem(System system) | |
| { | |
| printf("Prime: ");fmpz_print(system->prime);printf("\n"); | |
| printf("Prime-1: ");fmpz_print(system->primeMinusOne);printf("\n"); | |
| printf("Factorization: "); | |
| for(slong i = 0; i < system->factorization->num; i++) | |
| { | |
| printf("("); | |
| fmpz_print(&system->factorization->p[i]); printf(" ^ "); | |
| fmpz_print(&system->factorization->exp[i]); printf(")"); | |
| } | |
| printf("\n"); | |
| printf("Primitive Roots:["); | |
| for(size_t i = 0; i < arrlen(system->primitiveRoots); i++) | |
| { | |
| printf("%3d, ",system->primitiveRoots[i]); | |
| } | |
| printf("]\n"); | |
| printf("SmoothnessBound: %d\n",system->smoothnessBound); | |
| printf("Factor Base (length %d): [", system->factorBaseLength); | |
| for(size_t i = 0; i < arrlen(system->factorBase); i++) | |
| { | |
| printf("%3d, ",system->factorBase[i]); | |
| } | |
| printf("]\n"); | |
| printf("Current Primitive root: ");fmpz_print(system->primitiveRoot);printf("\n"); | |
| printf("Relations\n"); | |
| for(size_t i = 0; i < arrlen(system->factorBase) + system->extraRelations; i++) | |
| { | |
| printf("["); | |
| for(size_t j = 0; j < arrlen(system->factorBase) + 1; j++) | |
| { | |
| fmpz_print(fmpz_mod_mat_entry(system->relations, i, j));printf(", "); | |
| } | |
| printf("],\n"); | |
| } | |
| printf("CRT Solutions\n"); | |
| for(slong i = 0; i < system->factorization->num; i++) | |
| { | |
| printf("(");fmpz_print(&system->factorization->p[i]); printf(" ^ ");fmpz_print(&system->factorization->exp[i]); printf(") | "); | |
| for(size_t j = 0; j < arrlen(system->factorBase); j++) | |
| { | |
| fmpz_print(system->crtSolutions[i][j]);printf(", "); | |
| } | |
| printf("\n"); | |
| } | |
| printf("Final solution\n"); | |
| for(size_t i = 0; i < arrlen(system->factorBase); i++) | |
| { | |
| fmpz_print(system->combinedCRT[i]);printf(", "); | |
| } | |
| printf("\n"); | |
| } | |
| void TestSystem() | |
| { | |
| System chap3; | |
| int prime = 100003; | |
| int smoothnessBound = 100; | |
| int primitiveRootCount = 20; | |
| int factorBaseLength = 10; | |
| int extraRelations = 25; | |
| int primitiveRootIndex = 5; | |
| System_InitFromInteger(chap3, prime, smoothnessBound, primitiveRootCount,factorBaseLength, extraRelations); | |
| CollectDiscreteLogRelations(chap3, primitiveRootIndex); | |
| System_FindRREF(chap3); | |
| PrintSystem(chap3); | |
| System_Clear(chap3); | |
| } | |
| int main() | |
| { | |
| TestSystem(); | |
| flint_cleanup(); | |
| return 0; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Complete SageMath solution for RREF modulo composite numbers | |
| # Now works for any composite modulus | |
| def hensel_lift_matrix(M_p, p, k): | |
| """ | |
| Lift a matrix from mod p to mod p^k using proper Hensel lifting | |
| """ | |
| rows, cols = M_p.dimensions() | |
| # Convert to integers for lifting | |
| M_int = matrix(ZZ, [[int(x) for x in row] for row in M_p.rows()]) | |
| # For RREF, we need to be careful about pivots | |
| # This is a simplified approach - in practice, you'd solve the system properly | |
| M_pk = copy(M_int) | |
| # Reduce modulo p^k | |
| M_pk_mod = M_pk.change_ring(IntegerModRing(p^k)) | |
| return M_pk_mod | |
| def modular_rref_composite(M, modulus): | |
| """ | |
| Compute RREF modulo a composite number by factoring and CRT | |
| """ | |
| print(f"Computing RREF modulo {modulus}") | |
| # Factor the modulus | |
| factors = factor(modulus) | |
| print(f"Modulus factors: {list(factors)}") | |
| moduli_solutions = {} | |
| for p, k in factors: | |
| p_k = p^k | |
| print(f"\n=== Solving modulo {p}^{k} = {p_k} ===") | |
| if k == 1: | |
| # Prime modulus - use GF(p) | |
| try: | |
| M_p = Matrix(GF(p), [[int(x) for x in row] for row in M.rows()]) | |
| rref_p = M_p.rref() | |
| moduli_solutions[p_k] = rref_p | |
| print(f"RREF mod {p}:") | |
| print(rref_p) | |
| print(f"Rank mod {p}: {rref_p.rank()}") | |
| except Exception as e: | |
| print(f"Error solving mod {p}: {e}") | |
| # Fallback: use echelon form | |
| M_p = Matrix(IntegerModRing(p), [[int(x) for x in row] for row in M.rows()]) | |
| rref_p = M_p.echelon_form() | |
| moduli_solutions[p_k] = rref_p | |
| print(f"Echelon form mod {p} (fallback):") | |
| print(rref_p) | |
| else: | |
| # Prime power modulus | |
| try: | |
| # Try direct echelon form for prime powers | |
| M_pk = Matrix(IntegerModRing(p_k), [[int(x) for x in row] for row in M.rows()]) | |
| rref_pk = M_pk.echelon_form() | |
| moduli_solutions[p_k] = rref_pk | |
| print(f"Echelon form mod {p}^{k}:") | |
| print(rref_pk) | |
| except Exception as e: | |
| print(f"Error solving mod {p}^{k}: {e}") | |
| # Fallback: use Hensel lifting from mod p | |
| M_p = Matrix(GF(p), [[int(x) for x in row] for row in M.rows()]) | |
| rref_p = M_p.rref() | |
| print(f"RREF mod {p} (base for lifting):") | |
| print(rref_p) | |
| # Lift to mod p^k | |
| rref_pk = hensel_lift_matrix(rref_p, p, k) | |
| moduli_solutions[p_k] = rref_pk | |
| print(f"Lifted RREF mod {p}^{k}:") | |
| print(rref_pk) | |
| # Combine using CRT | |
| if len(moduli_solutions) == 0: | |
| print("No solutions found for any modulus!") | |
| return None | |
| print(f"\n=== Combining {len(moduli_solutions)} solutions using CRT ===") | |
| final_rref = combine_crt_solutions(moduli_solutions, modulus) | |
| return final_rref | |
| def combine_crt_solutions(solutions_dict, modulus): | |
| """ | |
| Combine solutions from different moduli using CRT | |
| """ | |
| moduli = list(solutions_dict.keys()) | |
| if len(moduli) == 1: | |
| return solutions_dict[moduli[0]] | |
| # For matrix CRT, we combine element-wise | |
| sample_sol = solutions_dict[moduli[0]] | |
| rows, cols = sample_sol.dimensions() | |
| result = matrix(ZZ, rows, cols) | |
| for i in range(rows): | |
| for j in range(cols): | |
| residues = [] | |
| mods = [] | |
| for m in moduli: | |
| sol_m = solutions_dict[m] | |
| residues.append(int(sol_m[i,j])) | |
| mods.append(m) | |
| # Use CRT to combine | |
| try: | |
| combined_val = crt(residues, mods) | |
| result[i,j] = combined_val | |
| except Exception as e: | |
| print(f"CRT failed for element ({i},{j}): {e}") | |
| result[i,j] = 0 # Fallback | |
| # Reduce modulo the original modulus | |
| result_mod = result.change_ring(IntegerModRing(modulus)) | |
| return result_mod | |
| # Your test code | |
| modulus = 100002 | |
| matrix_rows = [ | |
| [7, 3, 0, 0, 0, 1, 0, 0, 0, 0, 7781, ], | |
| [8, 1, 0, 1, 1, 0, 0, 0, 0, 0, 3246, ], | |
| [1, 2, 2, 0, 2, 0, 0, 0, 0, 0, 7497, ], | |
| [4, 2, 0, 0, 0, 1, 0, 0, 0, 0, 10491, ], | |
| [1, 0, 0, 1, 2, 0, 0, 0, 0, 0, 86958, ], | |
| [1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 67290, ], | |
| [0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 33792, ], | |
| [10, 0, 1, 0, 0, 0, 0, 1, 0, 0, 94936, ], | |
| [4, 2, 1, 0, 1, 0, 0, 0, 0, 0, 21039, ], | |
| [0, 2, 0, 1, 1, 0, 0, 1, 0, 0, 90010, ], | |
| [0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 61328, ], | |
| [0, 0, 0, 2, 1, 0, 1, 0, 0, 0, 63056, ], | |
| [2, 2, 0, 1, 0, 0, 1, 0, 0, 0, 91681, ], | |
| [2, 0, 0, 1, 0, 0, 1, 0, 0, 1, 13288, ], | |
| [2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 10412, ], | |
| [0, 3, 0, 0, 0, 0, 2, 0, 0, 0, 16161, ], | |
| [1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 76914, ], | |
| [7, 1, 0, 0, 1, 0, 1, 0, 0, 0, 90440, ], | |
| [3, 2, 3, 0, 0, 0, 0, 0, 0, 0, 70954, ], | |
| [1, 0, 2, 2, 0, 0, 0, 0, 0, 0, 823, ], | |
| [0, 3, 0, 0, 1, 0, 0, 0, 0, 1, 49058, ], | |
| [0, 2, 3, 0, 0, 0, 0, 0, 1, 0, 68043, ], | |
| [3, 2, 0, 0, 0, 0, 0, 1, 1, 0, 21144, ], | |
| [0, 2, 0, 2, 0, 0, 0, 0, 0, 1, 60675, ], | |
| [1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 42563, ], | |
| [0, 1, 0, 0, 0, 0, 0, 0, 2, 1, 87658, ], | |
| [1, 1, 2, 2, 0, 1, 0, 0, 0, 0, 74025, ], | |
| [3, 1, 1, 0, 0, 1, 0, 1, 0, 0, 88135, ], | |
| [2, 0, 0, 0, 1, 1, 0, 0, 0, 0, 16913, ], | |
| [6, 2, 1, 0, 0, 1, 0, 0, 0, 0, 55950, ], | |
| [2, 0, 0, 0, 1, 0, 1, 0, 1, 0, 30238, ], | |
| [1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 34517, ], | |
| [3, 2, 1, 0, 1, 0, 0, 1, 0, 0, 10513, ], | |
| [0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 11081, ], | |
| [2, 1, 2, 0, 0, 0, 1, 1, 0, 0, 9826, ], | |
| ] | |
| print("Original augmented matrix:") | |
| M_original = matrix(ZZ, matrix_rows) | |
| print(f"Dimensions: {M_original.dimensions()}") | |
| print(f"Modulus: {modulus} = {factor(modulus)}") | |
| # First, let's check the rank over rationals | |
| print(f"\n=== QUICK RANK CHECK ===") | |
| coefficient_matrix = M_original[:, :8] | |
| constants = M_original[:, 8] | |
| print(f"Rank of coefficient matrix (QQ): {coefficient_matrix.rank()}") | |
| print(f"Rank of augmented matrix (QQ): {M_original.rank()}") | |
| # Now compute RREF | |
| final_rref = modular_rref_composite(M_original, modulus) | |
| if final_rref is not None: | |
| print(f"\n=== FINAL RESULT ===") | |
| print(f"RREF modulo {modulus}:") | |
| print(final_rref) | |
| # Analysis | |
| rows, cols = final_rref.dimensions() | |
| variables = cols - 1 | |
| print(f"\n=== SOLUTION ANALYSIS ===") | |
| print(f"Matrix dimensions: {rows} x {cols}") | |
| print(f"Variables: {variables}") | |
| # Check consistency | |
| consistent = True | |
| pivot_cols = [] | |
| current_row = 0 | |
| for i in range(rows): | |
| all_zero = True | |
| for j in range(variables): | |
| if final_rref[i,j] != 0: | |
| all_zero = False | |
| if current_row == i and final_rref[i,j] == 1: | |
| pivot_cols.append(j) | |
| current_row += 1 | |
| break | |
| if all_zero and final_rref[i, variables] != 0: | |
| print(f"Inconsistent equation in row {i}: 0 = {final_rref[i, variables]}") | |
| consistent = False | |
| if consistent: | |
| print("System is consistent") | |
| print(f"Pivot columns: {pivot_cols}") | |
| print(f"Free variables: {[j for j in range(variables) if j not in pivot_cols]}") | |
| print(f"Rank: {len(pivot_cols)}") | |
| else: | |
| print("System is inconsistent") | |
| else: | |
| print("Failed to compute RREF") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment