Generating tuples containing Long for Vavr Property Checking - property-testing

I need a pair of random longs for property checking with Vavr.
My implementation looks like this:
Gen<Long> longs = Gen.choose(Long.MIN_VALUE, Long.MAX_VALUE);
Arbitrary<Tuple2<Long, Long>> pairOfLongs = longs
.flatMap(value -> random -> Tuple.of(value, longs.apply(random)))
.arbitrary();
Is any better/nicer way to do the same in vavr?

Arbitrary<T> can be seen as a function of type
int -> Random -> T
Generating arbitrary integers
Because the sample size is of type int, it would be natural to do the following:
Arbitrary<Tuple2<Integer, Integer>> intPairs = size -> {
Gen<Integer> ints = Gen.choose(-size, size);
return random -> Tuple.of(ints.apply(random), ints.apply(random));
};
Let's test it:
Property.def("print int pairs")
.forAll(intPairs.peek(System.out::println))
.suchThat(pair -> true)
.check(10, 5);
Output:
(-9, 2)
(-2, -10)
(5, -2)
(3, 8)
(-10, 10)
Generating arbitrary long values
Currently we are not able to define a size of type long, so the workaround is to ignore the size and use the full long range:
Arbitrary<Tuple2<Long, Long>> longPairs = ignored -> {
Gen<Long> longs = Gen.choose(Long.MIN_VALUE, Long.MAX_VALUE);
return random -> Tuple.of(longs.apply(random), longs.apply(random));
};
Let's test it again:
Property.def("print long pairs")
.forAll(longPairs.peek(System.out::println))
.suchThat(pair -> true)
.check(0, 5);
Output:
(2766956995563010048, 1057025805628715008)
(-6881523912167376896, 7985876340547620864)
(7449864279215405056, 6862094372652388352)
(3203043896949684224, -2508953386204733440)
(1541228130048020480, 4106286124314660864)
Interpreting an integer size as long
The size parameter can be interpreted in a custom way. More specifically we could map a given int size to a long size:
Arbitrary<Tuple2<Long, Long>> longPairs = size -> {
long longSize = ((long) size) << 32;
Gen<Long> longs = Gen.choose(-longSize, longSize);
return random -> Tuple.of(longs.apply(random), longs.apply(random));
};
However, the last example does not match the full long range. Maybe it is possible to find a better mapping.
Disclaimer: I'm the author of Vavr (formerly known as Javaslang)

Related

Converting a list of integers to a map of vertices containing the elements coordinates

This is what i have at the moment
(string -> int list)
let read filename = ....
this is working as intended, returning a list of integers from a textfile looking like this:
530070000
600195000
098000060
800600003
400803001
700020006
060000280
000419005
000080079
Yes you are correct, it is a sudoku board. This is what i have to work with:
type vertex = int * int (*Cells in the sudoku board*)
type gamma = int (*representing colors 1-9*)
(* [Vertex = Map.Make(Vertex)] *)
module Vertex = Map.Make(struct
type t = vertex
let compare = Stdlib.compare
end)
(* [Gamma = Set.Make(Gamma)] *)
module Gamma = Set.Make(struct
type t = gamma
let compare = Stdlib.compare
end)
The gamma set is for solving the sudoku board using graph coloring. I need help understanding how i can convert the list of integers to a suitable map for this kind of task. According to the structure i provided, so i can access each element in the map using it coordinates (x, y). Hope you understand, otherwise i will try to provide more info. I'm reaaally bad at OCaml but trying to learn. I'm sorry for body errors etc, first time posting here.
As far as I can understand your task, the text file contains a grid of digits with the initial disposition for sudoku. So you shouldn't interpret a line in the file as a single integer but rather as a list of integers. You can either change your read function so that it returns int list list instead of int list and then use List.fold_left over the list that will also count the position of an element in the list, but it is tedious. It is much easier to read the grid directly from the file, e.g.,
let read_matrix chan =
let rec loop i j grid =
match input_char chan with
| exception End_of_file -> grid
| '\n' -> loop (i+1) 0 grid
| '0'..'9' as c ->
loop i (j+1) ##
Vertex.add (i,j) (ascii_digit c) grid
| _ -> invalid_arg "invalid input" in
loop 0 0 Vertex.empty
where ascii_digit is defined as,
let ascii_digit c = Char.code c - Char.code '0'
The read_matrix function takes the channel as input so to read the grid from a file you can define,
let matrix_from_file file =
let chan = open_in file in
let r = read_matrix chan in
close_in chan;
r
Hint: you probably also don't want to include positions with 0 in your grid. It is easy to achieve, just add another case to the pattern in the loop function that will skip it, e.g.,
...
| '0' -> loop i (j+1) grid
...

