1
+ # sage.doctest: optional - pycryptosat, needs sage.modules sage.rings.polynomial.pbori
1
2
"""
2
3
SAT Functions for Boolean Polynomials
3
4
@@ -71,7 +72,7 @@ def solve(F, converter=None, solver=None, n=1, target_variables=None, **kwds):
71
72
72
73
We construct a very small-scale AES system of equations::
73
74
74
- sage: sr = mq.SR(1,1,1,4, gf2=True,polybori=True)
75
+ sage: sr = mq.SR(1, 1, 1, 4, gf2=True, polybori=True)
75
76
sage: while True: # workaround (see :trac:`31891`)
76
77
....: try:
77
78
....: F, s = sr.polynomial_system()
@@ -81,74 +82,78 @@ def solve(F, converter=None, solver=None, n=1, target_variables=None, **kwds):
81
82
82
83
and pass it to a SAT solver::
83
84
84
- sage: from sage.sat.boolean_polynomials import solve as solve_sat # optional - pycryptosat
85
- sage: s = solve_sat(F) # optional - pycryptosat
86
- sage: F.subs(s[0]) # optional - pycryptosat
85
+ sage: from sage.sat.boolean_polynomials import solve as solve_sat
86
+ sage: s = solve_sat(F)
87
+ sage: F.subs(s[0])
87
88
Polynomial Sequence with 36 Polynomials in 0 Variables
88
89
89
90
This time we pass a few options through to the converter and the solver::
90
91
91
- sage: s = solve_sat(F, c_max_vars_sparse=4, c_cutting_number=8) # optional - pycryptosat
92
- sage: F.subs(s[0]) # optional - pycryptosat
92
+ sage: s = solve_sat(F, c_max_vars_sparse=4, c_cutting_number=8)
93
+ sage: F.subs(s[0])
93
94
Polynomial Sequence with 36 Polynomials in 0 Variables
94
95
95
- We construct a very simple system with three solutions and ask for a specific number of solutions::
96
+ We construct a very simple system with three solutions
97
+ and ask for a specific number of solutions::
96
98
97
- sage: B.<a,b> = BooleanPolynomialRing() # optional - pycryptosat
98
- sage: f = a*b # optional - pycryptosat
99
- sage: l = solve_sat([f],n=1) # optional - pycryptosat
100
- sage: len(l) == 1, f.subs(l[0]) # optional - pycryptosat
99
+ sage: B.<a,b> = BooleanPolynomialRing()
100
+ sage: f = a*b
101
+ sage: l = solve_sat([f],n=1)
102
+ sage: len(l) == 1, f.subs(l[0])
101
103
(True, 0)
102
104
103
- sage: l = solve_sat([a*b],n=2) # optional - pycryptosat
104
- sage: len(l) == 2, f.subs(l[0]), f.subs(l[1]) # optional - pycryptosat
105
+ sage: l = solve_sat([a*b],n=2)
106
+ sage: len(l) == 2, f.subs(l[0]), f.subs(l[1])
105
107
(True, 0, 0)
106
108
107
- sage: sorted((d[a], d[b]) for d in solve_sat([a*b],n=3)) # optional - pycryptosat
109
+ sage: sorted((d[a], d[b]) for d in solve_sat([a*b], n=3))
108
110
[(0, 0), (0, 1), (1, 0)]
109
- sage: sorted((d[a], d[b]) for d in solve_sat([a*b],n=4)) # optional - pycryptosat
111
+ sage: sorted((d[a], d[b]) for d in solve_sat([a*b], n=4))
110
112
[(0, 0), (0, 1), (1, 0)]
111
- sage: sorted((d[a], d[b]) for d in solve_sat([a*b],n=infinity)) # optional - pycryptosat
113
+ sage: sorted((d[a], d[b]) for d in solve_sat([a*b], n=infinity))
112
114
[(0, 0), (0, 1), (1, 0)]
113
115
114
116
In the next example we see how the ``target_variables`` parameter works::
115
117
116
- sage: from sage.sat.boolean_polynomials import solve as solve_sat # optional - pycryptosat
117
- sage: R.<a,b,c,d> = BooleanPolynomialRing() # optional - pycryptosat
118
- sage: F = [a+b,a+c+d] # optional - pycryptosat
118
+ sage: from sage.sat.boolean_polynomials import solve as solve_sat
119
+ sage: R.<a,b,c,d> = BooleanPolynomialRing()
120
+ sage: F = [a + b, a + c + d]
119
121
120
122
First the normal use case::
121
123
122
- sage: sorted((D[a], D[b], D[c], D[d]) for D in solve_sat(F,n=infinity)) # optional - pycryptosat
124
+ sage: sorted((D[a], D[b], D[c], D[d])
125
+ ....: for D in solve_sat(F, n=infinity))
123
126
[(0, 0, 0, 0), (0, 0, 1, 1), (1, 1, 0, 1), (1, 1, 1, 0)]
124
127
125
128
Now we are only interested in the solutions of the variables a and b::
126
129
127
- sage: solve_sat(F,n=infinity,target_variables=[a,b]) # optional - pycryptosat
130
+ sage: solve_sat(F, n=infinity, target_variables=[a,b])
128
131
[{b: 0, a: 0}, {b: 1, a: 1}]
129
132
130
133
Here, we generate and solve the cubic equations of the AES SBox (see :trac:`26676`)::
131
134
132
- sage: from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence # optional - pycryptosat, long time
133
- sage: from sage.sat.boolean_polynomials import solve as solve_sat # optional - pycryptosat, long time
134
- sage: sr = sage.crypto.mq.SR(1, 4, 4, 8, allow_zero_inversions = True) # optional - pycryptosat, long time
135
- sage: sb = sr.sbox() # optional - pycryptosat, long time
136
- sage: eqs = sb.polynomials(degree = 3) # optional - pycryptosat, long time
137
- sage: eqs = PolynomialSequence(eqs) # optional - pycryptosat, long time
138
- sage: variables = map(str, eqs.variables()) # optional - pycryptosat, long time
139
- sage: variables = ",".join(variables) # optional - pycryptosat, long time
140
- sage: R = BooleanPolynomialRing(16, variables) # optional - pycryptosat, long time
141
- sage: eqs = [R(eq) for eq in eqs] # optional - pycryptosat, long time
142
- sage: sls_aes = solve_sat(eqs, n = infinity) # optional - pycryptosat, long time
143
- sage: len(sls_aes) # optional - pycryptosat, long time
135
+ sage: # long time
136
+ sage: from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence
137
+ sage: from sage.sat.boolean_polynomials import solve as solve_sat
138
+ sage: sr = sage.crypto.mq.SR(1, 4, 4, 8,
139
+ ....: allow_zero_inversions=True)
140
+ sage: sb = sr.sbox()
141
+ sage: eqs = sb.polynomials(degree=3)
142
+ sage: eqs = PolynomialSequence(eqs)
143
+ sage: variables = map(str, eqs.variables())
144
+ sage: variables = ",".join(variables)
145
+ sage: R = BooleanPolynomialRing(16, variables)
146
+ sage: eqs = [R(eq) for eq in eqs]
147
+ sage: sls_aes = solve_sat(eqs, n=infinity)
148
+ sage: len(sls_aes)
144
149
256
145
150
146
151
TESTS:
147
152
148
153
Test that :trac:`26676` is fixed::
149
154
150
155
sage: varl = ['k{0}'.format(p) for p in range(29)]
151
- sage: B = BooleanPolynomialRing(names = varl)
156
+ sage: B = BooleanPolynomialRing(names= varl)
152
157
sage: B.inject_variables(verbose=False)
153
158
sage: keqs = [
154
159
....: k0 + k6 + 1,
@@ -162,7 +167,7 @@ def solve(F, converter=None, solver=None, n=1, target_variables=None, **kwds):
162
167
....: k9 + k28,
163
168
....: k11 + k20]
164
169
sage: from sage.sat.boolean_polynomials import solve as solve_sat
165
- sage: solve_sat(keqs, n=1, solver=SAT('cryptominisat')) # optional - pycryptosat
170
+ sage: solve_sat(keqs, n=1, solver=SAT('cryptominisat'))
166
171
[{k28: 0,
167
172
k26: 1,
168
173
k24: 0,
@@ -187,7 +192,7 @@ def solve(F, converter=None, solver=None, n=1, target_variables=None, **kwds):
187
192
k2: 0,
188
193
k1: 0,
189
194
k0: 0}]
190
- sage: solve_sat(keqs, n=1, solver=SAT('picosat')) # optional - pycosat
195
+ sage: solve_sat(keqs, n=1, solver=SAT('picosat')) # optional - pycosat
191
196
[{k28: 0,
192
197
k26: 1,
193
198
k24: 0,
@@ -336,16 +341,16 @@ def learn(F, converter=None, solver=None, max_learnt_length=3, interreduction=Fa
336
341
337
342
EXAMPLES::
338
343
339
- sage: from sage.sat.boolean_polynomials import learn as learn_sat # optional - pycryptosat
344
+ sage: from sage.sat.boolean_polynomials import learn as learn_sat
340
345
341
346
We construct a simple system and solve it::
342
347
343
- sage: set_random_seed(2300) # optional - pycryptosat
344
- sage: sr = mq.SR(1,2,2,4, gf2=True,polybori=True) # optional - pycryptosat
345
- sage: F,s = sr.polynomial_system() # optional - pycryptosat
346
- sage: H = learn_sat(F) # optional - pycryptosat
347
- sage: H[-1] # optional - pycryptosat
348
- k033 + 1
348
+ sage: set_random_seed(2300)
349
+ sage: sr = mq.SR(1, 2, 2, 4, gf2=True, polybori=True)
350
+ sage: F,s = sr.polynomial_system()
351
+ sage: H = learn_sat(F)
352
+ sage: H[-1]
353
+ k033 + 1
349
354
"""
350
355
try :
351
356
len (F )
0 commit comments