Skip to content

Commit 0f82cdd

Browse files
Java override for FoldBag
1 parent b961f70 commit 0f82cdd

File tree

4 files changed

+174
-15
lines changed

4 files changed

+174
-15
lines changed

modules/BagsExt.tla

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,59 @@ BagRemove(B,x) ==
2727
ELSE [e \in DOMAIN B |-> IF e=x THEN B[e]-1 ELSE B[e]]
2828
ELSE B
2929

30+
BagRemoveAll(B,x) ==
31+
(************************************************************************)
32+
(* Remove all copies of an element x from bag B. *)
33+
(************************************************************************)
34+
[e \in DOMAIN B \ {x} |-> B[e]]
35+
36+
MapThenFoldBag(op(_,_), base, f(_), choose(_), B) ==
37+
(***********************************************************************)
38+
(* Fold operation op over the images through f of all elements of bag *)
39+
(* B, starting from base. The parameter choose indicates the order in *)
40+
(* which elements of the bag are processed; all replicas of an element *)
41+
(* are processed consecutively. *)
42+
(* *)
43+
(* Examples: *)
44+
(* MapThenFoldBag(LAMBDA x,y : x+y, *)
45+
(* 0, *)
46+
(* LAMBDA x: 1, *)
47+
(* LAMBDA B : CHOOSE x \in DOMAIN B : TRUE, *)
48+
(* (1 :> 2) @@ (2 :> 1) @@ (3 :> 3)) = 6 *)
49+
(* *)
50+
(* MapThenFoldBag(LAMBDA x,y : x \o y, *)
51+
(* << >>, *)
52+
(* LAMBDA x: << x >>, *)
53+
(* LAMBDA S: CHOOSE x \in S : \A y \in S : x <= y, *)
54+
(* (1 :> 2) @@ (2 :> 1) @@ (3 :> 3)) *)
55+
(* = <<1,1,2,3,3,3>> *)
56+
(* *)
57+
(* The fifth argument represents the bag {| 1, 1, 2, 3, 3, 3 |}. *)
58+
(* The first example counts the elements of the bag. *)
59+
(* The second example computes a sorted sequence of all elements *)
60+
(* of the bag. It is brittle because concatenation of sequences is *)
61+
(* non-commutative, and the result therefore relies on the *)
62+
(* definition of MapThenFoldSet. *)
63+
(***********************************************************************)
64+
LET handle(x) == \* handle all occurrences of x in B
65+
LET pow[n \in Nat \ {0}] ==
66+
op(IF n=1 THEN base ELSE pow[n-1], f(x))
67+
IN pow[B[x]]
68+
IN MapThenFoldSet(op, base, handle,
69+
LAMBDA S : CHOOSE x \in S : TRUE,
70+
DOMAIN B)
71+
3072
FoldBag(op(_,_), base, B) ==
3173
(************************************************************************)
3274
(* Fold op over all elements of bag B, starting with value base. *)
3375
(* *)
3476
(* Example: *)
3577
(* FoldBag(LAMBDA x,y : x+y, *)
3678
(* 0, *)
37-
(* (1 :> 2) @@ (2 :> 1) @@ (3 :> 2)) = 10 *)
38-
(* The third argument represents the bag {| 1, 1, 2, 3, 3 |}. *)
39-
(************************************************************************)
40-
LET repl(x) ==
41-
(* replicate operation op for all occurrences of x in B *)
42-
LET it[n \in Nat \ {0}] ==
43-
IF n = 1 THEN x ELSE op(x, it[n-1])
44-
IN it[B[x]]
45-
IN MapThenFoldSet(op, base, repl,
46-
LAMBDA S : CHOOSE x \in S : TRUE,
47-
DOMAIN B)
79+
(* (1 :> 2) @@ (2 :> 1) @@ (3 :> 3)) = 13 *)
80+
(* The third argument represents the bag {| 1, 1, 2, 3, 3, 3 |}. *)
81+
(************************************************************************)
82+
MapThenFoldBag(op, base, LAMBDA x: x, LAMBDA S : CHOOSE x \in S : TRUE, B)
4883