Convert Map <Integer, Long> to array of Integer

Can someone tell me what I am doing wrong here? p.getVote(), and the collection counting logic return a Long, but I am trying to make my end output an array of ints.
Map<Integer, Long> counters = iqr.getQgagueUniqueVotes().stream()
.collect(Collectors.groupingBy(p -> ((int)p.getVote()),
Collectors.counting()));
Collection<Long> values = counters.values();
long[] targetArray = values.toArray(new Long[values.size()]);
Error:
Incompatible type: Inference variable has incompatible upper bound
Change the type of the targetArray array to a type Long:
Long[] targetArray = values.toArray(new Long[values.size()]);
or create a stream of the values and map to a type long then collect to an array.
long[] targetArray = values.stream().mapToLong(Long::longValue).toArray();

Partition a list into equivalence classes

I am trying to write a function in SML which when given a list of general elements, reorders its elements into equivalent classes and returns a list of these classes (type "a list list).
Leave the elements in the classes in the same order as in the original list.
A given function defines the equivalence of the elements and it returns true if the elements are equivalent or false otherwise.
I cannot seem to get a grip on the solution.
fun sample x y = x = y
Required type: fn : (''a -> ''a -> bool) -> ''a list -> ''a list list
Thank you very much for the help.
The helper function does not work correctly, all I want to do with it is see if a given element belongs to any of the classes and put it accordingly inside or create a new sublist which contains it.
fun srt listoflists func new =
case listoflists of [] => [[]]
| a::b => if func (new, hd a) = true then (new::a)::b
else if func (new, hd a) = false then a::(srt b func new) else [new]::a::b
The sample functions checks equivalence of two elements when divided by 11.
Tests are not all working, it is not adding 17 into a new class.
srt [[7,7,7],[5,5,5],[11,11,11],[13,13,13]] eq 7;
val it = [[7,7,7,7],[5,5,5],[11,11,11],[13,13,13]] : int list list
- srt [[7,7,7],[5,5,5],[11,11,11],[13,13,13]] eq 5;
val it = [[7,7,7],[5,5,5,5],[11,11,11],[13,13,13]] : int list list
- srt [[7,7,7],[5,5,5],[11,11,11],[13,13,13]] eq 11;
val it = [[7,7,7],[5,5,5],[11,11,11,11],[13,13,13]] : int list list
- srt [[7,7,7],[5,5,5],[11,11,11],[13,13,13]] eq 13;
val it = [[7,7,7],[5,5,5],[11,11,11],[13,13,13,13]] : int list list
- srt [[7,7,7],[5,5,5],[11,11,11],[13,13,13]] eq 17;
val it = [[7,7,7],[5,5,5],[11,11,11],[13,13,13],[]] : int list list
- srt [[7,7,7],[5,5,5],[11,11,11],[13,13,13],[111,111,111]] eq 111;
val it = [[7,7,7],[5,5,5],[11,11,11],[13,13,13],[111,111,111,111]]
How to correct this and also once this helper function works, how to encorporate it exactly into the main function that is required.
Thank you very much.
Your example code seems like you are getting close, but has several issues
1) The basis cases is where new should be added, so in that case you should return the value [[new]] rather than [[]]
2) Your problem description suggests that func be of type ''a -> ''a -> bool but your code for srt seems to be assuming it is of type (''a * ''a) -> bool. Rather than subexpressions like func (new, hd a) you need func new (hd a) (note the parentheses location).
3) if func returns a bool then comparing the output to true is needlessly verbose, instead of if func new (hd a) = true then ... simply have if func new (hd a) then ...
4) Since you are adding [new] in the basis cases, your second clause is needlessly verbose. I see no reason to have any nested if expressions.
Since this seems to be homework, I don't want to say much more. Once you get the helper working correctly it should be fairly straightforward to use it (in the recursive case) of the overall function. Note that you could use (a # [new])::b rather than (new::a)::b if you want to avoid the need for a final mapping of rev across the final return value. # is more expensive than :: (it is O(n) rather than O(1)), but for small examples it really doesn't matter and could even be slightly better since it would avoid the final step of reversing the lists.

