Depth-first search for multiplicative sequences: Difference between revisions
From Polymath Wiki
Jump to navigationJump to search
New page: This C program performs depth-first search for multiplicative sequences. In the source code, define N to be the limit of your search and C to be the limit on discrepancy. You also need to... |
(No difference)
|
Revision as of 05:16, 6 February 2010
This C program performs depth-first search for multiplicative sequences.
In the source code, define N to be the limit of your search and C to be the limit on discrepancy. You also need to set MAX_N_PRIMES and MAX_N_DIVISORS (but you'll be prompted to do so if they aren't high enough).
The initial mapping of primes (f) is set within the main program: edit to taste! f[i] = true means that f maps the ith prime to -1, where the 0th prime is 2.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifndef _WIN32
# include <stdbool.h>
#else
# define bool char
# define true 1
# define false 0
#endif
#define N 3000 // limit of search
#define MAX_N_PRIMES 600
#define MAX_N_DIVISORS 600
#define C 3 // limit on sums
static unsigned int primes[MAX_N_PRIMES];
static unsigned int n_primes;
static bool is_prime[N+1];
static bool a[N+1][MAX_N_PRIMES]; // table of factorizations
static unsigned int s[N+1][MAX_N_DIVISORS]; // s[n] = list of divisors of n
static unsigned int l[N+1]; // l[n] = number of divisors of n
static bool f[MAX_N_PRIMES], g[MAX_N_PRIMES]; // f = initital values, g = values under test, true = sends to -1
static char x[N+1]; // sequence under test
static tot[N+1]; // totals table
static void seq(unsigned int M) { // calculate x corresponding to g, up to and including M
unsigned int n, i;
bool *fact;
char v = 1;
for (n = 1; n <= M; n++) {
fact = a[n];
for (i = 0; i < n_primes; i++) if (fact[i] && g[i]) v = -v;
x[n] = v;
}
}
static bool update_x(unsigned int i) { // update x from primes[i] to primes[i+1]-1, if discrep OK, return false if not
bool ok = true;
bool *fact;
char v;
unsigned int p1 = primes[i+1];
unsigned int n = primes[i];
unsigned int j;
char tt;
while ((n < p1) && ok) {
fact = a[n];
v = 1;
for (j = 0; j <= i; j++) if (fact[j] && g[j]) v = -v;
x[n] = v;
tt = tot[n-1] + x[n];
if (abs(tt) <= C) tot[n] = tt;
else ok = false;
n++;
}
return ok;
}
static void print_seq(FILE *fp, char *seq, unsigned int n) {
unsigned int j;
fprintf(fp, "\n ");
for (j = 1; j<=n; j++) {
fprintf(fp, "%s", (seq[j] == 1) ? "+" : "-");
if (j%81==0) fprintf(fp, "\n ");
}
fprintf(fp, "\n");
}
static bool check(char *seq, unsigned int n) {
bool ok = true;
unsigned int d = 1;
while ((d <= n) && ok) {
unsigned int i = d;
char tot = 0;
while ((i <= n) && ok) {
tot += seq[i];
if (abs(tot) > C) ok = false;
i += d;
}
d++;
}
return ok;
}
int main(int argc, char *argv[]) {
unsigned int i, max_i, min_back, max_fwd, next_g_i, n1, i0;
bool hope, ok, more;
{ // use Eratosthenes to find primes up to N
unsigned int p = 2;
bool ok = true;
unsigned int i, index;
is_prime[0] = false;
is_prime[1] = false;
for (i = 2; i<=N; i++) is_prime[i] = true;
while (ok) {
unsigned int i, q;
bool found;
for (i = 2*p; i <= N; i += p) is_prime[i] = false;
q = p+1;
found = false;
while ((q <= N) && !found) {
if (is_prime[q]) {
found = true;
p = q;
n_primes++;
}
q++;
}
if (!found) ok = false;
}
if (n_primes > MAX_N_PRIMES) {
fprintf(stderr, "Aborting. Increase MAX_N_PRIMES to at least %d.\n", n_primes);
return -1;
}
index = 0;
for (i = 2; i <= N; i++) {
if (is_prime[i]) {
primes[index] = i;
index++;
}
}
}
{ // initialize divisors table
unsigned int n, d;
for (n = 1; n <= N; n++) {
unsigned int d_count = 0;
for (d = 1; d <= N; d++) {
if ((n%d) == 0) {
if (d_count > MAX_N_DIVISORS) {
fprintf(stderr, "Aborting. Increase MAX_N_DIVISORS to at least %d (n = %d).\n", d_count, n);
return -1;
}
s[n][d_count] = d;
d_count++;
}
}
l[n] = d_count;
}
}
{ // make table of factorizations
unsigned int n;
for (n = 1; n <= N; n++) {
unsigned int i, k = n;
for (i = 0; i < n_primes; i++) {
unsigned int p = primes[i];
bool v = false;
while (k % p == 0) {
v = !v;
k /= p;
}
a[n][i] = v;
}
}
}
{ // set initial values of f, g, x
unsigned int i, p;
for (i = 0; i < n_primes; i++) {
p = primes[i];
if (p==3) f[i] = true;
else f[i] = (p%3==2);
if ((p==709) || (p==881) || (p==1201) || (p==1697) || (p==1999) || (p==2837) || (p==3323) || (p==3457)) f[i] = !f[i];
}
for (i = 0; i < n_primes; i++) g[i] = f[i];
seq(N);
}
{ // initialize totals table, t[n] = x[1]+x[2]+...+x[n]
unsigned int n;
for (n = 0; n <= N; n++) tot[n] = 0;
tot[1] = x[1];
}
i = 0;
max_i = 0;
min_back = 0;
max_fwd = 0;
hope = true;
while ((i < n_primes) && hope) {
if (i < min_back) {
min_back = i;
max_fwd = min_back;
printf("%d ", primes[min_back]);
fflush(stdout);
}
ok = update_x(i);
if (!ok) {
if (g[i] == f[i]) {
g[i] = !f[i];
ok = update_x(i);
}
}
if (ok) {
//if (i > max_fwd) {
// max_fwd = i;
// printf(" %d", i);
//}
if (i > max_i) {
max_i = i;
min_back = max_i;
n1 = primes[i+1]-1;
printf("\n\nmax_i = %d\n", max_i);
printf("max_n = %d\n", n1);
printf("verify: %s\n", check(x, n1) ? "pass" : "fail");
print_seq(stdout, x, n1);
printf("primes sent to -1:\n");
for (i0 = 0; i0 <= i; i0++) if (g[i0]) printf("%d, ", primes[i0]);
printf("\n\nbacktracking...\n");
}
i++;
}
else /* backtrack */{
while (g[i] == !f[i]) {
g[i] = f[i];
i--;
}
g[i] = !f[i];
if ((i == 0) && (g[i] == f[i])) hope = false;
}
}
printf("\n\nEND\n");
return 0;
}