4984
SumBag(B) ==
5085
(************************************************************************)
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2022 Inria. All rights reserved.
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10+
* of the Software, and to permit persons to whom the Software is furnished to do
11+
* so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18+
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19+
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20+
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22+
*
23+
* Contributors:
24+
* Stephan Merz - initial implementation
25+
******************************************************************************/
26+
package tlc2.overrides;
27+
28+
import java.util.Arrays;
29+
30+
import tlc2.module.Bags;
31+
import tlc2.output.EC;
32+
import tlc2.tool.EvalControl;
33+
import tlc2.tool.EvalException;
34+
import tlc2.value.Values;
35+
// import tlc2.value.impl.Applicable;
36+
// import tlc2.value.impl.BoolValue;
37+
// import tlc2.value.impl.Enumerable;
38+
import tlc2.value.impl.FcnRcdValue;
39+
import tlc2.value.impl.OpValue;
40+
// import tlc2.value.impl.SetOfRcdsValue;
41+
// import tlc2.value.impl.TupleValue;
42+
import tlc2.value.impl.Value;
43+
import tlc2.value.impl.IntValue;
44+
// import tlc2.value.impl.ValueEnumeration;
45+
46+
public final class BagsExt {
47+
48+
private BagsExt() {
49+
// no-instantiation!
50+
}
51+
52+
@TLAPlusOperator(identifier = "FoldBag", module = "BagsExt", warn = false)
53+
public static Value foldBag(final OpValue op, final Value base, final Value bag) {
54+
// Can assume type of OpValue because tla2sany.semantic.Generator.java will
55+
// make sure that the first parameter is a binary operator.
56+
57+
FcnRcdValue bfcn = (FcnRcdValue) bag.toFcnRcd();
58+
if (bfcn == null) {
59+
throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR,
60+
new String[] { "third", "FoldBag", "bag",
61+
Values.ppr(bag.toString()) });
62+
}
63+
64+
final Value[] domain = bfcn.getDomainAsValues();
65+
final Value[] values = bfcn.values;
66+
final Value acc[] = new Value[2];
67+
acc[0] = base;
68+
69+
for (int i=0; i < domain.length; i++) {
70+
acc[1] = domain[i];
71+
if (!(values[i] instanceof IntValue) || (((IntValue)values[i]).val <= 0)) {
72+
throw new EvalException(EC.TLC_MODULE_APPLYING_TO_WRONG_VALUE,
73+
new String[] { "third", "FoldBag", "bag",
74+
Values.ppr(bag.toString()) });
75+
}
76+
for (int j=0; j < ((IntValue)values[i]).val; j++) {
77+
acc[0] = op.apply(acc, EvalControl.Clear);
78+
}
79+
}
80+
81+
return acc[0];
82+
}
83+
}
84+

modules/tlc2/overrides/TLCOverrides.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@ public Class[] get() {
4444
// Remove `Json.resolves();` call when this Class is moved to `TLC`.
4545
Json.resolves();
4646
return new Class[] { IOUtils.class, SVG.class, SequencesExt.class, Json.class, Bitwise.class,
47-
FiniteSetsExt.class, Functions.class, CSV.class, Combinatorics.class };
47+
FiniteSetsExt.class, Functions.class, CSV.class, Combinatorics.class, BagsExt.class };
4848
} catch (NoClassDefFoundError e) {
4949
// Remove this catch when this Class is moved to `TLC`.
5050
System.out.println(
5151
"gson dependencies of Json overrides not found, Json module won't work unless "
5252
+ "the libraries in the lib/ folder of the CommunityModules have been added to the classpath of TLC.");
5353
}
5454
return new Class[] { IOUtils.class, SVG.class, SequencesExt.class, Bitwise.class,
55-
FiniteSetsExt.class, Functions.class, CSV.class, Combinatorics.class };
55+
FiniteSetsExt.class, Functions.class, CSV.class, Combinatorics.class, BagsExt.class };
5656
}
5757
}

