23
23
ConjectureData ,
24
24
ConjectureResult ,
25
25
Status ,
26
- bits_to_bytes ,
27
26
ir_value_equal ,
28
27
ir_value_key ,
29
28
ir_value_permitted ,
@@ -681,7 +680,7 @@ def greedy_shrink(self):
681
680
"reorder_examples" ,
682
681
"minimize_duplicated_nodes" ,
683
682
"minimize_individual_nodes" ,
684
- "redistribute_block_pairs " ,
683
+ "redistribute_integer_pairs " ,
685
684
"lower_blocks_together" ,
686
685
]
687
686
)
@@ -1227,42 +1226,32 @@ def minimize_duplicated_nodes(self, chooser):
1227
1226
self .minimize_nodes (nodes )
1228
1227
1229
1228
@defines_shrink_pass ()
1230
- def redistribute_block_pairs (self , chooser ):
1229
+ def redistribute_integer_pairs (self , chooser ):
1231
1230
"""If there is a sum of generated integers that we need their sum
1232
1231
to exceed some bound, lowering one of them requires raising the
1233
1232
other. This pass enables that."""
1233
+ # TODO_SHRINK let's extend this to floats as well.
1234
1234
1235
- node = chooser .choose (
1235
+ # look for a pair of nodes (node1, node2) which are both integers and
1236
+ # aren't separated by too many other nodes. We'll decrease node1 and
1237
+ # increase node2 (note that the other way around doesn't make sense as
1238
+ # it's strictly worse in the ordering).
1239
+ node1 = chooser .choose (
1236
1240
self .nodes , lambda node : node .ir_type == "integer" and not node .trivial
1237
1241
)
1242
+ node2 = chooser .choose (
1243
+ self .nodes ,
1244
+ lambda node : node .ir_type == "integer"
1245
+ # Note that it's fine for node2 to be trivial, because we're going to
1246
+ # explicitly make it *not* trivial by adding to its value.
1247
+ and not node .was_forced
1248
+ # to avoid quadratic behavior, scan ahead only a small amount for
1249
+ # the related node.
1250
+ and node1 .index < node .index <= node1 .index + 4 ,
1251
+ )
1238
1252
1239
- # The preconditions for this pass are that the two integer draws are only
1240
- # separated by non-integer nodes, and have the same size value in bytes.
1241
- #
1242
- # This isn't particularly principled. For instance, this wouldn't reduce
1243
- # e.g. @given(integers(), integers(), integers()) where the sum property
1244
- # involves the first and last integers.
1245
- #
1246
- # A better approach may be choosing *two* such integer nodes arbitrarily
1247
- # from the list, instead of conditionally scanning forward.
1248
-
1249
- for j in range (node .index + 1 , len (self .nodes )):
1250
- next_node = self .nodes [j ]
1251
- if next_node .ir_type == "integer" and bits_to_bytes (
1252
- node .value .bit_length ()
1253
- ) == bits_to_bytes (next_node .value .bit_length ()):
1254
- break
1255
- else :
1256
- return
1257
-
1258
- if next_node .was_forced :
1259
- # avoid modifying a forced node. Note that it's fine for next_node
1260
- # to be trivial, because we're going to explicitly make it *not*
1261
- # trivial by adding to its value.
1262
- return
1263
-
1264
- m = node .value
1265
- n = next_node .value
1253
+ m = node1 .value
1254
+ n = node2 .value
1266
1255
1267
1256
def boost (k ):
1268
1257
if k > m :
@@ -1272,11 +1261,11 @@ def boost(k):
1272
1261
next_node_value = n + k
1273
1262
1274
1263
return self .consider_new_tree (
1275
- self .nodes [: node .index ]
1276
- + [node .copy (with_value = node_value )]
1277
- + self .nodes [node .index + 1 : next_node .index ]
1278
- + [next_node .copy (with_value = next_node_value )]
1279
- + self .nodes [next_node .index + 1 :]
1264
+ self .nodes [: node1 .index ]
1265
+ + [node1 .copy (with_value = node_value )]
1266
+ + self .nodes [node1 .index + 1 : node2 .index ]
1267
+ + [node2 .copy (with_value = next_node_value )]
1268
+ + self .nodes [node2 .index + 1 :]
1280
1269
)
1281
1270
1282
1271
find_integer (boost )
0 commit comments