Using forall in minizinc with an array set (not contiguous) - minizinc

I'm trying to use a forall instance to add a constraint but I got this error and I'm not sure which should I do.
(array slice must be contiguous)
in call 'forall'
in array comprehension expression
with i = {10,24}
in binary '<=' operator expression
in call 'slice_1d'
I am working in a schedulling problem, and I need to apply a restriction which determines that a set of tasks (determined by suc) can only starts after a specific task (determined by 1..nTasks) is already finished.
The model follows
include "globals.mzn";
int: n_res;
array [1..n_res] of int: res_cap;
int: n_tasks;
array [1..n_tasks] of int: duration;
array [1..n_res, 1..n_tasks] of int: res_req;
array [1..n_tasks] of set of int: suc;
int: t_max = sum(i in 1..n_tasks)(duration[i]);
array [1..n_tasks] of var 0..t_max: start;
array [1..n_tasks] of var 0..t_max: end;
var 0..t_max: makespan;
% constraint that I can't implement. this constraint should make every task[i] to start after a set of tasks{i} are finished. The set is defined by the array suc.
constraint forall (i in suc)(end[i] <= start[i]);
constraint cumulative(start, duration, row(res_req, 1), res_cap[1]);
constraint cumulative(start, duration, row(res_req, 2), res_cap[2]);
constraint cumulative(start, duration, row(res_req, 3), res_cap[3]);
constraint cumulative(start, duration, row(res_req, 4), res_cap[4]);
constraint forall(i in 1..n_tasks)(end[i] = start[i]+duration[i]);
constraint makespan = max(i in 1..n_tasks)(end[i]);
solve minimize makespan;
The arrays suc and 1..nTasks have the same number of lines.
I have a 1d array with the specific sets of tasks that can start after the task[i] is over.
In a smaller instance, for example:
suc = [{5, 15}, {17, 23, 28}, {10, 12}, {8}]
What i need to implement is:
end[i] | i in 1..nTasks <= start[i] | i in suc
For the specific set that I posted, it could be done manually like this:
end[1] <= start[5]
end[1] <= start[15]
end[2] <= start[17]
end[2] <= start[23]
end[2] <= start[28]
end[3] <= start[10]
end[3] <= start[12]
end[4] <= start[8]
I just start using minizinc and something tells me that I'm missing something that may be simple, however, it's been a while and I can't implement it.
How can I write a forall instance that can do this?

The culprit is this constraint (as the error indicates):
constraint forall (i in suc)(end[i] <= start[i]);
where you trying use suc as a generator for the loop. The problem is that you want two things for this constraint: the start of the current task should be before the successor of that task. And this is not possible using your approach since i will have value such as { 10, 24 }, but there is no value (reference) of the current task (i.e. the value of start[i]).
Here is a way of solving this: Use i in n_res to loop through all the tasks (i is the i'th task), and then loop through suc[i] to get the successors of each task.
constraint forall (i in 1..n_res) (
forall(s in suc[i]) (
end[i] <= start[s]
)
);
Another way, which is perhaps simpler, is to combine the two forall loops into one loop:
constraint forall (i in 1..n_res, s in suc[i]) (
end[i] <= start[s]
);
When I ran the model it generated this solution:
% obj = 51
start = array1d(1..30, [7, 21, 4, 31, 6, 41, 34, 3, 35, 39, 21, 28, 47, 0, 38, 48, 44, 35, 28, 7, 10, 34, 11, 47, 41, 3, 11, 3, 22, 17]);
end = array1d(1..30, [17, 25, 5, 34, 11, 51, 35, 7, 41, 47, 28, 35, 51, 3, 48, 51, 48, 38, 35, 12, 11, 44, 19, 48, 47, 7, 18, 9, 31, 21]);
makespan = 51;
----------
% obj = 51
==========

Related

How to collect values every n seconds with a max count in each interval from a signal in ReactiveSwift?

It seems like a combination of collect(every:on:skipEmpty:discardWhenCompleted:) and collect(count:) in ReactiveSwift.
The resulting signal would send an event every n seconds if the count of accumulated values doesn't reach max count during each time interval. But if in a specific time interval, the count of values has reached max count, it will send immediately.
For example, timeInterval = 2s, maxCount = 2
interval 1: received two values [1, 2], forward them at end of interval 1
interval 2: received one value [3], forward them at end of interval 2
interval 3: received three values [5, 6, 7] ( 3 values > maxCount), forward [5, 6] immediately when 7 is received and 7 is regarded as received value in interval 4 (interval 3 stopped early)
Question is hard to grasp, but I will try.
If you want to batch emitted values by count and time, you can use bufferTimeout method. See documentation here https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Flux.html#bufferTimeout-int-java.time.Duration-
Some example:
void bufferTimeoutTry() throws InterruptedException {
Flux.interval(Duration.ofMillis(157))
.filter(time -> time > 20 && time < 38 || time % 5 == 0 || time % 17 == 0)
.bufferTimeout(5, Duration.ofSeconds(1))
.doOnNext(list -> {
// we will get list of items buffered in 1-second period of time, or at most 5 items.
})
.subscribe(System.out::println);
Thread.sleep(30000);
}
Output will be list of items. Flux.interval is generating sequential long number (i.e. 1, 2, 3, 4, 5, ...), it is filtered on second line of method (to get some non interval behavior) and than buffer-ed. After buffer, there is no long on stream, but it has changed to list of longs.
[0, 5]
[10, 15]
[17, 20, 21, 22, 23]
[24, 25, 26, 27, 28]
[29, 30, 31, 32, 33]
[34, 35, 36, 37, 40]
[45, 50, 51]
[55, 60]
[65, 68, 70]
[75, 80]
[85, 90]
[95, 100]
[102, 105]
[110, 115]
[119, 120, 125]
[130, 135, 136]
[140, 145]
[150, 153, 155]
[160, 165]
[170, 175]
[180, 185]
Is this what you want?

The ten's digit and unit's digit of numbers

I have this code
int[,] array = new int[,]{ {34, 21, 32, 41, 25},
{14 ,42, 43, 14, 31},
{54, 45, 52, 42, 23},
{33, 15, 51, 31, 35},
{21, 52, 33, 13, 23} };
for (int i = 0; i < array.GetLength(1); i++)
{
for (int j = 0; j < array.GetLength(0); j++)
{
Console.Write(array[i, j] + " ");
}
Console.WriteLine();
}
and i need to find a specific number ( the treasure ).
For each value the ten's digit represents the row number and the unit's digit represents the column number of the cell containing the next clue.
Starting in the upper left corner (at 1,1), i have to use the clues to guide me search of the array. (The first three clues are 11, 34, 42).
The treasure is a cell whose value is the same as its coordinates.
The program should output the cells it visits during its search.
I did the simply way:
Console.WriteLine("The next clue is: {0}", array[0, 0]);
Console.WriteLine("The next clue is: {0}", array[2, 3]);
Console.WriteLine("The next clue is: {0}", array[3, 2]);
Console.WriteLine("The next clue is: {0}", array[0, 4]);
and so on, but the problem is, that if I change the array to set another route the program will output the wrong way. So the solution needs to be dynamic and find the treasure regardless of the array content.
My problem is that i don't know how to do to find the ten's digit of the numbers and the unit's digit.
Can anyone please help me with this?
To illustrate my comment: code below and Fiddle
(I've added a HashSet<int> to track which cells have already been visited and avoid ending up with an infinite loop)
int[,] array = new int[,]
{
{34, 21, 32, 41, 25},
{14 ,42, 43, 14, 31},
{54, 45, 52, 42, 23},
{33, 15, 51, 31, 35},
{21, 52, 33, 13, 23}
};
int currentCoordinates = 11;
bool treasureFound = false;
var visitedCells = new HashSet<int>();
while (!treasureFound && !visitedCells.Contains(currentCoordinates))
{
int currentRowIndex = currentCoordinates / 10;
int currentColumnIndex = currentCoordinates % 10;
int nextCoordinates = array[currentRowIndex - 1, currentColumnIndex - 1];
if (nextCoordinates == currentCoordinates)
{
treasureFound = true;
}
else
{
visitedCells.Add(currentCoordinates);
currentCoordinates = nextCoordinates;
}
}
if (treasureFound)
{
Console.WriteLine($"Treasure found in cell {currentCoordinates}");
}
else
{
Console.WriteLine("No treasure");
}

Observable.switchMap does not interrupt Observable

I don't understand why switchMap doesn't work as expected.
At first case switchMap doesn't interrupt Observable but at second case it works as expected. Please, explain that behaviour.
val test = TestObserver<Int>()
Observable.fromArray(10, 20)
.switchMap({
// 1. switchMap does not interrupt generator
Observable.generate(
Callable{
generateSequence(it, { n -> if (n < it + 9) n + 1 else null}).iterator()
},
BiConsumer<Iterator<Int>, Emitter<Int>>(){ data, emitter ->
if (data.hasNext()) {
Thread.sleep(100)
emitter.onNext(data.next())
}else {
emitter.onComplete()
}
}
)
// 2. switchMap disposes observable
//Observable.just(it).delay(1, TimeUnit.SECONDS)
},2)
.subscribeWith(test)
test.await()
// 1. >> [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
// But I expect [20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
// 2. >> [20]
print(test.values())
What I want to do.
In reality my generator do hard work based on value from switchMap and I want interrupt this work if new value is appeared. At the beginning generator start transaction and at the end generator commits or cancels transaction.

How to return an array with unhappy numbers removed?

I'm quite new to using MATLAB, and am still trying to understand how to make this particular function. I understand the formula for performing this on paper, but I'm having trouble translating it into the required MATLAB syntax.
How would a function be written such that it takes an array of numbers, and returns that array with unhappy numbers removed i.e. only happy numbers remaining?
EDIT - Proving and input and output
Input:
array = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
Output:
array = [7, 13, 19, 23, 31, 79, 97]
A happy number is such that a number's squared digits summed eventually equal to 1, or continue the process indefinitely as seen here.
I've written a small function (which might be further improved) to test the "happines" of a number.
Current version only works with scalar and one dim. array.
Input: the scalar or array to be tested
Output:
1) an index: happy (1) unhappy(0)
2) the list of happy number within the input set
3) the list of unhappy number within the input set
Running the function with the input specified in the question, the function returns:
function [is_happy,h_array,unh_array]=happy_number(in_val)
%
% Output:
% is_happy: 1 ==> the numberis happy
% 0 ==> the numberis unhappy
% h_array: happy numbers within input
% unh_array: unhappy numbers within input
%
% Input validity check (to be improved)
s=size(in_val);
if(iscell(in_val) || isstr(in_val) || isstruct(in_val) ...
|| ~find(s,1) || length(s) >= 3 || sum(floor(in_val)-in_val) ~= 0)
error('Only scalar or 1 dim array supported')
end
% Vars initialization
h_array=[];
unh_array=[];
h_array_cnt=1;
unh_array_cnt=1;
h_unh_cnt=1;
% Loop through input number
for i=1:length(in_val)
seq=[];
n=in_val(i);
seq_cnt=1;
seq(seq_cnt)=n;
% Test if the number is happy
while(n ~= 1 && n ~= 4)
% Decompose the number in its digits
sn=num2str(n);
nv=str2num(sn(:));
seq_cnt=seq_cnt+1;
seq(seq_cnt)=sum(nv.^2);
n=seq(seq_cnt);
end
% Set and display results
if(n == 1)
disp(['Number ' num2str(seq(1)) ' is HAPPY'])
is_happy(h_unh_cnt)=1;
h_unh_cnt=h_unh_cnt+1;
h_array(h_array_cnt)=seq(1);
h_array_cnt=h_array_cnt+1;
else
disp(['Number ' num2str(seq(1)) ' is UNHAPPY'])
is_happy(h_unh_cnt)=0;
h_unh_cnt=h_unh_cnt+1;
unh_array(unh_array_cnt)=seq(1);
unh_array_cnt=unh_array_cnt+1;
end
end
Hope this helps.
If you have the index of your unhappy numbers. You can remove them by writing :
array(unhappy_index) = [];
If you do not have the unhappy index, you can find them by using the followng command:
find()

Range inside switch case statement in Coffeescript

I am using Handlebar in my Rails 3.2 jquery mobile application.
I am trying to write a switch case statement inside a Coffeescript method like
Handlebars.registerHelper 'status', (blog) ->
switch(parseInt(blog.status))
when [0..20]
status = "active"
when [20..40]
status = "Moderately Active"
when [40..60]
status = "Very Active"
when [60..100]
status = "Hyper Active"
return status
I am not getting any result . How to use range in when . Please suggest
Your switch won't work as Cygal notes in the comments (i.e. see issue 1383). A switch is just a glorified if(a == b) construct and you need to be able to say things like:
a = [1,2,3]
switch a
...
and have it work when you switch on an array. The CoffeeScript designers thought adding a (fragile) special case to handle arrays (which is all [a..b] is) specially wasn't worth it.
You can do it with an if:
Handlebars.registerHelper 'status', (blog) ->
status = parseInt(blog.status, 10)
if 0 <= status <= 20
'Active'
else if 20 < status <= 40
'Moderately Active'
else if 40 < status <= 60
'Very Active'
else if 60 < status <= 100
'Hyper Active'
else
# You need to figure out what to say here
Or with short circuiting returns like this:
Handlebars.registerHelper 'status', (blog) ->
status = parseInt(blog.status, 10)
return 'Something...' if status <= 0
return 'Active' if status <= 20
return 'Moderately Active' if status <= 40
return 'Very Active' if status <= 60
return 'Hyper Active' if status <= 100
return 'Something else' # This return isn't necessary but I like the symmetry
Note that you have three special cases that you need to add strings for:
status < 0.
status > 100.
status is NaN. This case would usually fall under the final "it isn't less than or equal to 100" branch since NaN => n and NaN <= n are both false for all n.
Yes, you're absolutely certain that the status will always fall within the assumed range. On the other hand, the impossible happens all the time software (hence the comp.risks mailing list) and there's no good reason to leave holes that are so easily filled.
Also note the addition of the radix argument to the parseInt call, you wouldn't want a leading zero to make a mess of things. Yes, the radix argument is optional but it really shouldn't be and your fingers should automatically add the , 10 to every parseInt call you make.
Adding a tiny bit to mu is too short's answer, you can transform its second code snippet into a switch expression:
Handlebars.registerHelper 'status', (blog) ->
status = parseInt(blog.status, 10)
switch
when status <= 0 then 'Something...'
when status <= 20 then 'Active'
when status <= 40 then 'Moderately Active'
when status <= 60 then 'Very Active'
when status <= 100 then 'Hyper Active'
else 'Something else'
This is basically equivalent to doing a switch (true) in JavaScript (though the CS compiler will generate a switch (false) statement with the negated conditions to ensure boolean results from the expressions... i think).
And the reason why the switch over ranges doesn't work is that ranges literals in CS represent plain old JS arrays (though the compiler will do some optimization tricks when doing something like for i in [1..something]), so when they are found inside a switch they are treated just like normal array values:
// Generated JS for question's CS code:
switch (parseInt(blog.status)) {
case [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]:
status = "active";
break;
case [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40]:
status = "Moderately Active";
break;
case [40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]:
status = "Very Active";
break;
case (function() {
_results = [];
for (_i = 60; _i <= 100; _i++){ _results.push(_i); }
return _results;
}).apply(this):
status = "Hyper Active";
}
The value inside the switch statement is basically compared to each case value using ===, which only works for primitives, not for arrays (and even if it worked for arrays, it would be testing array equality, not if the switched value is contained in the caseed arrays).