Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- This C (C++ compatible) program generates a satisfiable instance
- of a VMPC inversion problem, expressed as a SAT problem.
- Public domain. Author: François Grieu.
- Credits for the VMPC problem goes to Bartosz Zoltak, who
- proposed it in the field of cryptography, in (among other) a paper
- published at the conference Fast Software Encryption Conference
- (FSE 2004) held in Delhi, India, 5-7 Feb. 2004. See
- <http://www.vmpcfunction.com>
- 2004-03-24 FGR Comments further polished; simplified VMPC definitions.
- 2004-02-24 FGR No final comment line in the output; n default to 10.
- 2004-02-24 FGR Range of g is checked; comments polished.
- 2004-02-23 FGR Created.
- Syntax of this tool:
- sat_vmpc n [g [seed]]
- Parameter n determines the size of the problem.
- The SAT problem has n*n variables, and about 5*n*n*n clauses.
- All clauses (except 2*n+g) have either 2 or 3 variables.
- The optional parameter g makes the problem easier by giving
- away g variables using trivial clauses, which then trivialy
- expand to at least n*g given variables.
- Problem is written to standard output, with initial comments.
- To suppress hints at the solution from comments, use negative n.
- Based on experiments with ZChaff 2003.11.04, difficulty rating:
- sat_vmpc 10 trivial
- sat_vmpc 21 easy
- sat_vmpc 22 nice
- sat_vmpc 23 serious ( 69 s)
- sat_vmpc 23 0 1 just as serious, other seed (108 s)
- sat_vmpc 24 challenging
- sat_vmpc 25 1 easy
- sat_vmpc 43 4 nice
- sat_vmpc 50 5 nice
- sat_vmpc 80 10 4 serious ( 80 s)
- sat_vmpc 80 9 4 serious (147 s)
- For the purpose of SAT competition 2004, the author suggests
- values of n in range 5+3*g to 40+6*g, with g in range 0 to 10.
- The most interesting value of g is 0; many problems with g=0
- have several solutions; e.g.
- sat_vmpc 21
- Note: When n is 0, a special (huge) problem is generated;
- there is a $100 prize for solving it!
- This problem is approximately as hard as for n=256, g=24,
- and is believed untractable. For details see
- <http://www.vmpcfunction.com/trial.htm>
- Definition of the VMPC inversion problem:
- Let S be the set of nonnegative integers less than n.
- We are given a permutation Q on S, and want a permutation P with
- Q[x] = P[(P[P[x]]+1)%n]
- An instance of the VMPC inversion problem is satisfiable if a
- solution P exists.
- This is inherently a non-boolean satisfiability problem.
- The translation made here to boolean SAT is straightforward:
- it uses n * (n variables, one of which is set and n-1 are clear).
- */
- #include <limits.h>
- #include <stdlib.h>
- #include <stdio.h>
- /*
- find an at-least-32 bits type u32
- how to describe it to printf P32
- and mean to keep the low 32 bits L32()
- */
- #if UINT_MAX==0xFFFFFFFF
- typedef unsigned u32;
- #define P32
- #define L32(x) ((u32)(x))
- #else
- typedef unsigned long u32;
- #define P32 "l"
- #if ULONG_MAX==0xFFFFFFFF
- #define L32(x) ((u32)(x))
- #else
- #define L32(x) ((u32)(x)&0xFFFFFFFF)
- #endif
- #endif
- /*{ PRNG; fast, fully portable across machines, period of any bit at least 2^49-2^17, not crypto-quality */
- /* return an about uniformly distributed u32 */
- #define u32RNG() ((RNGA=L32((RNGA+1u)*0xA85ADDCDu)),(RNGB=(RNGB>>1)^(((RNGB|0xFFFFFFFEu)+1u)&0xD7626A57u))+(RNGA^(RNGA>>16)))
- /* for extra speed, a local rng context can be declared */
- #define u32RNGcontext u32 RNGA=0, RNGB=0
- /* else by default a global rng context is used */
- static u32RNGcontext;
- /* seed the RNG (optional) */
- #define SRNG(x) do RNGB=(RNGA=L32(x))&0x7FFFFFFFu; while(0)
- /*}*/
- /* type we use for most things, and how to describe it to printf */
- typedef int tNum;
- #define PNum "%4u"
- /* return a pseudorandom permutation on range [0..n-1] */
- void randperm(tNum P[],tNum n)
- {
- tNum j,g;
- for(j=0;j<n;++j)
- {
- g = u32RNG()%(j+1); /* not perfectly evenly distributed, but good enough */
- P[j] = P[g];
- P[g] = j;
- }
- }
- #define nmax 300
- #define ncha 256 /* size of the challenge */
- tNum P[nmax],Q[nmax],QC[ncha]={
- 61, 71, 49, 62, 52, 185, 214, 89, 156, 120, 240, 139, 172, 184, 43, 168,
- 74, 8, 132, 151, 83, 186, 159, 229, 23, 175, 112, 142, 75, 232, 204, 123,
- 12, 59, 73, 64, 225, 14, 161, 198, 68, 69, 92, 226, 63, 32, 87, 150, 178,
- 118, 245, 196, 45, 116, 255, 18, 46, 102, 179, 13, 136, 252, 154, 35, 70,
- 53, 169, 242, 72, 194, 10, 42, 19, 209, 121, 140, 86, 124, 80, 201, 137,
- 109, 114, 88, 106, 205, 11, 234, 157, 247, 129, 153, 28, 31, 238, 122, 202,
- 22, 103, 171, 37, 119, 166, 212, 182, 17, 91, 30, 216, 93, 101, 104, 0, 78,
- 141, 95, 107, 195, 1, 66, 41, 217, 237, 199, 165, 56, 143, 127, 100, 76,
- 117, 131, 193, 253, 167, 223, 38, 227, 113, 97, 206, 228, 130, 181, 221,
- 84, 236, 6, 211, 55, 33, 110, 177, 29, 27, 145, 96, 219, 249, 230, 40, 174,
- 105, 138, 85, 36, 243, 218, 9, 25, 4, 244, 250, 158, 149, 208, 188, 94,
- 146, 207, 111, 224, 203, 213, 125, 191, 7, 215, 200, 47, 148, 170, 26, 24,
- 34, 54, 57, 233, 192, 173, 44, 126, 98, 197, 3, 144, 128, 99, 134, 2, 58,
- 65, 133, 248, 241, 160, 152, 67, 164, 220, 183, 51, 239, 222, 189, 135,
- 155, 82, 210, 246, 187, 79, 190, 176, 81, 162, 39, 60, 50, 77, 254, 15,
- 180, 147, 251, 231, 16, 163, 90, 108, 48, 20, 115, 5, 21, 235
- };
- int main(int argc, char *argv[])
- {
- /* return the n-th argument with default value */
- #define arg(x,d) ((tNum)(((x)<argc&&argv[x]!=0&&*argv[x]!=0)?atol(argv[x]):(d)))
- tNum n,j,k,l,c,g;
- u32 s;
- char chal = 0; /* 1 for the challenge */
- char verb = 1; /* 1 for full comments */
- /* get parameters */
- n = arg(1,10);
- g = arg(2,0);
- s = arg(3,0);
- /* establish the VMPC problem */
- if (n<0)
- {
- n = -n;
- verb = 0;
- }
- if (n==0)
- {
- chal = 1;
- n = ncha;
- for(j=0;j<n;++j) P[j]=n;
- P[228]=86; P[86]=12; P[87]=35; P[240]=85; P[229]=137; P[252]=133; P[197]
- =187; P[129]=108; P[236]=80; P[156]=231; P[141]=152; P[158]=89; P[111]=97;
- P[29]=190; P[192]=236; P[232]=91; P[152]=62; P[248]=153; P[189]=45; P[182]
- =165; P[205]=25; P[119]=132; P[62]=130; P[7]=49; P[148]=181; P[42]=44; P
- [115]=16; P[167]=131; P[214]=158;
- s = g = 0;
- for(j=0;j<n;++j) g += P[j]!=n;
- }
- else
- {
- SRNG(s); /* seed the RNG */
- if (n>nmax) n = nmax;
- randperm(P,n);
- for(j=n;j--;)
- Q[j] = P[(P[P[j]]+1)%n];
- }
- if (g<0) g = 0;
- if (g>n) g = n;
- #define VP(a,b) ((a)*n+(b)+1) // variable true when P(a)==b
- /* initial comments */
- printf("c VMPC problem of size %u translated to SAT; %u entries revealed",n,g);
- if (verb)
- printf("; random seed %lu",s);
- printf("\nc "); for(j=0;j<n;++j) printf(PNum,j);
- if (verb || chal)
- {
- printf("\nc P "); for(j=0;j<n;++j) printf((chal&&P[j]==n)?" ? ":PNum,P[j]);
- }
- printf("\nc Q "); for(j=0;j<n;++j) printf(PNum,Q[j]);
- if (chal)
- printf("\nc Problem reportedly SAT, with $100 prize; see <http://www.vmpcfunction.com/trial.htm>");
- else
- {
- if (verb)
- {
- printf("\nc Problem is known SAT when true variables are:\nc");
- for(j=0;j<n;++j) printf(" %d",VP(j,P[j]));
- }
- }
- #define IMP2(X,Y) do if ((X)!=(Y)) printf("%d %d 0\n",-(X),(Y)); while(0) // clause for X => Y
- #define ANDIMP1(X,Y,Z) do if ((X)!=(Z) && (Y)!=(Z)) ++c; while(0) // clause for X&Y => Z
- #define ANDIMP2(X,Y,Z) do if ((X)!=(Z) && (Y)!=(Z)) if (X==Y) printf("%d %d 0\n",-(X),(Z)); else printf("%d %d %d 0\n",-(X),-(Y),(Z)); while(0) // clause for X&Y => Z
- /* precompute the number of clauses, which vary slightly */
- c = (n+n*n*(n-1))*2+g;
- for(j=0;j<n;++j)
- for(k=0;k<n;++k)
- for(l=0;l<n;++l)
- {
- ANDIMP1(VP(j,k),VP(k,l),VP((l+1)%n,Q[j]));
- ANDIMP1(VP(k,l),VP((l+1)%n,Q[j]),VP(j,k));
- ANDIMP1(VP((l+1)%n,Q[j]),VP(j,k),VP(k,l));
- }
- printf("\np cnf %d %d\n",n*n,c);
- /* giveaway variables */
- if (chal)
- {
- for(j=0;j<n;++j)
- if (P[j]!=n)
- printf("%d 0\n",VP(j,P[j]));
- }
- else
- for(j=0;j<g;++j)
- printf("%d 0\n",VP(j,P[j]));
- /* "at least one per row" clauses */
- for(j=0;j<n;++j)
- {
- for(k=0;k<n;++k)
- printf("%d ",VP(j,k));
- printf("0\n");
- }
- /* "at least one per column" clauses */
- for(k=0;k<n;++k)
- {
- for(j=0;j<n;++j)
- printf("%d ",VP(j,k));
- printf("0\n");
- }
- for(j=0;j<n;++j)
- for(k=0;k<n;++k)
- for(l=0;l<n;++l)
- {
- if (l!=k)
- IMP2(VP(j,k),-VP(j,l)); /* "at most one per row" clauses */
- if (l!=j)
- IMP2(VP(j,k),-VP(l,k)); /* "at most one per column" clauses */
- ANDIMP2(VP(j,k),VP(k,l),VP((l+1)%n,Q[j])); /* VMPC discovery rule 1 */
- ANDIMP2(VP(k,l),VP((l+1)%n,Q[j]),VP(j,k)); /* VMPC discovery rule 2 */
- ANDIMP2(VP((l+1)%n,Q[j]),VP(j,k),VP(k,l)); /* VMPC discovery rule 3 */
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment