Schedule minizinc no overlapping - constraints

I want to do a schedule with no overlapping only 1 teacher can be booked at 1 timeslot. I want to create a 2darray like teachers a rows and timeslot is coloumns.

The general constraints to use for these kind of constraints ("something should be distinct") are the two global constraints all_different or alldifferent_except_0.
Note: I changed to 3 teachers, 3 timeslots, and 5 presentations to make a more general point of using alldifferent_except_0, since there can be assignments where there are no teacher/timeslot for a presentation.
Also, I'm not sure I would use the specific representation as you did, since it the representation depends on further constraints (if any) in the model.
Here are some approaches that might be useful.
1) Simple model with just a "timetable" matrix
If you only want to assign T teachers, TS timeslots, and P presentations with no further constraints, then a single constraint "all_different_except_0" on a timetable matrix will suffice (together with a sum explained below). The dimension of "timetable" is T x TS (Teachers x Timeslots) where we assign the presentation, or 0 if there is no presentation for this teacher and timeslot.
include "globals.mzn";
set of int: Timeslots = 1..3;
set of int: Teachers = 1..3;
set of int: Presentations = 1..5;
solve satisfy;
% Decision variables
array[Teachers, Timeslots] of var {0} union Presentations: timetable;
constraint
alldifferent_except_0(array1d(timetable))
% ensure that there are 5 assigned presentations
/\ sum([timetable[t,ts]>0 | t in Teachers, ts in Presentations]) = card(Presentations)
;
% output [....];
The drawback of this model is that it's not easy to state further constraints that might be needed, and also that we have to count the number of non-0 assignments in the "timetable" matrix to ensure that there are exactly 5 presentations assigned.
So we will expand with more decision variables.
2) Adding decision variables
This model connects the original presentation with the "timetable" matrix and its constraint shown above. This means that we can keep the constraint on "timetable" to ensure unicity and we can work with constraint on the other decision variables as well. Here's a model with the two original arrays "presentation_teacher" and "presentation_time" and their constraints.
include "globals.mzn";
set of int: Timeslots = 1..3;
set of int: Teachers = 1..3;
set of int: Presentations = 1..5;
% Decision variables
% Which teacher has this presentation
array[Presentations] of var Teachers: presentation_teacher;
% Which timeslot for this presentation
array[Presentations] of var Timeslots: presentation_time;
% Which combination of teacher and timeslot for a presentation, if any
array[Teachers, Timeslots] of var {0} union Presentations: timetable;
solve satisfy;
constraint
alldifferent_except_0(array1d(timetable))
% This constraint is not needed now
% /\ sum([timetable[t,ts]>0 | t in Teachers, ts in Presentations]) = card(Presentations)
/\ % connect timetable and presentation_teacher and presentation_time
forall(p in Presentations) (
timetable[presentation_teacher[p],presentation_time[p]] = p
)
;
The constraint "forall(p in Presentations) ( ... ) " connects the two representations: the "timetable" representation and the two added arrays.
3) Alternative version
An alternative version of ensuring distinct timeslots and presentations for the teachers is to add constraints on the "presentation_teacher", "presentation_time". This don't really need a timetable matrix so it's skipped here. (One can add these constraints with the timetable approach might be faster.)
include "globals.mzn";
set of int: Timeslots = 1..3;
set of int: Teachers = 1..3;
set of int: Presentations = 1..5;
% Decision variables
% Which teacher has this presentation
array[Presentations] of var Teachers: presentation_teacher;
% Which timeslot for this presentation
array[Presentations] of var Timeslots: presentation_time;
solve satisfy;
constraint
% variant A
forall(t in Teachers) (
% the time for this teacher is distinct (or 0)
alldifferent_except_0([presentation_time[p] * (presentation_teacher[p]=t) | p in Presentations])
)
/\
% variant B
forall(t in Teachers) (
% combination of (time + teacher) for this teacher is unique
alldifferent([presentation_time[p]+(presentation_teacher[p]*card(Presentations)) | p in Presentations])
)
;
This model has two variants, where the first ("A") use alldifferent_except_0 to ensure that the presentations for each teacher are distinct.
For each teacher it loops through all the presentations ("p") and picks those time assigned for "this" teacher and ensures that they are distinct.
The second variant ("B") is kind of a hack, though quite useful sometimes: It builds an list of integers for which the teacher is assigned ( time + teacher_id * number of presentations) and ensure that these are distinct.
Since this model don't have an explicit timetable one have to extract the timetable in the output. Here is one way:
output [
"Teacher " ++ show(t) ++ " has these presentations" ++ show([p | p in Presentations where fix(presentation_teacher[p]) = t]) ++ "\n"
| t in Teachers
]
;
As mentioned above, the representation of the model (which decision variables to select) depends much on what one want to do further.