What is the difference between int -> int -> int and (int*int) -> int in SML?

I have noticed that there are 2 ways of defining functions in SML. For example if you take the add function, these are the two ways:
fun add x y = x+y;
fun add(x,y) = x+y;
The first method creates the function type as:
val add = fn : int -> int -> int
The second one creates the function type as:
val add = fn : int * int -> int
What is the difference between these two types for the same function? And also why are there two types for the same function?
If we remove the syntactic sugar from your two definitions they become:
val add = fn x => fn y => x+y
and
val add = fn xy =>
case xy of
(x,y) => x+y
So in the first case add is a function that takes an argument x and returns another function, which takes an argument y and then returns x+y. This technique of simulating multiple arguments by returning another function is known as currying.
In the second case add is a function that takes a tuple as an argument and then adds the two elements of the tuple.
This also explains the two different types. -> is the function arrow, which associates to the right, meaning int -> int -> int is the same as int -> (int -> int) describing a function that takes an int and returns an int -> int function.
* on the other hand is the syntax used for tuple types, that is int * int is the type of tuples containing two ints, so int * int -> int (which is parenthesized as (int * int) -> int because * has higher precedence than ->) describes a function that takes a tuple of two ints and returns an int.
The reason those 2 functions are different is because of the phenomenon of Currying. Specifically, Currying is the ability to write any function with dom(f) = R^{n} as a function that takes inputs from R n-times. This basically is accomplished by ensuring that each input returns a function for the next variable to take in. This is what the -> sign represents - It's a fundamental result from the Curry-Howard Isomorphism. So :
fun addCurry x y = x + y (* int -> int -> int *)
fun addProd (x,y) = x + y (* (int*int) -> int *)
tells us that addCurry is the reduction of addProd into a form that can be used to "substitute" and return variables. So, addProd and addCurry are Contextually-Equivalent. However, they are not Semantically-Equivalent.
(int*int) is a product-type. It says that it expects input1=int and input2=int. int -> int says that it takes an int and returns an int. It's an arrow-type.
If you're interested, you may also want to know that there are only 2 kinds of arguments to SML functions :
1) Curried
2) Tuples - So, fun addProd (x,y) represents (x,y) as a tuple to the function argument.

Index of string value in MiniZinc array

