use of sdp.cash.multiItem.GetPmfMulti in project Stochastic-Inventory by RobinChen121.
the class MultiItemCashLookPolicy method main.
public static void main(String[] args) {
double[] price = { 10, 5 };
// higher margin vs lower margin
double[] variCost = { 4, 2 };
// initial cash
double iniCash = 25;
// initial inventory
int iniInventory1 = 0;
int iniInventory2 = 0;
// higher average demand vs lower average demand
double[][] demand = { { 6, 6 }, { 8, 8 } };
// higher variance vs lower variance
double[] coe = { 0.5, 0.25 };
double[] salPrice = { 2, 1 };
// horizon length
int T = demand[0].length;
double truncationQuantile = 0.999;
int stepSize = 1;
double minCashState = 0;
double maxCashState = 10000;
int minInventoryState = 0;
int maxInventoryState = 200;
int Qbound = 100;
double discountFactor = 1;
double Rmin = 25;
double Rmax = 80;
int incre = 2;
int rowNum = (int) ((Rmax - Rmin) / incre) + 2;
int row = 0;
double[][] optResults = new double[rowNum][5];
for (iniCash = Rmin; iniCash <= Rmax; iniCash = iniCash + incre) {
// get demand possibilities for each period
Distribution[][] distributions = new Distribution[demand.length][T];
for (int t = 0; t < T; t++) {
for (int i = 0; i < demand.length; i++) {
distributions[t][i] = new PoissonDist(demand[i][t]);
}
}
double[][][] pmf = new GetPmf(distributions, truncationQuantile, stepSize).getpmfMulti();
// build action list for two items
Function<CashStateMulti, ArrayList<Actions>> buildActionList = s -> {
ArrayList<Actions> actions = new ArrayList<>();
for (int i = 0; i < Qbound; i++) for (int j = 0; j < Qbound; j++) {
if (variCost[0] * i + variCost[1] * j < s.getIniCash() + 0.1) {
Actions thisAction = new Actions(i, j);
actions.add(thisAction);
}
}
return actions;
};
// Immediate Value Function
ImmediateValueFunction<CashStateMulti, Actions, Demands, Double> immediateValue = (IniState, Actions, RandomDemands) -> {
double action1 = Actions.getFirstAction();
double action2 = Actions.getSecondAction();
double demand1 = RandomDemands.getFirstDemand();
double demand2 = RandomDemands.getSecondDemand();
double endInventory1 = Math.max(0, IniState.getIniInventory1() + action1 - demand1);
double endInventory2 = Math.max(0, IniState.getIniInventory2() + action2 - demand2);
double revenue = price[0] * (IniState.getIniInventory1() + action1 - endInventory1) + price[1] * (IniState.getIniInventory2() + action2 - endInventory2);
double orderingCosts = variCost[0] * action1 + variCost[1] * action2;
double salValue = 0;
if (IniState.getPeriod() == T - 1) {
salValue = salPrice[0] * endInventory1 + salPrice[1] * endInventory2;
}
return revenue - orderingCosts + salValue;
};
// State Transition Function
StateTransitionFunction<CashStateMulti, Actions, Demands, CashStateMulti> stateTransition = (IniState, Actions, RandomDemands) -> {
double endInventory1 = IniState.getIniInventory1() + Actions.getFirstAction() - RandomDemands.getFirstDemand();
endInventory1 = Math.max(0, endInventory1);
double endInventory2 = IniState.getIniInventory2() + Actions.getSecondAction() - RandomDemands.getSecondDemand();
endInventory2 = Math.max(0, endInventory2);
double nextCash = IniState.getIniCash() + immediateValue.apply(IniState, Actions, RandomDemands);
nextCash = nextCash > maxCashState ? maxCashState : nextCash;
nextCash = nextCash < minCashState ? minCashState : nextCash;
endInventory1 = endInventory1 > maxInventoryState ? maxInventoryState : endInventory1;
endInventory2 = endInventory2 < minInventoryState ? minInventoryState : endInventory2;
// rounding states to save computing time
nextCash = (int) nextCash;
endInventory1 = (int) endInventory1;
endInventory2 = (int) endInventory2;
return new CashStateMulti(IniState.getPeriod() + 1, endInventory1, endInventory2, nextCash);
};
/**
*****************************************************************
* Solve
*/
CashRecursionMulti recursion = new CashRecursionMulti(discountFactor, pmf, buildActionList, stateTransition, immediateValue, T);
int period = 1;
CashStateMulti iniState = new CashStateMulti(period, iniInventory1, iniInventory2, iniCash);
long currTime = System.currentTimeMillis();
double finalValue = iniCash + recursion.getExpectedValueMulti(iniState);
System.out.println("final optimal cash is " + finalValue);
System.out.println("optimal order quantity in the first priod is : Q1 = " + recursion.getAction(iniState).getFirstAction() + ", Q2 = " + recursion.getAction(iniState).getSecondAction());
double time = (System.currentTimeMillis() - currTime) / 1000;
System.out.println("running time is " + time + "s");
/**
*****************************************************************
* Simulating sdp results
*
* simulating results a little lower than SDP
*/
int sampleNum = 10000;
CashSimulationMulti simuation = new CashSimulationMulti(sampleNum, distributions, discountFactor, recursion, stateTransition, immediateValue);
double simFinalValue = simuation.simulateSDPGivenSamplNumMulti(iniState);
System.out.println(simFinalValue);
/**
*****************************************************************
* try to find some ordering patters from optTable
*
* output results to excel
*/
double Q1 = recursion.getAction(iniState).getFirstAction();
double Q2 = recursion.getAction(iniState).getSecondAction();
System.out.println("");
optResults[row][0] = iniInventory1;
optResults[row][1] = iniInventory2;
optResults[row][2] = iniCash;
optResults[row][3] = Q1;
optResults[row][4] = Q2;
row++;
}
System.out.println("**************************************************");
WriteToExcel wr = new WriteToExcel();
String fileName = "optTable2.xls";
String headString = "x1" + "\t" + "x2" + "\t" + "R" + "\t" + "Q1" + "\t" + "Q2";
wr.writeArrayToExcel(optResults, fileName, headString);
}
use of sdp.cash.multiItem.GetPmfMulti in project Stochastic-Inventory by RobinChen121.
the class MultiItemYR method main.
public static void main(String[] args) {
double[] price = { 2, 10 };
// higher margin vs lower margin
double[] variCost = { 1, 2 };
double depositeRate = 0;
// initial cash
double iniCash = 10;
// initial inventory
int iniInventory1 = 0;
int iniInventory2 = 0;
// gamma distribution:mean demand is shape / beta and variance is shape / beta^2
// beta = 1 / scale
// shape = demand * beta
// variance = demand / beta
// gamma in ssj: alpha is alpha, and lambda is beta(beta)
// horizon length
int T = 4;
double[] meanDemands = new double[] { 10, 3 };
// higher average demand vs lower average demand
double[][] demand = new double[2][T];
// higher variance vs lower variance
double[] beta = { 10, 1 };
double d1 = meanDemands[0];
double d2 = meanDemands[1];
double v1 = variCost[0];
double v2 = variCost[1];
double p1 = price[0];
double p2 = price[1];
for (int t = 0; t < T; t++) {
demand[0][t] = d1;
demand[1][t] = d2;
}
double[] salPrice = Arrays.stream(variCost).map(a -> a * 0.5).toArray();
// number of products
int m = demand.length;
// for (int index = 5; index <= 10; index++) {
// price[1] = index;
// may affect poisson results
double truncationQuantile = 0.9999;
int stepSize = 1;
double minCashState = 0;
double maxCashState = 10000;
int minInventoryState = 0;
int maxInventoryState = 200;
int Qbound = 20;
double discountFactor = 1;
// get demand possibilities for each period
Distribution[][] distributions = new GammaDist[m][T];
// Distribution[][] distributions = new NormalDist[m][T];
for (int i = 0; i < m; i++) for (int t = 0; t < T; t++) {
distributions[i][t] = new GammaDist(demand[i][t] * beta[i], beta[i]);
// distributions[i][t] = new PoissonDist(demand[i][t]);
// distributions[i][t]= new NormalDist(demand[i][t], 0.1 * demand[i][t]);
}
// build action list (y1, y2) for pai(y1, y2, R)
Function<CashStateMultiYR, ArrayList<double[]>> buildActionListPai = s -> {
ArrayList<double[]> actions = new ArrayList<>();
double Ybound = Qbound;
for (double i = 0; i < Ybound; i = i + 1) for (double j = 0; j < Ybound; j = j + 1) {
double[] thisActions = { i, j };
actions.add(thisActions);
}
return actions;
};
// build action list (y1, y2) for V(x1, x2, w)
Function<CashStateMulti, ArrayList<double[]>> buildActionListV = s -> {
ArrayList<double[]> actions = new ArrayList<>();
int miny1 = (int) s.getIniInventory1();
int miny2 = (int) s.getIniInventory2();
double iniR = s.getIniCash() + v1 * s.getIniInventory1() + v2 * s.getIniInventory2();
for (double i = miny1; i < miny1 + Qbound; i = i + 1) for (double j = miny2; j < miny2 + Qbound; j = j + 1) {
if (v1 * i + v2 * j < iniR + 0.1) {
double[] thisActions = { i, j };
actions.add(thisActions);
}
}
return actions;
};
BoundaryFuncton<CashStateMulti, Double> boundFinalCash = (IniState) -> {
return IniState.getIniCash() + salPrice[0] * IniState.getIniInventory1() + salPrice[1] * IniState.getIniInventory2();
};
// State Transition Function: from pai^n(y1, y2, R) to V^{n+1}(x1, x2, w)
StateTransitionFunctionV<CashStateMultiYR, double[], CashStateMulti> stateTransition = (IniState, RandomDemands) -> {
double endInventory1 = IniState.getIniInventory1() - RandomDemands[0];
endInventory1 = Math.max(0, endInventory1);
double endInventory2 = IniState.getIniInventory2() - RandomDemands[1];
endInventory2 = Math.max(0, endInventory2);
double revenue1 = p1 * Math.min(IniState.getIniInventory1(), RandomDemands[0]);
double revenue2 = p2 * Math.min(IniState.getIniInventory2(), RandomDemands[1]);
double nextW = revenue1 + revenue2 + (1 + depositeRate) * (IniState.getIniR() - v1 * IniState.getIniInventory1() - // revise
v2 * IniState.getIniInventory2());
endInventory1 = Math.round(endInventory1 * 10) / 10;
endInventory2 = Math.round(endInventory2 * 10) / 10;
nextW = Math.round(nextW * 10) / 10;
nextW = nextW > maxCashState ? maxCashState : nextW;
nextW = nextW < minCashState ? minCashState : nextW;
endInventory1 = endInventory1 > maxInventoryState ? maxInventoryState : endInventory1;
endInventory2 = endInventory2 < minInventoryState ? minInventoryState : endInventory2;
return new CashStateMulti(IniState.getPeriod() + 1, endInventory1, endInventory2, nextW);
};
GetPmfMulti PmfMulti = new GetPmfMulti(distributions, truncationQuantile, stepSize);
/**
*****************************************************************
* Solve
*/
CashRecursionV recursion = new CashRecursionV(discountFactor, PmfMulti, buildActionListV, buildActionListPai, stateTransition, boundFinalCash, T, variCost);
int period = 1;
CashStateMulti iniState = new CashStateMulti(period, iniInventory1, iniInventory2, iniCash);
long currTime = System.currentTimeMillis();
double finalValue = recursion.getExpectedValueV(iniState);
System.out.println("final optimal cash is " + finalValue);
System.out.println("optimal order quantity in the first priod is : y1 = " + recursion.getAction(iniState)[0] + ", y2 = " + recursion.getAction(iniState)[1]);
double time = (System.currentTimeMillis() - currTime) / 1000.0;
System.out.println("running time is " + time + "s");
CashStateR iniState2 = new CashStateR(period, iniCash);
double[] optY = recursion.getYStar(iniState2);
System.out.println("optimal order quantity y* in the first priod is : " + Arrays.toString(optY));
/**
*****************************************************************
* Simulate
*
* basically, this simulation is testing for Theorem 1:
* optimal ordering decisions depend on y*(R)
*/
int sampleNum = 10000;
currTime = System.currentTimeMillis();
CashSimulationY simulation = new CashSimulationY(sampleNum, distributions, discountFactor, recursion, stateTransition);
double simFinalValue = simulation.simulateSDPGivenSamplNum(iniState, variCost);
double gap = (simFinalValue - finalValue) / finalValue;
System.out.printf("optimality gap for this policy y* is %.2f%%\n", gap * 100);
time = (System.currentTimeMillis() - currTime) / 1000.0;
System.out.println("running time is " + time + "s");
//
// /*******************************************************************
// * Compute a1* and a2*
// *
// * and simulate their results to test Theorem 2
// *
// */
// double[][][] pmf1 = new GetPmf(distributions[0], truncationQuantile, stepSize).getpmf();
// Distribution[] distributions1 = distributions[0];
// double[][][] pmf2 = new GetPmf(distributions[1], truncationQuantile, stepSize).getpmf();
// Distribution[] distributions2 = distributions[1];
// RecursionG recursionG1 = new RecursionG(pmf1, distributions1, price[0], variCost[0], 0, salPrice[0]);
// RecursionG recursionG2 = new RecursionG(pmf2, distributions2, price[1], variCost[1], 0, salPrice[1]);
// double[] opta1 = recursionG1.getOptY();
// double[] opta2 = recursionG2.getOptY();
// System.out.println("a1* in each period:");
// DecimalFormat df = new DecimalFormat("0.00");
// Arrays.stream(opta1).forEach(e -> System.out.print(df.format(e) + " " ));
// System.out.println("");
// System.out.println("a2* in each period:");
// Arrays.stream(opta2).forEach(e -> System.out.print(df.format(e) + " " ));
// double simFinalValue2 = simulation.simulateSDPGivenSamplNuma1a2(iniState, variCost, opta1, opta2);
// double gap2 = (simFinalValue2 - finalValue) / finalValue;
// System.out.printf("optimality gap for this policy a* is %.2f%%\n", gap2 * 100);
//
// double[] mean = new double[] {demand[0][0], demand[1][0]};
// double[] variance = new double[] {demand[0][0] / beta[0], demand[1][0] / beta[1]};
// double[][] optTable = recursion.getOptTableDetail2(mean, variance, price, opta1, opta2);
//
// double[] gaps = new double[] {gap, gap2};
// WriteToExcel wr = new WriteToExcel();
// String fileName = "run" + ".xls";
// String headString =
// "meanD1" + "\t" + "meanD2" + "\t" + "variance1" + "\t" + "variance2" + "\t" +
// "period" + "\t" + "x1" + "\t" + "x2" + "\t" + "w" + "\t" +
// "p1" + "\t" + "p2" + "\t" +
// "c1" + "\t" + "c2" + "\t" + "R" + "\t" + "y1*"+ "\t" + "y2*" + "\t" +
// "cashSituation" + "\t" + "alpha" + "\t" + "yHead1" + "\t" + "yHead2" + "\t" + "a1*" + "\t" + "a2*" +
// "\t" + "Theorem1Gap" + "Theorem2Gap";
// wr.writeArrayToExcel2(optTable, fileName, headString, gaps);
// System.out.println("alpha in the first period: " + optTable[0][10]);
// System.out.println("*******************************");
}
use of sdp.cash.multiItem.GetPmfMulti in project Stochastic-Inventory by RobinChen121.
the class MultiItemCash method main.
public static void main(String[] args) {
double[] price = { 4, 50 };
// higher margin vs lower margin
double[] variCost = { 2, 4 };
// initial cash
double iniCash = 100;
// initial inventory
int iniInventory1 = 0;
int iniInventory2 = 0;
// higher average demand vs lower average demand
double[][] demand = { { 5, 6 }, { 5, 6 } };
// higher variance vs lower variance
double[] coe = { 0.25, 0.25 };
double[] salPrice = { 1, 1 };
// horizon length
int T = demand[0].length;
double truncationQuantile = 0.999;
int stepSize = 1;
double minCashState = 0;
double maxCashState = 10000;
int minInventoryState = 0;
int maxInventoryState = 200;
int Qbound = 100;
double discountFactor = 1;
// get demand possibilities for each period
BiNormalDist[] distributions = new BiNormalDist[T];
for (int t = 0; t < T; t++) distributions[t] = new BiNormalDist(demand[0][t], coe[0] * demand[0][t], demand[1][t], coe[1] * demand[1][t], 0);
// build action list for two items
Function<CashStateMulti, ArrayList<Actions>> buildActionList = s -> {
ArrayList<Actions> actions = new ArrayList<>();
for (int i = 0; i < Qbound; i++) for (int j = 0; j < Qbound; j++) {
if (variCost[0] * i + variCost[1] * j < s.getIniCash() + 0.1) {
Actions thisAction = new Actions(i, j);
actions.add(thisAction);
}
}
return actions;
};
// Immediate Value Function
ImmediateValueFunction<CashStateMulti, Actions, Demands, Double> immediateValue = (IniState, Actions, RandomDemands) -> {
double action1 = Actions.getFirstAction();
double action2 = Actions.getSecondAction();
double demand1 = RandomDemands.getFirstDemand();
double demand2 = RandomDemands.getSecondDemand();
double endInventory1 = Math.max(0, IniState.getIniInventory1() + action1 - demand1);
double endInventory2 = Math.max(0, IniState.getIniInventory2() + action2 - demand2);
double revenue1 = price[0] * (IniState.getIniInventory1() + action1 - endInventory1);
double revenue2 = price[1] * (IniState.getIniInventory2() + action2 - endInventory2);
double revenue = revenue1 + revenue2;
double orderingCost1 = variCost[0] * action1;
double orderingCost2 = variCost[1] * action2;
double orderingCosts = orderingCost1 + orderingCost2;
double salValue = 0;
if (IniState.getPeriod() == T) {
salValue = salPrice[0] * endInventory1 + salPrice[1] * endInventory2;
}
return revenue - orderingCosts + salValue;
};
// State Transition Function
StateTransitionFunction<CashStateMulti, Actions, Demands, CashStateMulti> stateTransition = (IniState, Actions, RandomDemands) -> {
double endInventory1 = IniState.getIniInventory1() + Actions.getFirstAction() - RandomDemands.getFirstDemand();
endInventory1 = Math.max(0, endInventory1);
double endInventory2 = IniState.getIniInventory2() + Actions.getSecondAction() - RandomDemands.getSecondDemand();
endInventory2 = Math.max(0, endInventory2);
double nextCash = IniState.getIniCash() + immediateValue.apply(IniState, Actions, RandomDemands);
nextCash = nextCash > maxCashState ? maxCashState : nextCash;
nextCash = nextCash < minCashState ? minCashState : nextCash;
endInventory1 = endInventory1 > maxInventoryState ? maxInventoryState : endInventory1;
endInventory2 = endInventory2 < minInventoryState ? minInventoryState : endInventory2;
// rounding states to save computing time
nextCash = (int) nextCash;
endInventory1 = (int) endInventory1;
endInventory2 = (int) endInventory2;
return new CashStateMulti(IniState.getPeriod() + 1, endInventory1, endInventory2, nextCash);
};
// GetPmfMulti pmfMulti = new GetPmfMulti(distributions, truncationQuantile, stepSize);
//
// /*******************************************************************
// * Solve
// */
// CashRecursionMulti recursion = new CashRecursionMulti(discountFactor, pmfMulti, buildActionList,
// stateTransition, immediateValue, T);
// int period = 1;
// CashStateMulti iniState = new CashStateMulti(period, iniInventory1, iniInventory2, iniCash);
// long currTime = System.currentTimeMillis();
// double finalValue = iniCash + recursion.getExpectedValue(iniState);
// System.out.println("final optimal cash is " + finalValue);
// System.out.println("optimal order quantity in the first priod is : Q1 = " + recursion.getAction(iniState).getFirstAction()
// + ", Q2 = " + recursion.getAction(iniState).getSecondAction());
// double time = (System.currentTimeMillis() - currTime) / 1000;
// System.out.println("running time is " + time + "s");
//
//
//
// /*******************************************************************
// * Simulating sdp results
// *
// * simulating results a little lower than SDP
// */
// int sampleNum = 10000;
// CashSimulationMulti simuation = new CashSimulationMulti(sampleNum, distributions, discountFactor,
// recursion, stateTransition, immediateValue);
// double simFinalValue = simuation.simulateSDPGivenSamplNum(iniState);
// System.out.println(simFinalValue);
/**
*****************************************************************
* try to find some ordering patters from optTable
*
* output results to excel
*/
// System.out.println("");
// double[][] optTable = recursion.getOptTable(variCost);
// WriteToExcel wr = new WriteToExcel();
// String fileName = "optTable" + "_c1=" + variCost[0] + "c2=" + variCost[1] + ".xls";
// String headString = "period" + "\t" + "x1" + "\t" + "x2" + "\t" + "w"+ "\t" + "R" + "\t" + "is limited cash and both ordering" + "\t" + "alpha"
// + "\t" + "Q1"+ "\t" + "Q2" + "\t" + "c1" + "\t" + "c2";
// wr.writeArrayToExcel(optTable, fileName, headString);
//
}
use of sdp.cash.multiItem.GetPmfMulti in project Stochastic-Inventory by RobinChen121.
the class MultiItemCashUniform method main.
public static void main(String[] args) {
double[] price = { 4, 10 };
// higher margin vs lower margin
double[] variCost = { 2, 4 };
// initial cash
double iniCash = 20;
// initial inventory
int iniInventory1 = 0;
int iniInventory2 = 0;
double depositeRate = 0;
double[] salPrice = { 1, 1 };
// horizon length
int T = 5;
double truncationQuantile = 0.999;
int stepSize = 1;
double minCashState = 0;
double maxCashState = 10000;
int minInventoryState = 0;
int maxInventoryState = 200;
int Qbound = 100;
double discountFactor = 1;
// possible number of demand values
int N = 10;
double[] values1 = new double[N];
double[] probs1 = new double[N];
double[] values2 = new double[N];
double[] probs2 = new double[N];
float NN = N;
Arrays.fill(values1, 10);
Arrays.fill(values2, 5);
Arrays.fill(probs1, 1.0 / NN);
Arrays.fill(probs2, 1.0 / NN);
Distribution[][] distributions = new DiscreteDistribution[T][2];
for (int t = 0; t < T; t++) {
distributions[t][0] = new DiscreteDistribution(values1, probs1, values1.length);
distributions[t][1] = new DiscreteDistribution(values2, probs2, values2.length);
}
// build action list (y1, y2) for two items
Function<CashStateMultiXR, ArrayList<double[]>> buildActionList = s -> {
ArrayList<double[]> actions = new ArrayList<>();
int miny1 = (int) s.getIniInventory1();
int miny2 = (int) s.getIniInventory2();
for (int i = miny1; i < miny1 + Qbound; i++) for (int j = miny2; j < miny2 + Qbound; j++) {
if (variCost[0] * i + variCost[1] * j < s.getIniR() + 0.1) {
double[] thisActions = { i, j };
actions.add(thisActions);
}
}
return actions;
};
// Immediate Value Function
ImmediateValueFunction<CashStateMultiXR, double[], double[], Double> immediateValue = (IniState, Actions, RandomDemands) -> {
double action1 = Actions[0];
double action2 = Actions[1];
double demand1 = RandomDemands[0];
double demand2 = RandomDemands[1];
double endInventory1 = Math.max(0, action1 - demand1);
double endInventory2 = Math.max(0, action2 - demand2);
double revenue1 = price[0] * (action1 - endInventory1);
double revenue2 = price[1] * (action2 - endInventory2);
double revenue = revenue1 + revenue2;
double initialCash = IniState.getIniR() - variCost[0] * IniState.getIniInventory1() - variCost[1] * IniState.getIniInventory2();
double orderingCostY1 = variCost[0] * action1;
double orderingCostY2 = variCost[1] * action2;
double orderingCostsY = orderingCostY1 + orderingCostY2;
double salValue = 0;
if (IniState.getPeriod() == T - 1) {
salValue = salPrice[0] * endInventory1 + salPrice[1] * endInventory2;
}
return revenue + (1 - depositeRate) * (IniState.getIniR() - orderingCostsY) + salValue - initialCash;
};
// State Transition Function
StateTransitionFunction<CashStateMultiXR, double[], double[], CashStateMultiXR> stateTransition = (IniState, Actions, RandomDemands) -> {
double endInventory1 = Actions[0] - RandomDemands[0];
endInventory1 = Math.max(0, endInventory1);
double endInventory2 = Actions[1] - RandomDemands[1];
endInventory2 = Math.max(0, endInventory2);
double initialCash = IniState.getIniR() - variCost[0] * IniState.getIniInventory1() - variCost[1] * IniState.getIniInventory2();
double nextCash = initialCash + immediateValue.apply(IniState, Actions, RandomDemands);
nextCash = nextCash > maxCashState ? maxCashState : nextCash;
nextCash = nextCash < minCashState ? minCashState : nextCash;
endInventory1 = endInventory1 > maxInventoryState ? maxInventoryState : endInventory1;
endInventory2 = endInventory2 < minInventoryState ? minInventoryState : endInventory2;
// rounding states to save computing time
nextCash = (int) nextCash;
endInventory1 = (int) endInventory1;
endInventory2 = (int) endInventory2;
double nextR = (int) nextCash + variCost[0] * endInventory1 + variCost[1] * endInventory2;
return new CashStateMultiXR(IniState.getPeriod() + 1, endInventory1, endInventory2, nextR);
};
GetPmfMulti PmfMulti = new GetPmfMulti(distributions, truncationQuantile, stepSize);
/**
*****************************************************************
* Solve
*/
CashRecursionMultiXR recursion = new CashRecursionMultiXR(discountFactor, PmfMulti, buildActionList, stateTransition, immediateValue, T);
int period = 1;
CashStateMultiXR iniState = new CashStateMultiXR(period, iniInventory1, iniInventory2, iniCash);
long currTime = System.currentTimeMillis();
double finalValue = iniCash + recursion.getExpectedValue(iniState);
System.out.println("final optimal cash is " + finalValue);
System.out.println("optimal order quantity in the first priod is : y1 = " + recursion.getAction(iniState)[0] + ", y2 = " + recursion.getAction(iniState)[1]);
double time = (System.currentTimeMillis() - currTime) / 1000.0;
System.out.println("running time is " + time + "s");
/**
*****************************************************************
* Simulating sdp results
*
* simulating results a little lower than SDP
*/
int sampleNum = 10000;
CashSimulationMultiXR simuation = new CashSimulationMultiXR(sampleNum, distributions, discountFactor, recursion, stateTransition, immediateValue);
double simFinalValue = simuation.simulateSDPGivenSamplNum(iniState);
System.out.println(simFinalValue);
/**
*****************************************************************
* try to find some ordering patters from optTable
*
* output results to excel
*/
System.out.println("");
double[][] optTable = recursion.getOptTable(variCost);
WriteToExcel wr = new WriteToExcel();
String fileName = "optTable" + "_c1=" + variCost[0] + "c2=" + variCost[1] + ".xls";
String headString = "period" + "\t" + "x1" + "\t" + "x2" + "\t" + "w" + "\t" + "R" + "\t" + "is limited cash and both ordering" + "\t" + "alpha" + "\t" + "y1" + "\t" + "y2" + "\t" + "c1" + "\t" + "c2";
wr.writeArrayToExcel(optTable, fileName, headString);
}
use of sdp.cash.multiItem.GetPmfMulti in project Stochastic-Inventory by RobinChen121.
the class MultiItemCashXR method main.
public static void main(String[] args) {
double[] price = { 2, 10 };
// higher margin vs lower margin
double[] variCost = { 1, 2 };
// initial cash
double iniCash = 10;
// initial inventory
int iniInventory1 = 0;
int iniInventory2 = 0;
double depositeRate = 0;
// gamma distribution:mean demand is shape / beta and variance is shape / beta^2
// beta = 1 / scale
// shape = demand * beta
// variance = demand / beta
// gamma in ssj: alpha is alpha, and lambda is beta(beta)
// horizon length
int T = 2;
double[] meanDemands = new double[] { 10, 3 };
// higher average demand vs lower average demand
double[][] demand = new double[2][T];
// higher variance vs lower variance
double[] beta = { 10, 1 };
double[] salPrice = Arrays.stream(variCost).map(a -> a * 0.5).toArray();
// number of products
int m = meanDemands.length;
double d1 = meanDemands[0];
double d2 = meanDemands[1];
for (int t = 0; t < T; t++) {
demand[0][t] = d1;
demand[1][t] = d2;
}
// may affect poisson results
double truncationQuantile = 0.99;
int stepSize = 1;
double minCashState = 0;
double maxCashState = 10000;
int minInventoryState = 0;
int maxInventoryState = 200;
int Qbound = 20;
double discountFactor = 1;
// get demand possibilities for each period
Distribution[][] distributions = new GammaDist[m][T];
// Distribution[][] distributions = new NormalDist[m][T];
for (int i = 0; i < m; i++) for (int t = 0; t < T; t++) {
distributions[i][t] = new GammaDist(demand[i][t] * beta[i], beta[i]);
// distributions[i][t] = new PoissonDist(demand[i][t]);
// distributions[i][t]= new NormalDist(demand[i][t], 0.1 * demand[i][t]);
}
// build action list (y1, y2) for two items
Function<CashStateMultiXR, ArrayList<double[]>> buildActionList = s -> {
ArrayList<double[]> actions = new ArrayList<>();
int miny1 = (int) s.getIniInventory1();
int miny2 = (int) s.getIniInventory2();
for (int i = miny1; i < miny1 + Qbound; i++) for (int j = miny2; j < miny2 + Qbound; j++) {
if (variCost[0] * i + variCost[1] * j < s.getIniR() + 0.1) {
double[] thisActions = { i, j };
actions.add(thisActions);
}
}
return actions;
};
// Immediate Value Function
ImmediateValueFunction<CashStateMultiXR, double[], double[], Double> immediateValue = (IniState, Actions, RandomDemands) -> {
double action1 = Actions[0];
double action2 = Actions[1];
double demand1 = RandomDemands[0];
double demand2 = RandomDemands[1];
double endInventory1 = Math.max(0, action1 - demand1);
double endInventory2 = Math.max(0, action2 - demand2);
double revenue1 = price[0] * (action1 - endInventory1);
double revenue2 = price[1] * (action2 - endInventory2);
double revenue = revenue1 + revenue2;
double initialCash = IniState.getIniR() - variCost[0] * IniState.getIniInventory1() - variCost[1] * IniState.getIniInventory2();
double orderingCostY1 = variCost[0] * action1;
double orderingCostY2 = variCost[1] * action2;
double orderingCostsY = orderingCostY1 + orderingCostY2;
double salValue = 0;
if (IniState.getPeriod() == T) {
salValue = salPrice[0] * endInventory1 + salPrice[1] * endInventory2;
}
return revenue + (1 - depositeRate) * (IniState.getIniR() - orderingCostsY) + salValue - initialCash;
};
// State Transition Function
StateTransitionFunction<CashStateMultiXR, double[], double[], CashStateMultiXR> stateTransition = (IniState, Actions, RandomDemands) -> {
double endInventory1 = Actions[0] - RandomDemands[0];
endInventory1 = Math.max(0, endInventory1);
double endInventory2 = Actions[1] - RandomDemands[1];
endInventory2 = Math.max(0, endInventory2);
double initialCash = IniState.getIniR() - variCost[0] * IniState.getIniInventory1() - variCost[1] * IniState.getIniInventory2();
double nextCash = initialCash + immediateValue.apply(IniState, Actions, RandomDemands);
nextCash = nextCash > maxCashState ? maxCashState : nextCash;
nextCash = nextCash < minCashState ? minCashState : nextCash;
endInventory1 = endInventory1 > maxInventoryState ? maxInventoryState : endInventory1;
endInventory2 = endInventory2 < minInventoryState ? minInventoryState : endInventory2;
// rounding states to save computing time
nextCash = (int) nextCash;
endInventory1 = (int) endInventory1;
endInventory2 = (int) endInventory2;
double nextR = (int) nextCash + variCost[0] * endInventory1 + variCost[1] * endInventory2;
return new CashStateMultiXR(IniState.getPeriod() + 1, endInventory1, endInventory2, nextR);
};
GetPmfMulti PmfMulti = new GetPmfMulti(distributions, truncationQuantile, stepSize);
/**
*****************************************************************
* Solve
*/
CashRecursionMultiXR recursion = new CashRecursionMultiXR(discountFactor, PmfMulti, buildActionList, stateTransition, immediateValue, T);
int period = 1;
CashStateMultiXR iniState = new CashStateMultiXR(period, iniInventory1, iniInventory2, iniCash);
long currTime = System.currentTimeMillis();
double finalValue = iniCash + recursion.getExpectedValue(iniState);
System.out.println("final optimal cash is " + finalValue);
System.out.println("optimal order quantity in the first priod is : y1 = " + recursion.getAction(iniState)[0] + ", y2 = " + recursion.getAction(iniState)[1]);
double time = (System.currentTimeMillis() - currTime) / 1000.0;
System.out.println("running time is " + time + "s");
//
//
// /*******************************************************************
// * Simulating sdp results
// *
// * simulating results a little lower than SDP
// */
// int sampleNum = 10000;
// CashSimulationMultiXR simuation = new CashSimulationMultiXR(sampleNum, distributions, discountFactor,
// recursion, stateTransition, immediateValue);
// double simFinalValue = simuation.simulateSDPGivenSamplNum(iniState);
// System.out.println(simFinalValue);
//
//
// /*******************************************************************
// * try to find some ordering patters from optTable
// *
// * output results to excel
// */
// System.out.println("");
// double[][] optTable = recursion.getOptTable(variCost);
// WriteToExcel wr = new WriteToExcel();
// String fileName = "optTable" + "_c1=" + variCost[0] + "c2=" + variCost[1] + ".xls";
// String headString = "period" + "\t" + "x1" + "\t" + "x2" + "\t" + "w"+ "\t" + "R" + "\t" + "is limited cash and both ordering" + "\t" + "alpha"
// + "\t" + "y1"+ "\t" + "y2" + "\t" + "c1" + "\t" + "c2";
// wr.writeArrayToExcel(optTable, fileName, headString);
//
}
Aggregations