Related

Recurrence Analysis (Time complexity)

im writing a boolean function that calculate if two binary trees are identical.
Lets see the program:
boolean func(Node head1 , Node head2){
if(head1 == null || head2 == null) return head1 == null && head2 == null;
return func(head1.left , head2.left) && (head1.right,head2.right);
}
i know that in the worst case the program check n element so its O(n).
and i want to describe this recurrence function in T(n).
i dont know were to start becuse i dont know what is the value of the stopping point ,
i think that the function is T(n,m) = 2*t(n-1,m-1) + n + m.
Let n be the number of nodes in the binary trees. If the binary trees have different number of nodes, then n is smaller of the two sizes (since you'll stop comparing once you reach the end of one tree).
On each call you are doing some comparisons between the nodes of the tree. This will be in constant time, so you can call this time spent d which represents some arbitrary constant.
Lastly, you're making 2 recursive calls for the current node's 2 children. Note that in the worst case, each of the children are the root of a subtree that holds half the total number of nodes in the tree. In other words if you have a tree with n nodes, and you are looking at the root node, then each child of the root has about n/2 nodes below it (and including it).
So your recurrence is as follows:
T(n) = 2*T((n-1)/2) + d
You can simplify this to:
T(n) = 2*T(n/2) + d

Pyomo constraint > 100000 OR 0

All,
I am working on some code where there is a requirement to buy/sell a minimum of 100,000 packets. If not possible then this should be zeroed.
I have tried a number of things for things for this including:
def objective_rule(model):
return sum(model.Prices[ProductCount]*model.Amount[ProductCount]*(model.Amount[ProductCount]>100000) for ProductCount in model.Products)
But this is slower than expected.
I would like to put an explicit constraint in place. Something akin to:
def minTradesize_Constraint(model):
return ((model.Amount[ProductCount]>=100000)| \
(model.Amount[ProductCount]==0.00) for ProductCount in model.Products)
I have looked at indicator functions but the Pyomo continuous approximations don't help.
Any help/guidance appreciated.
Basically, what you are trying to achieve is make the model.Amount[ProductCount] terms take discontinuous values (zero or larger or equal to 100,000). To achieve that, first, you will basically need to define a binary variable: model.y = pyomo.Var(model.Products, within=pyomo.Binary).
Then you will need to add the following constraints:
def minTradesize_Constraint1(model):
return (model.Amount[ProductCount] >= 100000 * y[ProductCount] for ProductCount in model.Products)
def minTradesize_Constraint2(model):
return (model.Amount[ProductCount] <= M * y[ProductCount] for ProductCount in model.Products)
where M is a sufficiently large number (can be a realistic upper bound for your model.Amount[ProductCount] variable).
As a result of this formulation, if y[ProductCount] is zero, then the model.Amount[ProductCount] term will also be zero. If the model wants now to make model.Amount[ProductCount] variable take positive values, it will have to set the binary y[ProductCount] to 1, hence, forcing model.Amount[ProductCount] to become larger or equal to 100,000.
Note: I have formulated the constraints in the same style that you did in your answer. However, if I understand your model correctly, I would say that the first constraint, for instance, should be:
def minTradesize_Constraint1(model, ProductCount):
return (model.Amount[ProductCount] >= 100000 * y[ProductCount]
and the for ProductCount in model.Products part should be added when you create the Pyomo constraint.
to simplify the solution even further. I added a variable called route_selected
model.route_selected = pe.Var(<a set, for me its routes == r>, domain=pe.Binary, initialize=0, within=pe.Binary)
model.route_selected = pe.Var(model.R, domain=pe.Binary, initialize=0, within=pe.Binary)
thats my dependent variable looks
# Variable to solve, this is the variable that will be changed by solver to find a solution
# for each route, port, cust, year combination what should be supplied amount
model.x_rpcy = pe.Var(self.model.R, self.model.P, self.model.C, self.model.Y, domain=pe.NonNegativeIntegers, initialize=0)
and then added this constraint
for y in self.model.Y:
for r in self.model.R:
lhs = sum(self.model.x_rpcy[r, p, c, y] for p in self.model.P for c in self.model.C)
vessel_size = 1000
self.model.const_route.add(lhs == vessel_size * self.model.route_selected[r])
model.const_route.add(lhs == vessel_size * model.route_selected[r])

Need review of scheduling model logic, suggestions for constraint creation and fixes for syntax errors

I am creating a scheduling model for a blending facility in Mini Zinc. I have asked a similar question earlier but I have since progressed. I will summarize what I think my existing model should do, it would be super helpful if someone could correct any logical or syntax errors I have made. The model currently errors, with several instances of "expecting end of file". It seems way to simplistic in comparison to several other sequence dependent scheduling models I have found. Below you will find the model code commented with my understanding of each line.
Besides an overview of the logic and syntax, I am looking for help with the "missing constraint" in this model, which needs to require that the array of blends [y] contain no more than the declared integer quantity of each blend.
Notable future goals for this model include automatic generation of the blendcost matrix, output the schedule array given a starting day into a 5 column matrix representing weekdays, and showing the blend name as opposed to blend number.
enum Blends = { A, B, C, D, E, F};
%Establish names for each blend and link them to their order number.
int: nb = count([Blends])
%Count the number of blends, plan to use later.
int: qA; %Error: syntax error, unexpected int, expecting end of file
int: qB;
int: qC;
int: qD;
int: qE;
int: qF;
int: sb;
%Call for inputs of the quantity of each of the blends needed, as well as the number/letter of the blend currently in the machine.
int: mc = qA + qB + qC + qD + qE + qF;
%Sum the blend quantities to determine total number of blends
[Blendcost] : [|1,2,2,2,2,2,|1,1,1,1,1,1,|1,1,1,1,1,1,|2,2,2,1,2,2,|1,1,1,1,1,1,|1,1,1,1,1,1,|]; %Error: syntax error, unexpected [|, expecting identifier
%Establishes a blend cost matrix, 6X6 depicting the transition costs from any blend A-F to any other blend A-F
array [Blends] of int: 1..6;
%Is this line needed to establish the link between A/1, B/2, C/3 etc;? Or is that taken care of when Blends is enumerated?
array [0..mc] of var 1..6: y;
%Create an array from 0 to the number of blends with potential values from 1-6, corresponding to the blend numbers.
%Missing constraint: [y] can contain no more than the quantity of each blend declared above, except for the blend declared in the starting blend, which will be allowed that blend quantity + 1
constraint y(0) = sb
%y(0) is set equal to the starting blend Letter/Number Defined earlier, used to determine the first transitionary cost.
array [1..mc] of int: x(i); %Error: syntax error, unexpected array, expecting end of file
%Create an array from 1 to number of blends, which will be filled with the transition costs in response to variations in y
constraint forall(i in x)(x(i) = Blendcost(y(i-1),y(i)))
%For each space in x, x will equal the blend cost value obtained from the previous blend in the y array vs the next blend in the y array
solve minimize sum (x); %Error: syntax error, unexpected solve, expecting end of file
%Solves this model attempting to minimize the sum of the x array, which should be filled with the transition costs.
show(y):
%Print the final array of blend numbers that has minimized blend cost transition.
%Error: unexpected end of file, expecting identifier.
Here is a basic version of your CP-model that runs (assuming some demand q):
enum BLEND = { A, B, C, D, E, F};
array[BLEND] of int: q = [1, 2, 4, 6, 8, 1];
array[BLEND, BLEND] of int: Blendcost =
[|1,2,2,2,2,2|1,1,1,1,1,1|1,1,1,1,1,1|2,2,2,1,2,2|1,1,1,1,1,1|1,1,1,1,1,1|];
int: mc = sum(q);
array[1..mc] of var BLEND: y;
include "global_cardinality.mzn";
constraint global_cardinality(y, BLEND, q);
var int: obj = sum(p in 1..mc-1)(Blendcost[y[p],y[p+1]]) + 1;
array[int] of var opt BLEND: day = [y[p] | p in 1..mc-1, q in 1..max(Blendcost) where q <= Blendcost[y[p],y[p+1]]] ++ [y[mc]];
array[int] of var opt int: wash = [bool2int(q > 1) | p in 1..mc-1, q in 1..max(Blendcost) where q <= Blendcost[y[p],y[p+1]]] ++ [0];
solve minimize obj;
output ["obj=\(obj)\n"] ++
["day=\n"] ++ [
show(day[d]) ++ if fix(wash[d]) > 0 then "W" else "" endif ++ " " ++
if d mod 5 = 0 then "\n" else "" endif | d in 1..length(day)
] ++ ["\nmc=\(mc)\n"] ++ ["y=\(y)\n"] ++ ["wash=\(wash)\n"]
Have a look at https://www.minizinc.org/doc-2.2.3/en/lib-globals.html#counting-constraints for alternative versions of the counting constraint.
For larger instances a MIP-model might show better performance.

Weighted randomization based on runtime data in System Verilog

Is there a way to do weighted randomization in System Verilog based on runtime data. Say, I have a queue of integers and a queue of weights (unsigned integers) and wish to select a random integer from the first queue as per the weights in the second queue.
int data[$] = '{10, 20, 30};
uint_t weights[$] = '{100, 200, 300};
Any random construct expects the weights hardcoded as in
constraint range { Var dist { [0:1] := 50 , [2:7] := 50 }; }
But in my case, I need to pick an element from an unknown number of elements.
PS: Assume the number of elements and weights will be the same always.
Unfortunately, the dist constraint only lets you choose from a fixed number of values.
Two approaches I can think of are
Push each data value into a queue using the weight as a repetition count. In your example, you wind up with a queue of 600 values. Randomly pick an index into the queue. The selected element has the distribution you want. An example is posted here.
Create an array of ranges for each weight. For your example the array would be uint_t ranges[][2]'{{0,99},{100,299},{300,599}}. Then you could do the following in a constraint
index inside {[0:weights.sum()-1]};
foreach (data[ii])
index inside {[ranges[ii][0]:ranges[ii][1]} -> value == date[ii];

Can any set of numbers be expressed by a function?

Is it possible to express ANY random set of numbers by a function?
Question clarification:
for example:
if desired result set = {1,2,3,4,5}
so I don't mean something like this:
function getSet(){
return {1,2,3,4,5};
}
but more like this:
function genSet(){
result = {}
for(i=0;i<5;i++){
result.push(i);
}
return result;
}
So in other words, can there be a logic to calculate any desired set?
There is a lot of mathematics behind this question. There are some interesting results.
Any set of (real) numbers can be define by a polynomial function f(x) = a + b x + c x^2 + ... so that a number is in the set if f(x)=0. Technically this is an algebraic curve in 1D. While this might seem a optimistic result there is not limit on how complex the polynomial could be and polynomials above the degree 5 have no explicit result.
There is a whole field of study on Computable numbers, real numbers which can be can be computed to within any desired precision by a finite, terminating algorithm, and their converse: non computable numbers, which can't. The bad news is there are a lot more non-computable numbers than computable ones.
The above has been based on real numbers which are decidedly more tricky than the integers or even a finite set of integers which is all we can represent by int or long datatypes. There is a big field of study in this see Computability theory (computer science). I think the Turings halting problem come in to play, this is about if you can determine if a algorithm will terminate. Unfortunately this can't be determined and a consequence is "Not every set of natural numbers is computable." The proof of this does require the infinite size of the naturals so I'm not sure about finite sets.
Representations
There are two common representations used for sets when programming. Suppose the set S is a subset of some universe of items U.
Membership Predicate
One way to represent the set S is a function member from S to { true, false }. For all x in U:
member(x) = true if x is in S
member(x) = false if x is not in S
Pseudocode
bool member(int n)
return 1 <= n <= 5
Enumeration
Another way to represent the S is to store all of its members in a data structure, such as a list, hash table, or binary tree.
Pseudocode
enumerable<int> S()
for int i = 1 to 5
yield return i
Operations
With either of these representations, most set operations can be defined. For example, the union of two sets would look as follows with each of the two representations.
Membership Predicate
func<int, bool> union(func<int, bool> s, func<int, bool> t)
return x => s(x) || t(x)
Enumeration
enumrable<int> union(enumerable<int> s, enumerable<int> t)
hashset<int> r
foreach x in s
r.add(x)
foreach x in t
if x not in r
r.add(x)
return r
Comparison
The membership predicate representation can be extremely versatile because all kinds of set operations from mathematics can be very easily expressed (complement, Cartesian product, etc.). The drawback is that there is no general way to enumerate all the members of a set represented in this way. The set of all positive real numbers, for example, cannot even be enumerated.
The enumeration representation typically involves much more expensive set operations, and some operations (such as the complement of the integer set {1, 2, 3, 4, 5}) cannot even be represented. It should be chosen if you need to be able to enumerate the members of a set, not just test membership.

Resources