Skip to content

Commit 90c227b

Browse files
flowKKohuanerw0608robin-aws
authored
fix: fix module Collections.Seq functions using a binary predicate (#6412)
Hi Robin(@robin-aws), the MaxBy() and MinBy() functionalties are using a comparator previously. To ensure precision, @huanerw0608 changed it to using a bianry predicate to replace the comparator functions. --------- Co-authored-by: huanerw0608 <[email protected]> Co-authored-by: Robin Salkeld <[email protected]>
1 parent 8be5c7d commit 90c227b

File tree

10 files changed

+32
-58
lines changed

10 files changed

+32
-58
lines changed

Source/DafnyCore/GeneratedFromDafny/Std_Collections_Seq.cs

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -191,49 +191,47 @@ public static Dafny.ISequence<__T> Repeat<__T>(__T v, BigInteger length)
191191
goto TAIL_CALL_START;
192192
}
193193
}
194-
public static __T MaxBy<__T>(Dafny.ISequence<__T> s, Func<__T, __T, BigInteger> comparator)
194+
public static __T MaxBy<__T>(Dafny.ISequence<__T> s, Func<__T, __T, bool> lessThan)
195195
{
196-
return Std.Collections.Seq.__default.MaxByHelper<__T>(s, BigInteger.One, (s).Select(BigInteger.Zero), comparator);
196+
return Std.Collections.Seq.__default.MaxByHelper<__T>(s, BigInteger.One, (s).Select(BigInteger.Zero), lessThan);
197197
}
198-
public static __T MaxByHelper<__T>(Dafny.ISequence<__T> s, BigInteger idx, __T current, Func<__T, __T, BigInteger> comparator)
198+
public static __T MaxByHelper<__T>(Dafny.ISequence<__T> s, BigInteger idx, __T current, Func<__T, __T, bool> lessThan)
199199
{
200200
TAIL_CALL_START: ;
201201
if ((idx) == (new BigInteger((s).Count))) {
202202
return current;
203203
} else {
204-
BigInteger _0_cmp = Dafny.Helpers.Id<Func<__T, __T, BigInteger>>(comparator)(current, (s).Select(idx));
205-
__T _1_next = (((_0_cmp).Sign == -1) ? ((s).Select(idx)) : (current));
204+
__T _0_next = ((Dafny.Helpers.Id<Func<__T, __T, bool>>(lessThan)(current, (s).Select(idx))) ? ((s).Select(idx)) : (current));
206205
Dafny.ISequence<__T> _in0 = s;
207206
BigInteger _in1 = (idx) + (BigInteger.One);
208-
__T _in2 = _1_next;
209-
Func<__T, __T, BigInteger> _in3 = comparator;
207+
__T _in2 = _0_next;
208+
Func<__T, __T, bool> _in3 = lessThan;
210209
s = _in0;
211210
idx = _in1;
212211
current = _in2;
213-
comparator = _in3;
212+
lessThan = _in3;
214213
goto TAIL_CALL_START;
215214
}
216215
}
217-
public static __T MinBy<__T>(Dafny.ISequence<__T> s, Func<__T, __T, BigInteger> comparator)
216+
public static __T MinBy<__T>(Dafny.ISequence<__T> s, Func<__T, __T, bool> lessThan)
218217
{
219-
return Std.Collections.Seq.__default.MinByHelper<__T>(s, BigInteger.One, (s).Select(BigInteger.Zero), comparator);
218+
return Std.Collections.Seq.__default.MinByHelper<__T>(s, BigInteger.One, (s).Select(BigInteger.Zero), lessThan);
220219
}
221-
public static __T MinByHelper<__T>(Dafny.ISequence<__T> s, BigInteger idx, __T current, Func<__T, __T, BigInteger> comparator)
220+
public static __T MinByHelper<__T>(Dafny.ISequence<__T> s, BigInteger idx, __T current, Func<__T, __T, bool> lessThan)
222221
{
223222
TAIL_CALL_START: ;
224223
if ((idx) == (new BigInteger((s).Count))) {
225224
return current;
226225
} else {
227-
BigInteger _0_cmp = Dafny.Helpers.Id<Func<__T, __T, BigInteger>>(comparator)(current, (s).Select(idx));
228-
__T _1_next = (((_0_cmp).Sign == 1) ? ((s).Select(idx)) : (current));
226+
__T _0_next = ((Dafny.Helpers.Id<Func<__T, __T, bool>>(lessThan)((s).Select(idx), current)) ? ((s).Select(idx)) : (current));
229227
Dafny.ISequence<__T> _in0 = s;
230228
BigInteger _in1 = (idx) + (BigInteger.One);
231-
__T _in2 = _1_next;
232-
Func<__T, __T, BigInteger> _in3 = comparator;
229+
__T _in2 = _0_next;
230+
Func<__T, __T, bool> _in3 = lessThan;
233231
s = _in0;
234232
idx = _in1;
235233
current = _in2;
236-
comparator = _in3;
234+
lessThan = _in3;
237235
goto TAIL_CALL_START;
238236
}
239237
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-13 Bytes
Binary file not shown.

Source/DafnyStandardLibraries/examples/TargetSpecific/DurationExamples-cs.dfy

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ operation using Dafny's {:test} annotation.
1010
These tests serve as verification examples that work with Dafny's formal proofs.
1111
*/
1212

13+
1314
module TestDuration {
1415
import Std.Duration
1516
import opened Std.BoundedInts
@@ -123,26 +124,16 @@ module TestDuration {
123124
AssertAndExpect(str[1] == 'T');
124125
}
125126

126-
function CompareHelper(d1: Duration.Duration, d2: Duration.Duration): int
127-
ensures -1 <= CompareHelper(d1, d2) <= 1
128-
{
129-
if d1.seconds < d2.seconds then -1
130-
else if d1.seconds > d2.seconds then 1
131-
else if d1.millis < d2.millis then -1
132-
else if d1.millis > d2.millis then 1
133-
else 0
134-
}
135-
136127
method {:test} TestMaxByWithCompareHelper() {
137128
var d1 := Duration.Duration(1, 100);
138129
var d2 := Duration.Duration(2, 50);
139130
var d3 := Duration.Duration(0, 999);
140131
var durations := [d1, d2, d3];
141132

142-
var maxD := MaxBy(durations, CompareHelper);
143-
var minD := MinBy(durations, CompareHelper);
133+
var maxD := MaxBy(durations, Duration.Less);
134+
var minD := MinBy(durations, Duration.Less);
144135

145-
expect CompareHelper(maxD, d2) == 0;
146-
expect CompareHelper(minD, d3) == 0;
136+
expect maxD == d2;
137+
expect minD == d3;
147138
}
148-
}
139+
}

