I have an array: array[backpacks] of int: capacity specifying the capacity of each backpack.
Now I want to create an array of variables which the constraint solver will have to satisfy. I want each variable to take values in domain 1..capacity where capacity corresponds to the one specified in the above array.
Would something like this work: array[backpacks] of var capacity: bagcaps ?
Or do I have to do something like: array[backpacks] of var 1..MAX: bagcaps
and then add constraints: constraint forall(i in backpacks) bagcaps[i] <= capacity[i] ?
Thank you.
There is no short cut to restrict the domain of specific element in the array declaration. The traditional version is the one you wrote last:
constraint forall(i in backpacks) bagcaps[i] <= capacity[i]);
However, you can make this as an predicate (and place it in a separate file which is then imported into the model with include). E.g. some thing like this:
set of int: backpacks = 1..6;
array[backpacks] of int: capacity = [10,4,3,7,5,3];
array[backpacks] of var 1..max(capacity): bagcaps;
solve satisfy;
predicate restrict_domains(array[int] of var int: x, array[int] of int: d) =
forall(i in index_set(x)) ( x[i] <= d[i] );
constraint
% forall(i in backpacks) ( bagcaps[i] <= capacity[i] ) % original
restrict_domains(bagcaps,capacity)
;
% output [];
Note that you must still use restrict_domains as a constraint. And I recommend that you always restrict the domain in the declaration as much as possible, i.e. use the declaration using var 1..max(capacity) instead of var int.
Related
I have array contain string items in scala , each item contain from prefix + || + double value like below :
var y = Array("Zara||6.0", "Nuha||4.0","Zara||2.0","Zara||0.1")
what I want to Do :
i need sum all double value from above array (y(i).split("\|\|")(1)) But if the prefix the duplicated in the array then I only want sum the max value like below :
for item Zara we have 3 values i want to take the max (in our sample it 6.0)
for item Nuha it unique then i will take it's value (4.0)
the excepted output is (6.0+4.0)=10.0
is there are any way to do it in scala rather than using 2 instead loop ?
Prepare your array: extract prefix and values into tuple. Use foldLeft for aggregate max elem for each prefix, and sum values
val res = y.map(_.split("\\|\\|")).map(arr => (arr(0), arr(1).toDouble))
.foldLeft(Map.empty[String, Double]) { (acc, elem) =>
val value = acc.get(elem._1).map(math.max(_, elem._2)).getOrElse(elem._2)
acc + (elem._1 -> value)
}.values.sum
println(res)
You can do it pretty much in one step (it's three steps technically, but only one specifically addressing your requirement, everything else (split and sum) is kinda a given either way.
y
.iterator
.map(_.split("""\|\|"""))
.groupMapReduce(_.head)(_.last.toDouble)(_ max _)
.values
.sum
Also ... do not use vars. Even if you just putting together a quick sample. Vars are evil, just pretend they do not exist at all ... at least for a while, until you acquire enough of a command of the language to be able to tell the 1% of situations, where you might actually need them. Actually, avoid using Arrays as much as possible too.
I am new to constraint programming and to Minizinc.
I have look for a solution to this not relly hard task but I found nothing.
I want to count the number of different elements that appear in an array:
This is the declaration of my array:
array[1..n,1..n] of var 1..n: countLeft;
I have try to do like this:
constraint
forall(j in 1..n) (
length(array2set([countLeft[i,j]|i in 1..stopCountLeft[j]]) )==left_vision[j]
);
But apparently my array is of type: array[int]of var opt int and is not accept by the function array2set.
Any ideas?
There might be different approaches you could take, but an approach that is similar to what you try would be to split the counting of different elements in an array into two steps:
Counting the occurrence of the values in the domain.
Counting the amount of times the occurrence is higher than zero.
We can use the global global_cardinality constraint to count the occurrences and then use a simply count constraint over its result.
include "global_cardinality_fn";
array[1..n] of var int: occurrences = global_cardinality(YOURARRAY, [i | i in 1..n]);
var int: num_diff = count(o in occurrences) (o > 0);
Note, however, that this might not be the best code for your model. For some solvers global_cardinality might not be perform well enough. Similarly if your stopCountLeft contains variables, then that means that you are creating a array of optional variables, and global_cardinality might not be defined for optional variables.
Instead we can write an implication graph instead. The idea is still the same, but instead of counting the number of a value occurring, we just use a boolean value to signal wether the value is in use.
array[1..n] of var bool: occurs;
constraint forall(i,j in 1..n) (YOURARRAY[i] = j -> occurs[j]);
var int: num_diff = count(occurs);
Note that the problem with this approach is the exponential number of implications posted in the forall loop. However, I suspect that, with implications being small, it would perform reasonably well.
In MiniZinc 2.5.0, you can do something like this:
array[int, int] of int: a =
[| 1, 1,
| 2, 3,
| 3, 4 |];
set of int: Rows = index_set_1of2(a);
set of int: Cols = index_set_2of2(a);
int: values = card({ a[r, c] | r in Rows, c in Cols });
output ["\(values) values in "] ++
[if c == 1 then "\n" else "" endif ++
"\(a[r, c]) " | r in Rows, c in Cols];
I am working on the guide.elm-lang website on the Random example.
I am trying to add a feature that shows you the total number of times you threw the dice, and some stats on how many times you got each face.
To do this I've changed the model to look like this:
type alias Model =
{
die_face : Int,
total_throws : Int,
stats: Array.Array Int
}
and this is what I do to update the model:
{ model |
die_face = face,
total_throws = model.total_throws + 1,
stats = Array.set face ((Array.get face model.stats) + 1) model.stats
}
this throws an error that tells me:
This get call produces:
#Maybe# Int
But (+) only works with #Int# and #Float# values.
Which refers to Array.get not returning a Int but a Maybe and therefore I can't add it to the number 1.
I have tried using lists to achieve the same purpose but since they are not indexed I am not sure what to increment when I map over it. I am thinking of using records to do this and figure out a way to map the record keys to the face Int.
In general my question is. What is a good method to increment an element at index [x] of an Array in elm ? Or if I am just thinking about this wrong, what would be the elm way ?
Array.get returns a Maybe because it has to account for the case where the index is outside the array. The simplest way of getting around that is using Maybe.withDefault with a reasonable default value:
Array.set face (((Array.get face model.stats) |> Maybe.withDefault 0) + 1) model.stats
It might be a good idea to write a helper function for this though, to clean up the code a bit. Something like this:
incrementAt : Int -> Array Int -> Array Int
incrementAt index array =
case Array.get index array of
Just value ->
Array.set index (value + 1) array
Nothing ->
array
You can also use Array.Extra.update if you don't mind the extra dependency.
i am trying to make a model in minizinc that finds 3 numbers in sequence with the MaxSUM, in arrays below:
[2,3,4,**10,22,11**,17]).
[1,2,3,4,**10,22,11**,11,10,24]).
[2,3,4,5,10,23,**10,22,11**,17]).
I want my model to output these numbers, their indices and their sum.
I tried this:
array[int] of int : list1 = [2,3,4,10,22,11,17];
array[int] of int : list2 = [1,2,3,4,10,22,11,11,10,24];
array[int] of int : list3 = [2,3,4,5,10,23,10,22,11,17];
array[1..3] of var int: values;
array[1..3] of var int: indices;
constraint forall(i in 1..3, j in list1)(
values[i]=list1[j]
);
constraint exists (i in 1..length(list1)-2)(
exists(j in 1..length(list2)-2)(
exists(k in 1..length(list3)-2)
(list1[i]=list2[j]/\list2[j]=list3[k] /\
list1[i+1]=list2[j+1]/\list2[j+1]=list3[k+1]/\
list1[i+2]=list2[j+2]/\list2[j+2]=list3[k+2]
/\values[1]=list1[i]/\values[2]=list1[i+1]/\values[3]=list1[i+2]
/\indices[1]=i/\indices[2]=j/\indices[3]=k
)));
var int: max_sum;
constraint max_sum=sum(values);
solve maximize max_sum;
but, UNSATISFIABLE :(
Here are two hints.
Hint 1: The error states that there's something wrong at line 8, where j=3. If you comment out this constraint then there's no syntax error. Since I don't understand the purpose of this constraint I can't help you there.
Hint 2: Also, if you comment out that constraint (at line 8) then it might take a long time to get a solution - depending on the solver - since you have the decision variables values and indices set to var int. It's much better to state a positive domain for these two decision variables.
For example, I define a record as:
type a = {b : float; c: int list}
but I already know that this list must be of a predefined size, let's say 2 and if the list is not 2 it would be a different type or error since it is not defined such a type.
Is it possible to define the size of the list as happens in other languages that you must define the size?
Depending on the application this question can be applied to an array.
Maybe you should use an array instead of a list, since an array has a fixed length:
// create an array of length = 2, initialized with zeros.
let cValues : int[] = Array.create 2 0
cValues.IsFixedSize // returns true
EDIT: As others have suggested, a tuple might also be the way to go. For a pair (a tuple of length two), you can access the values using the fst and snd functions.
For a longer tuple, you can use pattern matching as shown below. If the tuple is too long to make this pattern matching approach practical, then you probably need a structure other than an F# tuple. Of course, one major requirement to consider is whether you need to store values of mixed types. A tuple or a record can store a mix of multiple types, whereas an array or list stores values of a single type.
let fourTuple = (5, 10, 2, 3)
let _,_,third,_ = fourTuple
printfn "%d" third // displays "2"
If an array or a tuple won't meet your requirements, then maybe you should use another record like this:
type ListOfC = {c1 : int; c2 : int}
type a' = {b' : float; c' : ListOfC}
Or you could create a new class that would meet your requirements, starting like the script below. Of course, this would probably not be considered idiomatic functional programming style. It's more like OOP.
type ListOfTwo(firstInt : int, secondInt : int) =
member this.First = firstInt
member this.Second = secondInt
let myListOfTwo = ListOfTwo(4, 5)
myListOfTwo.First
type a = {b : float; c : ListOfTwo }