Hi Alex,
Let me give some examples of set operations in AIMMS:
! Initialize the set order pool by assigning all orders initially to it.
s_orderPool := s_allOrders ;
! Construct a set of orders based on some condition.
s_orderInProduction := { i_order | bp_orderInProduction( i_order ) } ;
! Moving a particular order from one set to another:
ep_thisOrder := First( s_orderPool ); ! As an example, let's move the first order in the pool to the orders in production.
s_orderPool -= ep_thisOrder ; ! Remove the order from the pool.
s_orderInProduction += ep_thisOrder ; ! And add it to the orders in production.
Does that help?
With kind regards,
Chris
Hi @Chris Kuip ,
i havent tried it out yet. But i think that was exactly what i was looking
for.
Thank you very much.
Hey @Chris Kuip,
i have one more question regarding that topic.
The Elements in the order set have certain parameters related to them (e.g. due date, process time etc.) How can i assure that when an order moves from one set to another the same parameters are still “attached” to them?
An Answer is much appreciated.
With kind regards,
Alex
Hi Alex,
Assuming all order subsets are subsets of the set s_allOrders, and the index i_order is an index of the set s_allOrders, then declare the parameter p_dueDate as p_dueDate(i_order).
With such a declaration, moving an order from one subset of s_allOrders to another subset of s_allOrdes does not affect p_dueDate of that order.
Does this help?
With kind regards,
Chris
Hi Alex,
Let me give some examples of set operations in AIMMS:
! Initialize the set order pool by assigning all orders initially to it. s_orderPool := s_allOrders ;
! Construct a set of orders based on some condition. s_orderInProduction := { i_order | bp_orderInProduction( i_order ) } ;
! Moving a particular order from one set to another: ep_thisOrder := First( s_orderPool ); ! As an example, let's move the first order in the pool to the orders in production. s_orderPool -= ep_thisOrder ; ! Remove the order from the pool. s_orderInProduction += ep_thisOrder ; ! And add it to the orders in production.
Does that help?
With kind regards,
Chris
Hey @Chris Kuip
My Code is as follows:
for (j in OrderPool_AllOrders) do
if(PlannedReleaseDateOfOrder(j) <= TimeLimit) then
endif;
endfor;
In the if-Statemtent i want to move all Orders that fullfill the condition from the set OrderPool_AllOrders to the set OrderPool_InTimeLimit. I am not so sure how to do this with the operations mentioned above.
I thought i can maybe do it like this:
for (j in OrderPool_AllOrders) do
OrderPool_InTimeLimit := {j | PlannedReleaseDateOfOrder(j) <= TimeLimit}
endfor;
But then i get the error message: There is no operation defined for operator "<=" with arguments of data type element and data type numeric; the arguments themselves are "j $ PlannedReleaseDateOfOrder(j)" and "TimeLimit".
Sorry for asking so much questions, but i have never worked with Aimms and the model i have to implement is rather complex for me so i have a lot of points where i cant get it to work :(
Thank you in advance and kind regards
Alex
Hi Alex,
To create the set OrderPool_InTimeLimit you formulated that almost correctly.
There are two ways to improve:
First, the for statement is obselete, just bind the "j” in the set constructor as follows:
OrderPool_InTimeLimit := {j in OrderPool_AllOrders | some_condition}
Second (assuming PlannedReleaseDateOfOrder(j) is an element parameter), you can indeed not compare an element in an AIMMS set, with a numeric parameter. therefor you want to replace some_condition with something like
StringToMoment( format, unit, planningStartDate, PlannedReleaseDateOfOrder(j) ) <= TimeLimit
See also: https://documentation.aimms.com/functionreference/elementary-computational-operations/time-functions/stringtomoment.html
Let me know if you have questions about the above, or further questions.
With kind regards,
Chris
PS: there is one exception to not being able to compare the an element in an AIMMS set with a numeric parameter; that is when the AIMMS Set is a subset of the set AllIntegers.
Hi @Chris Kuip ,
Thank you for your help and time so far. It already helped me a lot, but i still have some problems to get the model to do the exact thing i want.
This is the first part, that works ok, in my opinion. (i is the index for the Workingstations and j the index for the Orders):
CurrentWorkloadOnStation(i) := StartingWorkloadOfStation(i);
OrderPool_InTimeLimit := {j in OrderPool_AllOrders| PlannedReleaseDateOfOrder(j) <= TimeLimit};
for (j in OrderPool_InTimeLimit) do
WorkloadIfOrderGetsReleased(i,j) := CurrentWorkloadOnStation(i) + (WorkloadOfOrderOnWorkstation(j,i) / NumberOfWorkstationInRouting(j,i));
endfor;
→ In this part i am just setting up the set with Orders that are inside a given time limit and prepare a chart with the Workload Contribution that each order gives to each station.
Then the second part is the actual release procedure and here things dont really work out as intended:
for (i in WorkingStations) do
for (j in OrderPool_InTimeLimit) do
ThisOrder := First (OrderPool_InTimeLimit);
if(CurrentWorkloadOnStation (i) + WorkloadIfOrderGetsReleased(i,j) <= WorkloadNormOfWorkstations) then
CurrentWorkloadOnStation(i) := CurrentWorkloadOnStation(i) + WorkloadIfOrderGetsReleased(i,j);
OrderPool_InTimeLimit -= ThisOrder;
OrdersInProduction += ThisOrder;
else
OrderPool_NextPeriod += ThisOrder;
endif;
endfor;
endfor;
→ What should happen is:The first order in the OrderPool_InTimeLimit gets selected and when the workloadcontribution for this order doesnt hurt the WorkloadNorm of any station it gets released and therefore switched to the set OrdersInProduction. If workloadnorms are violated it just gets moved into the next Period, where it will be checked again.
BUT: The Problem here is i cant seem to view each order seperatly, like i intend to with the Ep “ThisOrder” , cause i cant use the if-statement only for the workload of “ThisOrder”. I also have tried the same code but without all the lines including “ThisOrder” and shifting it between sets but then again the mechanism just releases every possble part until the Workloadnorm for each workstation is met. (For example if Station 1 has still workload left for Order5 it will ad the Workload part from Order 5 for station 1 but not for Station 3 if the workload is already full, so Orders are released partly while they should only be released as a whole).
I know this is very much text, but I hope I could explain my problem in an understandable way and if not feel free to ask where I can explain it better. I am thankyful for every advice I can get.
With kind regards,
Alex
Hi @Chris Kuip ,
Thank you for your help and time so far. It already helped me a lot, but i still have some problems to get the model to do the exact thing i want.
This is the first part, that works ok, in my opinion. (i is the index for the Workingstations and j the index for the Orders):
CurrentWorkloadOnStation(i) := StartingWorkloadOfStation(i);
OrderPool_InTimeLimit := {j in OrderPool_AllOrders| PlannedReleaseDateOfOrder(j) <= TimeLimit};
for (j in OrderPool_InTimeLimit) do
WorkloadIfOrderGetsReleased(i,j) := CurrentWorkloadOnStation(i) + (WorkloadOfOrderOnWorkstation(j,i) / NumberOfWorkstationInRouting(j,i));
endfor;
→ In this part i am just setting up the set with Orders that are inside a given time limit and prepare a chart with the Workload Contribution that each order gives to each station.
Then the second part is the actual release procedure and here things dont really work out as intended:
for (i in WorkingStations) do
for (j in OrderPool_InTimeLimit) do
ThisOrder := First (OrderPool_InTimeLimit);
if(CurrentWorkloadOnStation (i) + WorkloadIfOrderGetsReleased(i,j) <= WorkloadNormOfWorkstations) then
CurrentWorkloadOnStation(i) := CurrentWorkloadOnStation(i) + WorkloadIfOrderGetsReleased(i,j);
OrderPool_InTimeLimit -= ThisOrder;
OrdersInProduction += ThisOrder;
else
OrderPool_NextPeriod += ThisOrder;
endif;
endfor;
endfor;
→ What should happen is:The first order in the OrderPool_InTimeLimit gets selected and when the workloadcontribution for this order doesnt hurt the WorkloadNorm of any station it gets released and therefore switched to the set OrdersInProduction. If workloadnorms are violated it just gets moved into the next Period, where it will be checked again.
BUT: The Problem here is i cant seem to view each order seperatly, like i intend to with the Ep “ThisOrder” , cause i cant use the if-statement only for the workload of “ThisOrder”. I also have tried the same code but without all the lines including “ThisOrder” and shifting it between sets but then again the mechanism just releases every possble part until the Workloadnorm for each workstation is met. (For example if Station 1 has still workload left for Order5 it will ad the Workload part from Order 5 for station 1 but not for Station 3 if the workload is already full, so Orders are released partly while they should only be released as a whole).
I know this is very much text, but I hope I could explain my problem in an understandable way and if not feel free to ask where I can explain it better. I am thankyful for every advice I can get.
With kind regards,
Alex
Another try I did looked like this:
ThisOrder := first (OrderPool_InTimeLimit);
CurrentOrder += ThisOrder;
for (j in CurrentOrder) do
for (i in WorkingStations) do
if(CurrentWorkloadOnStation (i) + WorkloadIfOrderGetsReleased(j,i) <= WorkloadNormOfWorkstations(i)) then
CurrentWorkloadOnStation(i) := CurrentWorkloadOnStation(i) + WorkloadIfOrderGetsReleased(j,i);
CurrentOrder -= ThisOrder;
OrdersInProduction += ThisOrder;
endif;
endfor;
endfor;
This allows me to release only the first order, but i cant figure out how to repeat this process until the Set OrderPool_InTimeLimit is empty.