Source/DafnyStandardLibraries/src/Std/Collections/Seq.dfy

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -442,57 +442,42 @@ module Std.Collections.Seq {
442442
}
443443

444444

445-
function MaxBy<T>(s: seq<T>, comparator: (T, T) -> int): T
445+
function MaxBy<T>(s: seq<T>, lessThan: (T, T) -> bool): T
446446
requires |s| > 0
447447
decreases |s|
448448
{
449-
MaxByHelper(s, 1, s[0], comparator)
449+
MaxByHelper(s, 1, s[0], lessThan)
450450
}
451451

452-
/// Helper function for MaxBy - iterates through sequence tracking the maximum
453-
function MaxByHelper<T>(s: seq<T>, idx: nat, current: T, comparator: (T, T) -> int): T
452+
function MaxByHelper<T>(s: seq<T>, idx: nat, current: T, lessThan: (T, T) -> bool): T
454453
requires idx <= |s|
455454
decreases |s| - idx
456455
{
457456
if idx == |s| then
458457
current
459458
else
460-
var cmp := comparator(current, s[idx]);
461-
var next := if cmp < 0 then s[idx] else current;
462-
MaxByHelper(s, idx + 1, next, comparator)
463-
}
464-
465-
/// Find the minimum element in a sequence using a comparator function
466-
///
467-
/// The comparator function should return:
468-
/// -1 if a < b (first argument is less than second)
469-
/// 0 if a == b (equal)
470-
/// 1 if a > b (first argument is greater than second)
471-
///
472-
/// Example usage with Duration:
473-
/// var minDuration := MinBy(durations, Duration.Compare)
474-
function MinBy<T>(s: seq<T>, comparator: (T, T) -> int): T
459+
var next := if lessThan(current, s[idx]) then s[idx] else current;
460+
MaxByHelper(s, idx + 1, next, lessThan)
461+
}
462+
463+
function MinBy<T>(s: seq<T>, lessThan: (T, T) -> bool): T
475464
requires |s| > 0
476465
decreases |s|
477466
{
478-
MinByHelper(s, 1, s[0], comparator)
467+
MinByHelper(s, 1, s[0], lessThan)
479468
}
480469

481-
/// Helper function for MinBy - iterates through sequence tracking the minimum
482-
function MinByHelper<T>(s: seq<T>, idx: nat, current: T, comparator: (T, T) -> int): T
470+
function MinByHelper<T>(s: seq<T>, idx: nat, current: T, lessThan: (T, T) -> bool): T
483471
requires idx <= |s|
484472
decreases |s| - idx
485473
{
486474
if idx == |s| then
487475
current
488476
else
489-
var cmp := comparator(current, s[idx]);
490-
var next := if cmp > 0 then s[idx] else current;
491-
MinByHelper(s, idx + 1, next, comparator)
477+
var next := if lessThan(s[idx], current) then s[idx] else current;
478+
MinByHelper(s, idx + 1, next, lessThan)
492479
}
493480

494-
495-
496481
/* Unzipping and zipping a sequence results in the original sequence */
497482
lemma LemmaZipOfUnzip<A, B>(xs: seq<(A, B)>)
498483
ensures Zip(Unzip(xs).0, Unzip(xs).1) == xs

0 commit comments

Comments
 (0)