Multiplicative.c

From Polymath Wiki
Jump to navigationJump to search
/* --- The following code comes from C:\lcc\lib\wizard\textmode.tpl. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SIZE 400  // how many numbers the computer will look at;
                  // in principle, increasing this number makes the computer smarter

// our knowledge is encoded in the following array

int vals[SIZE+1]; // vals[i] = +a means f(i) = +f(a); vals[i] = -a means f(i) = -f(a).
int up[SIZE+1];  //  best known upper bound for f[1,n]
int low[SIZE+1];  // best known lower bound for f[1,n]

void deduce(void);
void exit_display(void);

int abs( int i )
 {
	 if (i > 0) return i;
	 else return -i;
 }

int sgn(int i)
 {
	  if (i > 0) return +1;
	  if (i < 0) return -1;
	  return 0;
 }

void init( void )
 {
	  int i;
	  int j;

	  vals[0] = 0;
	  up[0] = 0;
	  low[0] = 0;

	  for (i=1; i <= SIZE; i++)
		  {
			  vals[i] = i;
			  for (j=2; j<40; j++)
				  {
					  while (vals[i] % (j*j) == 0) vals[i] /= j*j;
				}
			  if (i % 2 == 0)
				  {
					  up[i] = 2; low[i] = -2;
					}
					else
						{
							up[i] = 1; low[i] = -1;
					}
		  }
 }

int modified=0;

void set( int p, int s )  // set f(p) = s
 {
	 int i;
	 int pred, sred;

	 // need to reduce f(p)=s to f(pred)=sred

	 if (vals[p] > 0)
		  {
			  pred = vals[p]; sred = s;
		  }
		 else
		  {
		      pred = -vals[p]; sred = -s;
	      }

	 if (vals[pred] == sred) return;

     if (vals[pred] == -sred)
		 {
			 printf("Contradiction! f(%d) = 1 and f(%d) = -1 (from f(%d)=%d)\n", pred, pred, p, s);
			 exit_display();
		 }

	 printf("Setting f(%d)=%d...\n",pred,sred);

	 for (i=1; i<SIZE; i++)
		 while (vals[i] % pred == 0)
			 {
				 vals[i] /= pred; vals[i] *= sred;
			 }

	 modified=1;
 }


void newup( int i, int new)  // add f[1,i] <= new to knowledge
 {
	 if (up[i] <= new) return;  // is redundant

	 if (low[i] > new)
		 {
			 printf("Contradiction! %d <= f[1,%d] <= %d\n", low[i], i, new);
			 exit_display();
		}

//     printf(" (up[%d] = %d)", i, new);

     up[i] = new;
     modified = 1;
 }

void newdown( int i, int new)  // add f[1,i] >= new to knowledge
 {
	 if (low[i] >= new) return; // is redundant

	 if (up[i] < new)
		 {
			 printf("Contradiction! %d >= f[1,%d] >= %d\n", up[i], i, new);
			 exit_display();
		}

 //   printf(" (low[%d] = %d)", i, new);

     low[i] = new;
     modified = 1;
 }


void cut(int i)   // we learn that f[1,i] = 0
{
	if (up[i] == 0 && low[i] == 0) return;

	if (up[i] < 0)
	 {
		printf("Contradiction! f[1,%d]=-2 but f(%d)=f(%d+1)\n", i, i, i);
		exit_display();
	}
	if (low[i] > 0)
	 {
		printf("Contradiction! f[1,%d]=+2 but f(%d)=f(%d+1)\n", i, i, i);
		exit_display();
	}

//	printf(" (cut[%d])", i);

	up[i]=0;
	low[i]=0;
	modified=1;
}


void deduce( void )  // make simple deductions based on existing knowledge
 {
	  int i, j;


	  do
		  {
			  printf("Deducing...\n");
			  modified = 0;

			  // begin forward scan to update up,low by deducing bounds on f[1,i] from f[1,i-1]

			  for (i=1; i < SIZE; i++)
				  if (abs(vals[i]) == 1)
					  {
						  newup(i, up[i-1]+vals[i]);
						  newdown(i, low[i-1]+vals[i]);
					  }
				   else
				      {
					      newup(i, up[i-1]+1);
					      newdown(i, low[i-1]-1);
					}

			  // begin backward scan to update up,low by deducing bounds on f[1,i-1] from f[1,i]

			  for (i=SIZE-1; i > 0; i--)
				  if (abs(vals[i]) == 1)
					  {
						  newup(i-1, up[i] - vals[i]);
						  newdown(i-1, low[i] - vals[i]);
					  }
				  else
					  {
						  newup(i-1, up[i] + 1);
						  newdown(i-1, low[i] - 1);
						}

			   // look for cuts  (though this is redundant from the previous two scans

			   for (i=1; i < SIZE; i++)
				   if (i % 2 == 1 && vals[i] == vals[i-1])
					   cut(i-1);

			   // look for peaks and troughs

			   for (i=1; i < SIZE-1; i++)
				 {
				   if (up[i] <= low[i-1])
					   set(i,-1);
				   if (low[i] >= up[i-1])
					   set(i, 1);
			     }

			   // look for multiplicativity opportunities
		  	   for (i=2; i <SIZE; i++)
				   for (j=2; j*i<SIZE; j++)
					 {
					   if (abs(vals[i]) == 1)
						   if (abs(vals[j]) == 1)
							  if (abs(vals[i*j]) > 1)
								{
								   printf("f(%d)=f(%d)f(%d)=%d... ", i*j,i,j,vals[i]*vals[j]);
  				  	               set(i*j, vals[i]*vals[j]);
							    }

					   if (abs(vals[i])== 1)
						   if (abs(vals[i*j]) == 1)
							  if (abs(vals[j]) > 1)
								{
								   printf("f(%d)=f(%d)/f(%d)=%d... ", j,i*j,j,vals[i*j]*vals[i]);
  				  	               set(j, vals[i]*vals[i*j]);
							    }
					 }


		  }
       while(modified);
 }


void display( void )
 {
	int i;

	printf("\n");
   for (i=0; i < SIZE; i++)
	  {
		 if (up[i-1] == 0 && low[i-1] == 0) printf(" |");
		 else
			if (low[i-1] == 2) printf(" ^");
	     else
			if (up[i-1] == -2) printf(" v");
	     else printf("  ");

	     printf(" %4d", vals[i]);

		 if (i % 10 == 9) printf(" [%d-%d]\n", i-9,i);
	  }

	printf("\n");
  }

void exit_display(void)
 {
	 display();
	 exit(1);
 }


void main(int argc, char *argv[])
 {
	 int i, m;

	 init();
	 for (i=1; i < argc; i++)
		 {
			 m=0;
			 sscanf(argv[i],"%d",&m);
			 if (m==0)
				 {
					 printf("Arguments must be numbers!\n");
					 exit(0);
					}
			 set( abs(m), sgn(m) );
		}

	  deduce();
      display();
 }