tests/BagsExtTests.tla

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,56 @@ ASSUME LET B == SetToBag({1,2}) IN BagRemove(B,2) = B (-) SetToBag({2})
1616
ASSUME LET B == SetToBag({1,2}) IN
1717
/\ BagRemove(B,3) = B (-) SetToBag({3})
1818
/\ BagRemove(B,3) = B
19+
ASSUME LET B == (1 :> 2) @@ (2 :> 1) IN BagRemoveAll(B,1) = SetToBag({2})
1920

2021
-----------------------------------------------------------------------------
2122

22-
ASSUME FoldBag(LAMBDA x,y : x+y, 0, (1:>2) @@ (2:>1) @@ (3:>2)) = 10
23+
ASSUME LET B == (1 :> 2) @@ (2 :> 1) @@ (3 :> 3)
24+
IN MapThenFoldBag(LAMBDA x,y : x \cup y,
25+
{},
26+
LAMBDA x : {x},
27+
LAMBDA S : CHOOSE x \in S : TRUE,
28+
B)
29+
= BagToSet(B)
30+
31+
(***************************************************************************)
32+
(* This operator is a copy of FoldBag in module BagsExt. It serves for *)
33+
(* testing the Java override of the FoldBag operator. Note that the *)
34+
(* operator MapThenFoldBag does not have a Java override. *)
35+
(***************************************************************************)
36+
TLAFoldBag(op(_,_), base, B) ==
37+
(************************************************************************)
38+
(* Fold op over all elements of bag B, starting with value base. *)
39+
(* *)
40+
(* Example: *)
41+
(* FoldBag(LAMBDA x,y : x+y, *)
42+
(* 0, *)
43+
(* (1 :> 2) @@ (2 :> 1) @@ (3 :> 3)) = 13 *)
44+
(* The third argument represents the bag {| 1, 1, 2, 3, 3, 3 |}. *)
45+
(************************************************************************)
46+
MapThenFoldBag(op, base, LAMBDA x: x, LAMBDA S : CHOOSE x \in S : TRUE, B)
47+
48+
ASSUME LET B == (1:>2) @@ (2:>1) @@ (3:>3)
49+
IN FoldBag(LAMBDA x,y : x+y, 0, B)
50+
= TLAFoldBag(LAMBDA x,y : x+y, 0, B)
51+
ASSUME LET B == ({1}:>2) @@ ({-2}:>1) @@ ({3}:>3)
52+
IN FoldBag(LAMBDA x,y : x \union y, {}, B)
53+
= TLAFoldBag(LAMBDA x,y : x \union y, {}, B)
54+
55+
ASSUME FoldBag(LAMBDA x,y : x+y, 0, (1:>2) @@ (2:>1) @@ (3:>3)) = 13
2356
ASSUME FoldBag(LAMBDA x,y : x+y, 0, (1:>2) @@ (-2:>1)) = 0
2457

2558
ASSUME SumBag((1:>2) @@ (2:>1) @@ (3:>2)) = 10
2659
ASSUME SumBag((1:>2) @@ (-2:>1)) = 0
2760

2861
ASSUME ProductBag((1:>2) @@ (-2:>1)) = -2
29-
ASSUME ProductBag((1:>2) @@ (0:>1) @@ (10000:>1)) = 0
62+
63+
(***************************************************************************)
64+
(* The two following tests fail without the Java override for FoldBag. *)
65+
(***************************************************************************)
66+
ASSUME LET B == (1 :> 1000) @@ (-2 :> 500)
67+
IN FoldBag(LAMBDA x,y : x+y, 0, B) = 0
68+
69+
ASSUME ProductBag((0 :> 1) @@ (10000 :> 1000)) = 0
3070

3171
=============================================================================

0 commit comments

Comments
 (0)