@@ -323,7 +323,14 @@ ensures DictLessThan(d1, d3)
323323ensures !DictLessThan(d3, d1)
324324decreases
325325func StrictDictLessThanTransitive(d1 dict[Key]Val, d2 dict[Key]Val, d3 dict[Key]Val) {
326- assume false
326+ DictLessThanTransitive(d1, d2, d3)
327+ assert DictLessThan(d1, d3)
328+ assert d1 !== d3
329+
330+ if DictLessThan(d3, d1) {
331+ DictLessEq(d1, d3)
332+ assert false // Unreachable
333+ }
327334}
328335
329336ghost
@@ -366,54 +373,64 @@ func DictLessEq(d1 dict[Key]Val, d2 dict[Key]Val) {
366373 assert domain(d1) == domain(d2)
367374}
368375
376+ ghost
377+ decreases
378+ pure func keyInDict(d dict[Key]Val, k Key, v io.Pkt) bool {
379+ return k elem domain(d) && v elem AsSet(d[k])
380+ }
381+
382+ ghost
383+ ensures let d := DictMax(d1, d2) in
384+ forall k Key, v io.Pkt :: !keyInDict(d, k, v) == !(keyInDict(d1, k, v) || keyInDict(d2, k, v))
385+ decreases
386+ func dictMaxAssocLemma0(d1 dict[Key]Val, d2 dict[Key]Val) {
387+ reveal DictUnion(d1, d2)
388+ }
389+
390+ ghost
391+ ensures let d := DictMax(d1, DictMax(d2, d3)) in
392+ forall k Key, v io.Pkt :: keyInDict(d, k, v) == (keyInDict(d1, k, v) || keyInDict(d2, k, v) || keyInDict(d3, k, v))
393+ decreases
394+ func dictMaxAssocLemma1(d1 dict[Key]Val, d2 dict[Key]Val, d3 dict[Key]Val) {
395+ d := DictMax(d1, DictMax(d2, d3))
396+ assert forall k Key, v io.Pkt :: (keyInDict(d1, k, v) || keyInDict(d2, k, v) || keyInDict(d3, k, v)) ==> keyInDict(d, k, v)
397+ dictMaxAssocLemma0(d2, d3)
398+ dictMaxAssocLemma0(d1, DictMax(d2, d3))
399+ assert forall k Key, v io.Pkt :: keyInDict(d, k, v) ==> (keyInDict(d1, k, v) || keyInDict(d2, k, v) || keyInDict(d3, k, v))
400+ }
401+
402+ ghost
403+ ensures let d := DictMax(DictMax(d1, d2), d3) in
404+ forall k Key, v io.Pkt :: keyInDict(d, k, v) == (keyInDict(d1, k, v) || keyInDict(d2, k, v) || keyInDict(d3, k, v))
405+ decreases
406+ func dictMaxAssocLemma2(d1 dict[Key]Val, d2 dict[Key]Val, d3 dict[Key]Val) {
407+ d := DictMax(DictMax(d1, d2), d3)
408+ assert forall k Key, v io.Pkt :: (keyInDict(d1, k, v) || keyInDict(d2, k, v) || keyInDict(d3, k, v)) ==> keyInDict(d, k, v)
409+ dictMaxAssocLemma0(d1, d2)
410+ dictMaxAssocLemma0(DictMax(d1, d2), d3)
411+ assert forall k Key, v io.Pkt :: keyInDict(d, k, v) ==> (keyInDict(d1, k, v) || keyInDict(d2, k, v) || keyInDict(d3, k, v))
412+ }
413+
414+ ghost
415+ ensures (forall k Key, v io.Pkt :: keyInDict(d1, k, v) == keyInDict(d2, k, v)) == (d1 === d2)
416+ decreases
417+ func dictMaxExtensionality(d1 dict[Key]Val, d2 dict[Key]Val) {
418+ assert (d1 === d2) ==> (forall k Key, v io.Pkt :: keyInDict(d1, k, v) == keyInDict(d2, k, v))
419+ assume false
420+ assert forall k Key, v io.Pkt :: keyInDict(d1, k, v) == keyInDict(d2, k, v) ==>
421+ domain(d1) == domain(d2)
422+ // assert forall k Key :: k elem domain(d1) ==>
423+ // ((forall v io.Pkt :: keyInDict(d1, k, v) == keyInDict(d2, k, v)) ==
424+ // (k elem domain(d2) && d1[k] == d2[k]))
425+ }
426+
369427ghost
370428ensures DictMax(d1, DictMax(d2, d3)) === DictMax(DictMax(d1, d2), d3)
371429decreases
372430func DictMaxAssoc(d1 dict[Key]Val, d2 dict[Key]Val, d3 dict[Key]Val) {
373- m1 := DictMax(d1, DictMax(d2, d3))
374- m2 := DictMax(DictMax(d1, d2), d3)
375- assert m1 === d1 || m1 === DictMax(d2, d3) || m1 === DictUnion(d1, DictMax(d2, d3))
376-
377- if DictLessThan(d1, d2) {
378- DictLessThanTransitive(d1, d2, DictMax(d2, d3))
379- assert DictMax(d1, DictMax(d2, d3)) === DictMax(d2, d3)
380- assert DictMax(DictMax(d1, d2), d3) === DictMax(d2, d3)
381- } else if DictLessThan(d2, d1) {
382- assert DictMax(DictMax(d1, d2), d3) === DictMax(d1, d3)
383- if DictLessThan(d2, d3) {
384- // proven
385- } else if DictLessThan(d3, d2) {
386- assert DictMax(d2, d3) === d2
387- assert DictMax(d1, DictMax(d2, d3)) === DictMax(d1, d2)
388- assert DictMax(d1, d2) === d1
389- assert DictMax(DictMax(d1, d2), d3) === DictMax(d1, d3)
390- StrictDictLessThanTransitive(d3, d2, d1)
391- assert DictLessThan(d3, d1)
392- assert DictMax(d1, d3) === d1 || DictMax(d1, d3) === d3
393- assert !DictLessThan(d1, d3)
394- assert DictMax(d1, d3) === d1
395- } else {
396- assert DictMax(d2, d3) === DictUnion(d2, d3)
397- assert DictLessThan(d1, DictMax(d1, d3))
398- if DictLessThan(d1, d3) {
399- // d1 <= d3 && d2 <= d1 && !(d2 <= d3) && !(d3 <= d2)
400- assert DictMax(DictMax(d1, d2), d3) === DictMax(d1, d3)
401- assert DictMax(d1, d3) === d3
402- DictLessThanTransitive(d2, d1, d3) // Shows contradiction
403- assert false // Unreachable
404- } else if DictLessThan(d3, d1) {
405- // d3 <= d1 && !(d1 <= d3) && d2 <= d1 && !(d2 <= d3) && !(d3 <= d2)
406- assert DictMax(DictMax(d1, d2), d3) === d1
407- DictMaxIsLessThan(d2, d3, d1)
408- DictMaxIsComm(d1, DictMax(d2, d3))
409- assert DictMax(d1, DictMax(d2, d3)) === d1
410- } else {
411- assume false
412- }
413- }
414- } else {
415- assume false
416- }
431+ dictMaxAssocLemma1(d1, d2, d3)
432+ dictMaxAssocLemma2(d1, d2, d3)
433+ dictMaxExtensionality(DictMax(d1, DictMax(d2, d3)), DictMax(DictMax(d1, d2), d3))
417434}
418435
419436ghost
@@ -425,7 +442,6 @@ func DictMaxIsComm(d1 dict[Key]Val, d2 dict[Key]Val) {
425442 }
426443 assert d1 != d2 && DictLessThan(d1, d2) ==> !DictLessThan(d2, d1)
427444 assert DictLessThan(d1, d2) ==> DictMax(d1, d2) == d2
428- //assert DictMax(d2, d1) === DictLessThan(d2, d1) ? d1 : DictLessThan(d2, d1) ? d1 : DictUnion(d1, d2)
429445 assert DictLessThan(d1, d2) ==> DictMax(d2, d1) == d2
430446 assert DictLessThan(d2, d1) ==> DictMax(d1, d2) == d1
431447 assert DictLessThan(d2, d1) ==> DictMax(d2, d1) == d1
@@ -650,13 +666,6 @@ func DictUnionIsComm(d1 dict[Key]Val, d2 dict[Key]Val) {
650666 assert forall k Key :: k elem domain(u1) ==> u1[k] == u2[k]
651667}
652668
653- ghost
654- ensures DictUnion(DictUnion(d1, d2), d3) === DictUnion(d1, DictUnion(d2, d3))
655- decreases
656- func DictUnionIsAssoc(d1 dict[Key]Val, d2 dict[Key]Val, d3 dict[Key]Val) {
657- assume false
658- }
659-
660669// DictUnion(d1, d2) is the smallest dict that is bigger than both d1 and d2
661670ghost
662671ensures DictLessThan(d1, d3) && DictLessThan(d2, d3) ==> DictLessThan(DictUnion(d1, d2), d3)
0 commit comments