The question
Given a MiniZinc array of strings:
int: numStats;
set of int: Stats = 1..numStats;
array[Stats] of string: statNames;
... with data loaded from a MiniZinc data file:
numStats = 3;
statNames = ["HEALTH", "ARMOR", "MANA"];
How can one look up the index of a specific string in the array? For example, that ARMOR is located at position 2.
The context
I need to find an optimal selection of items with regard to some constraints on their stats. This information is stored in a 2D array declared as follows:
int: numItems;
set of int: Items = 1..numItems;
array[Items, Stats] of float: itemStats;
So in order to write a constraint on, say, the minimum amount of ARMOR obtained through the selected items, I need to know that ARMOR has index 2 in the inner array.
Since the data file is generated by an external program, and the number and order of stats are dynamic, I cannot hardcode the indices in the constraints.
One solution (that won't work in my case)
The MiniZinc tutorial uses an interesting trick to achieve something similar:
set of int: Colors = 1..3;
int: red = 1;
int: yellow = 2;
int: blue = 3;
array[Colors] of string: name = ["red", "yellow", "blue"];
var Colors: x;
constraint x != red;
output [ name[fix(x)] ];
Unfortunately, as variable declarations are not allowed in MiniZinc data files, this trick won't work in my case.
You can write your own custom function to get the index of a string within a string array:
function int: getIndexOfString(string: str,
array[int] of string: string_array) =
sum( [ if str = string_array[i]
then i
else 0 endif
| i in index_set(string_array) ]
);
In this function I create an array of integers where the integer at position i either equals the index of str if string_array[i]=str and 0 otherwise. For instance, for your sample string array ["HEALTH", "ARMOR", "MANA"] and str ARMOR the resulting int array will be [0,2,0].
This is why I can simply sum over the int array to get the index of the string. If the string does not occur, the return value is 0, which is fine since indices in MiniZinc start with 1 by default.
Here is how you can call the function above for your first example:
int: numStats;
set of int: Stats = 1..numStats;
array[Stats] of string: statNames;
numStats = 3;
statNames = ["HEALTH", "ARMOR", "MANA"];
var int: indexOfArmor;
constraint
indexOfArmor = getIndexOfString("ARMOR",statNames);
solve satisfy;
Note however that the function above is limited and has some flaws. First, if you have multiple occurrences of the string in the array, then you will receive an invalid index (the sum of all indices where str occurred). Also, if you have your own index set for your string array (say (2..6)), then you will need to adapt the function.
Another, cleaner option is to write a function that uses a recursive helper function:
% main function
function int: index_of(string: elem, array[int] of string: elements) =
let {
int: index = length(elements);
} in % calls the helper function with the last index
get_index(elem, elements, index)
;
% recursive helper function
function int: get_index(string: elem, array[int] of string: elements, int: index) =
if index == 0
then -1 % the element was not found (base case of recursion)
elseif elements[index] == elem
then index % the element was found
else
get_index(elem, elements, index - 1) % continue searching
endif
;
The helper function iterates recursively over the array, starting from the last element, and when it finds the element, it returns the index. If the element was not found in the array, then -1 is returned. Alternatively, you can also throw an assertion following the suggestion of Patrick Trentin by replacing then -1 with then assert(false, "unknown element: " + elem).
An example of calling this function:
set of int: Customers = 1..5;
array[Customers] of string: ids = ["a-1", "a-2", "a-3", "a-4", "a-5"];
var int: index = index_of("a-3", ids);
var int: unknown_index = index_of("x-3", ids);
where index will be assigned 3 and unknown_index will be -1.
An alternative approach to that presented by Andrea Rendl-Pitrey, is the following one:
array[int] of string: statNames = array1d(10..12, ["HEALTH", "ARMOR", "MANA"]);
var int: indexOfArmor =
sum([i | i in index_set(statNames) where statNames[i] = "ARMOR"]);
solve satisfy;
output [
"indexOfArmor=", show(indexOfArmor), "\n",
];
which outputs:
~$ mzn2fzn example.mzn ; flatzinc example.fzn
indexOfArmor = 11;
----------
note: that var can be dropped from the declaration of indexOfArmor, since the index can be statically computed. I kept it here only for output purposes.
A better solution is to declare a new predicate:
predicate index_of_str_in_array(var int: idx,
string: str,
array[int] of string: arr) =
assert(
not exists(i in index_set(arr), j in index_set(arr))
(i != j /\ arr[i] = str /\ arr[j] = str),
"input string occurs at multiple locations",
assert(
exists(i in index_set(arr))
(arr[i] = str),
"input string does not occur in the input array",
exists(i in index_set(arr))
(arr[i] = str /\ i = idx)
));
which enforces both of the following conditions:
str occurs at least once in arr
str does not occur multiple times in arr
e.g
predicate index_of_str_in_array(var int: idx,
string: str,
array[int] of string: arr) =
...
array[10..13] of string: statNames =
array1d(10..13, ["HEALTH", "ARMOR", "MANA", "ATTACK"]);
var int: indexOfArmor;
constraint index_of_str_in_array(indexOfArmor, "ARMOR", statNames);
solve satisfy;
output [
"indexOfArmor=", show(indexOfArmor), "\n",
];
outputs
~$ mzn2fzn example.mzn ; flatzinc example.fzn
indexOfArmor = 11;
----------
If one changes statNames in the following way
array[10..13] of string: statNames =
array1d(10..13, ["HEALTH", "ARMOR", "MANA", "ARMOR"]);
then mzn2fzn detects an assertion violation:
~$ mzn2fzn example.mzn ; flatzinc example.fzn
MiniZinc: evaluation error:
example.mzn:24:
in call 'index_of_str_in_array'
example.mzn:4:
in call 'assert'
Assertion failed: input string occurs at multiple locations
flatzinc:
example.fzn: cannot open input file: No such file
A similar result would be obtained by searching for the index of a string that does not occur in the array. This condition can of course be removed if not necessary.
DISCLAIMER: older versions of mzn2fzn don't seem to check that the declared index-set of an array of strings variable matches the index-set of an array of strings literal that is being assigned to it. This rule is enforced on newer versions, as it is also valid for other data types.
According to this other post on Stackoverflow there is no way of converting strings to integers in MiniZinc, only the other way around. You need to first pre process your data in some other language and turn it into integers. You can however turn those integers into string once you are done in MiniZinc.
You can however load MiniZinc files instead of data files if you would like. Use the include syntax to include any .mzn file.

Resources