Search in sources :

Example 1 with Recursion

use of sdp.inventory.Recursion in project Stochastic-Inventory by RobinChen121.

the class LevelFitsS method main.

public static void main(String[] args) {
    double truncationQuantile = 0.9999;
    double stepSize = 1;
    double minInventory = -500;
    double maxInventory = 1000;
    double fixedOrderingCost = 250;
    double variOrderingCost = 0;
    double penaltyCost = 26;
    // double[] meanDemand = { 20, 40, 60, 40 };
    double holdingCost = 1;
    int maxOrderQuantity = 41;
    boolean isForDrawGy = true;
    // // get demand possibilities for each period
    // int T = meanDemand.length;
    // Distribution[] distributions = IntStream.iterate(0, i -> i + 1).limit(T)
    // //.mapToObj(i -> new PoissonDist(meanDemand[i]))
    // .mapToObj(i -> new NormalDist(meanDemand[i], coeValue * meanDemand[i]))
    // .toArray(Distribution[]::new);
    // double[][][] pmf = new GetPmf(distributions, truncationQuantile, stepSize).getpmf();
    // int T = 8;
    // double[] values = {6, 7};
    // double[] probs = {0.95, 0.05};
    // Distribution[] distributions = IntStream.iterate(0, i -> i + 1).limit(T)
    // .mapToObj(i -> new DiscreteDistribution(values, probs, values.length)) // can be changed to other distributions
    // .toArray(DiscreteDistribution[]::new);
    // double[][][] pmf = new GetPmf(distributions, truncationQuantile, stepSize).getpmf();
    int T = 4;
    double[][] values = { { 34, 159, 281, 286 }, { 14, 223, 225, 232 }, { 5, 64, 115, 171 }, { 35, 48, 145, 210 } };
    double[][] probs = { { 0.018, 0.888, 0.046, 0.048 }, { 0.028, 0.271, 0.17, 0.531 }, { 0.041, 0.027, 0.889, 0.043 }, { 0.069, 0.008, 0.019, 0.904 } };
    Distribution[] distributions = IntStream.iterate(0, i -> i + 1).limit(T).mapToObj(// can be changed to other distributions
    i -> new DiscreteDistribution(values[i], probs[i], values[i].length)).toArray(DiscreteDistribution[]::new);
    double[][][] pmf = new GetPmf(distributions, truncationQuantile, stepSize).getpmf();
    // feasible actions
    Function<State, double[]> getFeasibleAction = s -> {
        double[] feasibleActions = new double[(int) (maxOrderQuantity / stepSize) + 1];
        int index = 0;
        for (double i = 0; i <= maxOrderQuantity; i = i + stepSize) {
            feasibleActions[index] = i;
            index++;
        }
        return feasibleActions;
    };
    // state transition function
    StateTransitionFunction<State, Double, Double, State> stateTransition = (state, action, randomDemand) -> {
        double nextInventory = state.getIniInventory() + action - randomDemand;
        nextInventory = nextInventory > maxInventory ? maxInventory : nextInventory;
        nextInventory = nextInventory < minInventory ? minInventory : nextInventory;
        return new State(state.getPeriod() + 1, nextInventory);
    };
    // immediate value
    ImmediateValueFunction<State, Double, Double, Double> immediateValue = (state, action, randomDemand) -> {
        double fixedCost = 0, variableCost = 0, inventoryLevel = 0, holdingCosts = 0, penaltyCosts = 0;
        fixedCost = action > 0 ? fixedOrderingCost : 0;
        variableCost = variOrderingCost * action;
        inventoryLevel = state.getIniInventory() + action - randomDemand;
        holdingCosts = holdingCost * Math.max(inventoryLevel, 0);
        penaltyCosts = penaltyCost * Math.max(-inventoryLevel, 0);
        double totalCosts = fixedCost + variableCost + holdingCosts + penaltyCosts;
        return totalCosts;
    };
    /**
     *****************************************************************
     * Solve
     */
    Recursion recursion = new Recursion(OptDirection.MIN, pmf, getFeasibleAction, stateTransition, immediateValue);
    int period = 1;
    double iniInventory = 500;
    State initialState = new State(period, iniInventory);
    long currTime = System.currentTimeMillis();
    double opt = recursion.getExpectedValue(initialState);
    System.out.println("final optimal expected value is: " + opt);
    System.out.println("optimal order quantity in the first priod is : " + recursion.getAction(initialState));
    double time = (System.currentTimeMillis() - currTime) / 1000;
    System.out.println("running time is " + time + "s");
    /**
     *****************************************************************
     * Simulating sdp results
     */
    int sampleNum = 10000;
    SimulateFitsS simuation = new SimulateFitsS(distributions, sampleNum, recursion);
    simuation.simulateSDPGivenSamplNum(initialState);
    double error = 0.0001;
    double confidence = 0.95;
    simuation.simulateSDPwithErrorConfidence(initialState, error, confidence);
    /**
     *****************************************************************
     * Fit (s, S) levels
     */
    System.out.println("");
    double[][] optTable = recursion.getOptTable();
    MIPFitsS findsS = new MIPFitsS(maxOrderQuantity, T);
    double[][] optsS = findsS.getSinglesS(optTable);
    System.out.println("single s, S level: " + Arrays.deepToString(optsS));
    optsS = findsS.getTwosS(optTable);
    System.out.println("two s, S level: " + Arrays.deepToString(optsS));
    optsS = findsS.getThreesS(optTable);
    System.out.println("three s, S level: " + Arrays.deepToString(optsS));
    double sim1 = simuation.simulateSinglesS(initialState, optsS, maxOrderQuantity);
    System.out.printf("one level gap is %.2f%%\n", (sim1 - opt) * 100 / opt);
    double sim2 = simuation.simulateTwosS(initialState, optsS, maxOrderQuantity);
    System.out.printf("two level gap is %.2f%%\n", (sim2 - opt) * 100 / opt);
    double sim3 = simuation.simulateThreesS(initialState, optsS, maxOrderQuantity);
    System.out.printf("three level gap is %.2f%%\n", (sim3 - opt) * 100 / opt);
}
Also used : IntStream(java.util.stream.IntStream) ImmediateValueFunction(sdp.inventory.ImmediateValue.ImmediateValueFunction) Arrays(java.util.Arrays) DiscreteDistribution(umontreal.ssj.probdist.DiscreteDistribution) NormalDist(umontreal.ssj.probdist.NormalDist) MIPFitsS(milp.MIPFitsS) Function(java.util.function.Function) StateTransitionFunction(sdp.inventory.StateTransition.StateTransitionFunction) GetPmf(sdp.inventory.GetPmf) OptDirection(sdp.inventory.Recursion.OptDirection) CheckKConvexity(sdp.inventory.CheckKConvexity) State(sdp.inventory.State) Recursion(sdp.inventory.Recursion) PoissonDist(umontreal.ssj.probdist.PoissonDist) Drawing(sdp.inventory.Drawing) Distribution(umontreal.ssj.probdist.Distribution) Recursion(sdp.inventory.Recursion) MIPFitsS(milp.MIPFitsS) State(sdp.inventory.State) DiscreteDistribution(umontreal.ssj.probdist.DiscreteDistribution) Distribution(umontreal.ssj.probdist.Distribution) GetPmf(sdp.inventory.GetPmf) DiscreteDistribution(umontreal.ssj.probdist.DiscreteDistribution)

Example 2 with Recursion

use of sdp.inventory.Recursion in project Stochastic-Inventory by RobinChen121.

the class TwoLevelFitsSTest method main.

public static void main(String[] args) {
    String headString = "K, v, h, I0, pai, Qmax, DemandPatt, OpValue, Time(sec), simValue, error";
    WriteToCsv.writeToFile("./" + "test_results.csv", headString);
    double[][] demands = { { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }, { 6.6, 9.3, 11.1, 12.9, 16.8, 21.6, 24, 26.4, 31.5, 33.9, 36.3, 40.8, 44.4, 47.1, 48.3, 50.1, 50.1, 48.9, 47.1, 44.4 }, { 45.9, 48.6, 49.8, 49.8, 48.6, 45.9, 42.3, 37.8, 35.4, 33, 30.3, 27.9, 25.5, 23.1, 20.7, 18.3, 14.4, 10.8, 8.1, 6.3 }, { 36.3, 30, 23.7, 21, 23.7, 30, 36.3, 39, 36.3, 30, 23.7, 21, 23.7, 30, 36.3, 30.9, 24.3, 21.3, 26.4, 33 }, { 47.1, 30, 12.9, 6, 12.9, 30, 47.1, 54, 47.1, 30, 12.9, 6, 12.9, 30, 47.1, 29.7, 15, 7.5, 11.4, 29.7 }, { 62.7, 27.3, 9.9, 23.7, 1, 22.8, 32.7, 34.5, 67.2, 6.6, 14.4, 40.8, 3.9, 63.3, 25.5, 45, 53.1, 24.6, 10.2, 49.8 }, { 1, 15.3, 45.6, 140.1, 80.4, 146.7, 133.8, 74.4, 84.3, 108.9, 46.5, 87.9, 66, 27.9, 32.1, 88.5, 161.7, 36, 32.4, 49.8 }, { 14.1, 24.3, 70.8, 118.2, 49.2, 86.1, 152.4, 117.3, 226.2, 208.2, 78.3, 58.5, 96, 33.3, 57.3, 115.5, 17.7, 134.7, 127.8, 179.7 }, { 13.2, 34.8, 79.2, 43.2, 43.8, 59.4, 22.2, 54.9, 61.2, 34.2, 49.5, 95.4, 35.7, 144.6, 160.2, 103.8, 150.6, 86.4, 122.7, 63.6 }, { 14.7, 56.4, 19.2, 83.7, 135.9, 67.2, 66.9, 155.1, 87.3, 164.1, 193.8, 67.2, 64.5, 132, 34.8, 131.4, 132.9, 35.7, 172.5, 152.1 } };
    // 1500, 1000, 500
    double[] K = { 500, 800, 200 };
    double[] v = { 0, 5, 10 };
    // 15, 10, 5
    double[] pai = { 15, 10, 5 };
    // 3, 5, 7
    double[] capacity = { 2, 3, 4 };
    double truncationQuantile = 0.9999;
    double stepSize = 1;
    double minInventory = -300;
    double maxInventory = 800;
    double holdingCost = 1;
    for (int iK = 0; iK < K.length; iK++) {
        for (int iv = 0; iv < v.length; iv++) {
            for (int ipai = 0; ipai < pai.length; ipai++) {
                for (int idemand = 0; idemand < demands.length; idemand++) for (int icapacity = 0; icapacity < capacity.length; icapacity++) {
                    // double[] meanDemand = demands[idemand];
                    double[] meanDemand = { 9, 23, 53, 29 };
                    double fixedOrderingCost = K[iK];
                    double proportionalOrderingCost = v[iv];
                    double penaltyCost = pai[ipai];
                    int maxOrderQuantity = (int) (Math.round(Arrays.stream(meanDemand).sum() / meanDemand.length) * capacity[icapacity]);
                    // get demand possibilities for each period
                    int T = meanDemand.length;
                    Distribution[] distributions = IntStream.iterate(0, i -> i + 1).limit(T).mapToObj(// can be changed to other distributions
                    i -> new PoissonDist(meanDemand[i])).toArray(PoissonDist[]::new);
                    double[][][] pmf = new GetPmf(distributions, truncationQuantile, stepSize).getpmf();
                    // feasible actions
                    Function<State, double[]> getFeasibleAction = s -> {
                        double[] feasibleActions = new double[(int) (maxOrderQuantity / stepSize) + 1];
                        int index = 0;
                        for (double i = 0; i <= maxOrderQuantity; i = i + stepSize) {
                            feasibleActions[index] = i;
                            index++;
                        }
                        return feasibleActions;
                    };
                    // state transition function
                    StateTransitionFunction<State, Double, Double, State> stateTransition = (state, action, randomDemand) -> {
                        double nextInventory = state.getIniInventory() + action - randomDemand;
                        nextInventory = nextInventory > maxInventory ? maxInventory : nextInventory;
                        nextInventory = nextInventory < minInventory ? minInventory : nextInventory;
                        return new State(state.getPeriod() + 1, nextInventory);
                    };
                    // immediate value
                    ImmediateValueFunction<State, Double, Double, Double> immediateValue = (state, action, randomDemand) -> {
                        double fixedCost = 0, variableCost = 0, inventoryLevel = 0, holdingCosts = 0, penaltyCosts = 0;
                        fixedCost = action > 0 ? fixedOrderingCost : 0;
                        variableCost = proportionalOrderingCost * action;
                        inventoryLevel = state.getIniInventory() + action - randomDemand;
                        holdingCosts = holdingCost * Math.max(inventoryLevel, 0);
                        penaltyCosts = penaltyCost * Math.max(-inventoryLevel, 0);
                        double totalCosts = fixedCost + variableCost + holdingCosts + penaltyCosts;
                        return totalCosts;
                    };
                    /**
                     *****************************************************************
                     * Solve
                     */
                    Recursion recursion = new Recursion(OptDirection.MIN, pmf, getFeasibleAction, stateTransition, immediateValue);
                    // using tree map when finding levels for s and S
                    recursion.setTreeMapCacheAction();
                    int period = 1;
                    double iniInventory = 0;
                    State initialState = new State(period, iniInventory);
                    long currTime = System.currentTimeMillis();
                    double finalValue = recursion.getExpectedValue(initialState);
                    System.out.println("final optimal expected value is: " + finalValue);
                    System.out.println("optimal order quantity in the first priod is : " + recursion.getAction(initialState));
                    double time = (System.currentTimeMillis() - currTime) / 1000;
                    System.out.println("running time is " + time + "s");
                    /**
                     *****************************************************************
                     * Simulating two level s S results
                     */
                    int sampleNum = 10000;
                    SimulateFitsS simuation = new SimulateFitsS(distributions, sampleNum, recursion);
                    double[][] optTable = recursion.getOptTable();
                    MIPFitsS findsS = new MIPFitsS(maxOrderQuantity, T);
                    double[][] optsS = findsS.getTwosS(optTable);
                    System.out.println(Arrays.deepToString(optsS));
                    simuation.simulateSDPGivenSamplNum(initialState);
                    double simFinalValue = simuation.simulateTwosS(initialState, optsS, maxOrderQuantity);
                    System.out.printf("Optimality gap is: %.2f%%\n", (simFinalValue - finalValue) / finalValue * 100);
                    String out = fixedOrderingCost + ",\t" + proportionalOrderingCost + ",\t" + holdingCost + ",\t" + iniInventory + ",\t" + penaltyCost + ",\t" + maxOrderQuantity + ",\t" + (idemand + 1) + ",\t" + finalValue + ",\t" + time + ",\t" + simFinalValue + ",\t" + (simFinalValue - finalValue) / finalValue;
                    WriteToCsv.writeToFile("./" + "test_results.csv", out);
                }
            }
        }
    }
}
Also used : PoissonDist(umontreal.ssj.probdist.PoissonDist) StateTransitionFunction(sdp.inventory.StateTransition.StateTransitionFunction) Recursion(sdp.inventory.Recursion) MIPFitsS(milp.MIPFitsS) ImmediateValueFunction(sdp.inventory.ImmediateValue.ImmediateValueFunction) Function(java.util.function.Function) StateTransitionFunction(sdp.inventory.StateTransition.StateTransitionFunction) State(sdp.inventory.State) GetPmf(sdp.inventory.GetPmf) ImmediateValueFunction(sdp.inventory.ImmediateValue.ImmediateValueFunction)

Example 3 with Recursion

use of sdp.inventory.Recursion in project Stochastic-Inventory by RobinChen121.

the class MultiItemCashG 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[] iniInventory = { 0, 0 };
    // compute G(d)
    int d = 1;
    int T = 4;
    // mean demand is shape * scale and variance is shape * scale^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 d1 = meanDemands[0];
    double d2 = meanDemands[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();
    double truncationQuantile = 0.9999;
    int stepSize = 1;
    int maxInventoryState = 200;
    int Qbound = 40;
    double discountFactor = 1;
    // get shape possibilities for a product in each period
    // normal dist for one product
    GammaDist[] distributions = new GammaDist[T];
    for (int t = 0; t < T; t++) distributions[t] = new GammaDist(demand[d - 1][t] * beta[d - 1], beta[d - 1]);
    // build action list for this item
    Function<State, double[]> buildActionList = s -> {
        return DoubleStream.iterate(0, i -> i + stepSize).limit(Qbound + 1).toArray();
    };
    // Immediate Value Function
    ImmediateValueFunction<State, Double, Double, Double> immediateValue = (IniState, action, randomDemand) -> {
        double revenue = 0;
        revenue = (price[d - 1] - variCost[d - 1]) * Math.min(IniState.getIniInventory() + action, randomDemand);
        if (IniState.getPeriod() == T) {
            revenue += (salPrice[d - 1] - variCost[d - 1]) * Math.max(IniState.getIniInventory() + action - randomDemand, 0);
        }
        return revenue;
    };
    // State Transition Function
    // need change
    StateTransitionFunction<State, Double, Double, State> stateTransition = (IniState, action, randomDemand) -> {
        double endInventory = IniState.getIniInventory() + action - randomDemand;
        endInventory = Math.max(0, endInventory);
        endInventory = endInventory > maxInventoryState ? maxInventoryState : endInventory;
        endInventory = (int) endInventory;
        return new State(IniState.getPeriod() + 1, endInventory);
    };
    double[][][] pmf = new GetPmf(distributions, truncationQuantile, stepSize).getpmf();
    /**
     *****************************************************************
     * Solve
     */
    RecursionG recursion = new RecursionG(pmf, buildActionList, stateTransition, immediateValue);
    int period = 1;
    State iniState = new State(period, iniInventory[d - 1]);
    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 :  Q = " + recursion.getAction(iniState));
    double time = (System.currentTimeMillis() - currTime) / 1000;
    System.out.println("running time is " + time + "s");
    System.out.println("a* in each period:");
    double[] optY = recursion.getOptY();
    optY[0] = iniState.getIniInventory() + recursion.getAction(iniState);
    System.out.println(Arrays.toString(optY));
}
Also used : ImmediateValueFunction(sdp.inventory.ImmediateValue.ImmediateValueFunction) Arrays(java.util.Arrays) GammaDist(umontreal.ssj.probdist.GammaDist) NormalDist(umontreal.ssj.probdist.NormalDist) Function(java.util.function.Function) StateTransitionFunction(sdp.inventory.StateTransition.StateTransitionFunction) ArrayList(java.util.ArrayList) DoubleStream(java.util.stream.DoubleStream) GetPmf(sdp.inventory.GetPmf) OptDirection(sdp.inventory.Recursion.OptDirection) RecursionG(sdp.cash.multiItem.RecursionG) State(sdp.inventory.State) Recursion(sdp.inventory.Recursion) BiNormalDist(umontreal.ssj.probdistmulti.BiNormalDist) WriteToExcel(sdp.write.WriteToExcel) RecursionG(sdp.cash.multiItem.RecursionG) GammaDist(umontreal.ssj.probdist.GammaDist) State(sdp.inventory.State) GetPmf(sdp.inventory.GetPmf)

Example 4 with Recursion

use of sdp.inventory.Recursion in project Stochastic-Inventory by RobinChen121.

the class OneLevelFitsSTest method main.

public static void main(String[] args) {
    String headString = "K, v, h, I0, pai, Qmax, DemandPatt, OpValue, Time(sec), simValue, error";
    WriteToCsv.writeToFile("./" + "test_results.csv", headString);
    double[][] demands = { { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }, { 6.6, 9.3, 11.1, 12.9, 16.8, 21.6, 24, 26.4, 31.5, 33.9, 36.3, 40.8, 44.4, 47.1, 48.3, 50.1, 50.1, 48.9, 47.1, 44.4 }, { 45.9, 48.6, 49.8, 49.8, 48.6, 45.9, 42.3, 37.8, 35.4, 33, 30.3, 27.9, 25.5, 23.1, 20.7, 18.3, 14.4, 10.8, 8.1, 6.3 }, { 36.3, 30, 23.7, 21, 23.7, 30, 36.3, 39, 36.3, 30, 23.7, 21, 23.7, 30, 36.3, 30.9, 24.3, 21.3, 26.4, 33 }, { 47.1, 30, 12.9, 6, 12.9, 30, 47.1, 54, 47.1, 30, 12.9, 6, 12.9, 30, 47.1, 29.7, 15, 7.5, 11.4, 29.7 }, { 62.7, 27.3, 9.9, 23.7, 1, 22.8, 32.7, 34.5, 67.2, 6.6, 14.4, 40.8, 3.9, 63.3, 25.5, 45, 53.1, 24.6, 10.2, 49.8 }, { 1, 15.3, 45.6, 140.1, 80.4, 146.7, 133.8, 74.4, 84.3, 108.9, 46.5, 87.9, 66, 27.9, 32.1, 88.5, 161.7, 36, 32.4, 49.8 }, { 14.1, 24.3, 70.8, 118.2, 49.2, 86.1, 152.4, 117.3, 226.2, 208.2, 78.3, 58.5, 96, 33.3, 57.3, 115.5, 17.7, 134.7, 127.8, 179.7 }, { 13.2, 34.8, 79.2, 43.2, 43.8, 59.4, 22.2, 54.9, 61.2, 34.2, 49.5, 95.4, 35.7, 144.6, 160.2, 103.8, 150.6, 86.4, 122.7, 63.6 }, { 14.7, 56.4, 19.2, 83.7, 135.9, 67.2, 66.9, 155.1, 87.3, 164.1, 193.8, 67.2, 64.5, 132, 34.8, 131.4, 132.9, 35.7, 172.5, 152.1 } };
    double[] K = { 200, 500, 800 };
    double[] v = { 2, 5, 10 };
    double[] pai = { 15, 10, 5 };
    double[] capacity = { 1, 2, 3 };
    double truncationQuantile = 0.9999;
    double stepSize = 1;
    double minInventory = -300;
    double maxInventory = 500;
    double holdingCost = 1;
    for (int iK = 0; iK < K.length; iK++) {
        for (int iv = 0; iv < v.length; iv++) {
            for (int ipai = 0; ipai < pai.length; ipai++) {
                for (int idemand = 0; idemand < demands.length; idemand++) for (int icapacity = 0; icapacity < capacity.length; icapacity++) {
                    // double[] meanDemand = demands[idemand];
                    double[] meanDemand = { 30, 40, 50 };
                    double fixedOrderingCost = K[iK];
                    double proportionalOrderingCost = v[iv];
                    double penaltyCost = pai[ipai];
                    int maxOrderQuantity = (int) (Math.round(Arrays.stream(meanDemand).sum() / meanDemand.length) * capacity[icapacity]);
                    // get demand possibilities for each period
                    int T = meanDemand.length;
                    Distribution[] distributions = IntStream.iterate(0, i -> i + 1).limit(T).mapToObj(// can be changed to other distributions
                    i -> new PoissonDist(meanDemand[i])).toArray(PoissonDist[]::new);
                    double[][][] pmf = new GetPmf(distributions, truncationQuantile, stepSize).getpmf();
                    // feasible actions
                    Function<State, double[]> getFeasibleAction = s -> {
                        double[] feasibleActions = new double[(int) (maxOrderQuantity / stepSize) + 1];
                        int index = 0;
                        for (double i = 0; i <= maxOrderQuantity; i = i + stepSize) {
                            feasibleActions[index] = i;
                            index++;
                        }
                        return feasibleActions;
                    };
                    // state transition function
                    StateTransitionFunction<State, Double, Double, State> stateTransition = (state, action, randomDemand) -> {
                        double nextInventory = state.getIniInventory() + action - randomDemand;
                        nextInventory = nextInventory > maxInventory ? maxInventory : nextInventory;
                        nextInventory = nextInventory < minInventory ? minInventory : nextInventory;
                        return new State(state.getPeriod() + 1, nextInventory);
                    };
                    // immediate value
                    ImmediateValueFunction<State, Double, Double, Double> immediateValue = (state, action, randomDemand) -> {
                        double fixedCost = 0, variableCost = 0, inventoryLevel = 0, holdingCosts = 0, penaltyCosts = 0;
                        fixedCost = action > 0 ? fixedOrderingCost : 0;
                        variableCost = proportionalOrderingCost * action;
                        inventoryLevel = state.getIniInventory() + action - randomDemand;
                        holdingCosts = holdingCost * Math.max(inventoryLevel, 0);
                        penaltyCosts = penaltyCost * Math.max(-inventoryLevel, 0);
                        double totalCosts = fixedCost + variableCost + holdingCosts + penaltyCosts;
                        return totalCosts;
                    };
                    /**
                     *****************************************************************
                     * Solve
                     */
                    Recursion recursion = new Recursion(OptDirection.MIN, pmf, getFeasibleAction, stateTransition, immediateValue);
                    int period = 1;
                    double iniInventory = 0;
                    recursion.setTreeMapCacheAction();
                    State initialState = new State(period, iniInventory);
                    long currTime = System.currentTimeMillis();
                    double finalValue = recursion.getExpectedValue(initialState);
                    System.out.println("final optimal expected value is: " + finalValue);
                    System.out.println("optimal order quantity in the first priod is : " + recursion.getAction(initialState));
                    double time = (System.currentTimeMillis() - currTime) / 1000;
                    System.out.println("running time is " + time + "s");
                    /**
                     *****************************************************************
                     * Simulating single s S results
                     */
                    int sampleNum = 10000;
                    SimulateFitsS simuation = new SimulateFitsS(distributions, sampleNum, recursion);
                    double[][] optTable = recursion.getOptTable();
                    MIPFitsS findsS = new MIPFitsS(maxOrderQuantity, T);
                    double[][] optsS = findsS.getSinglesS(optTable);
                    System.out.println(Arrays.deepToString(optsS));
                    simuation.simulateSDPGivenSamplNum(initialState);
                    double simFinalValue = simuation.simulateSinglesS(initialState, optsS, maxOrderQuantity);
                    System.out.printf("Optimality gap is: %.2f%%\n", (simFinalValue - finalValue) / finalValue * 100);
                    String out = fixedOrderingCost + ",\t" + proportionalOrderingCost + ",\t" + holdingCost + ",\t" + iniInventory + ",\t" + penaltyCost + ",\t" + maxOrderQuantity + ",\t" + (idemand + 1) + ",\t" + finalValue + ",\t" + time + ",\t" + simFinalValue + ",\t" + (simFinalValue - finalValue) / finalValue;
                    WriteToCsv.writeToFile("./" + "test_results.csv", out);
                }
            }
        }
    }
}
Also used : PoissonDist(umontreal.ssj.probdist.PoissonDist) StateTransitionFunction(sdp.inventory.StateTransition.StateTransitionFunction) Recursion(sdp.inventory.Recursion) MIPFitsS(milp.MIPFitsS) ImmediateValueFunction(sdp.inventory.ImmediateValue.ImmediateValueFunction) Function(java.util.function.Function) StateTransitionFunction(sdp.inventory.StateTransition.StateTransitionFunction) State(sdp.inventory.State) GetPmf(sdp.inventory.GetPmf) ImmediateValueFunction(sdp.inventory.ImmediateValue.ImmediateValueFunction)

Example 5 with Recursion

use of sdp.inventory.Recursion in project Stochastic-Inventory by RobinChen121.

the class ThreeLevelFitsSTest method main.

public static void main(String[] args) {
    String headString = "K, v, h, I0, pai, Qmax, DemandPatt, OpValue, Time(sec), simValue, error, K-convexity";
    WriteToCsv.writeToFile("./" + "test_results.csv", headString);
    double[][] iniMeanDemands = { { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }, { 6.6, 9.3, 11.1, 12.9, 16.8, 21.6, 24, 26.4, 31.5, 33.9, 36.3, 40.8, 44.4, 47.1, 48.3, 50.1, 50.1, 48.9, 47.1, 44.4 }, { 45.9, 48.6, 49.8, 49.8, 48.6, 45.9, 42.3, 37.8, 35.4, 33, 30.3, 27.9, 25.5, 23.1, 20.7, 18.3, 14.4, 10.8, 8.1, 6.3 }, { 36.3, 30, 23.7, 21, 23.7, 30, 36.3, 39, 36.3, 30, 23.7, 21, 23.7, 30, 36.3, 30.9, 24.3, 21.3, 26.4, 33 }, { 47.1, 30, 12.9, 6, 12.9, 30, 47.1, 54, 47.1, 30, 12.9, 6, 12.9, 30, 47.1, 29.7, 15, 7.5, 11.4, 29.7 }, { 62.7, 27.3, 9.9, 23.7, 1, 22.8, 32.7, 34.5, 67.2, 6.6, 14.4, 40.8, 3.9, 63.3, 25.5, 45, 53.1, 24.6, 10.2, 49.8 }, { 5, 15.3, 45.6, 140.1, 80.4, 146.7, 133.8, 74.4, 84.3, 108.9, 46.5, 87.9, 66, 27.9, 32.1, 88.5, 161.7, 36, 32.4, 49.8 }, { 14.1, 24.3, 70.8, 118.2, 49.2, 86.1, 152.4, 117.3, 226.2, 208.2, 78.3, 58.5, 96, 33.3, 57.3, 115.5, 17.7, 134.7, 127.8, 179.7 }, { 13.2, 34.8, 79.2, 43.2, 43.8, 59.4, 22.2, 54.9, 61.2, 34.2, 49.5, 95.4, 35.7, 144.6, 160.2, 103.8, 150.6, 86.4, 122.7, 63.6 }, { 14.7, 56.4, 19.2, 83.7, 135.9, 67.2, 66.9, 155.1, 87.3, 164.1, 193.8, 67.2, 64.5, 132, 34.8, 131.4, 132.9, 35.7, 172.5, 152.1 } };
    // 1500, 1000, 500
    double[] K = { 500, 800, 200 };
    double[] v = { 0, 5, 10 };
    // 15, 10, 5
    double[] pai = { 15, 10, 5 };
    // 3, 5, 7
    double[] capacity = { 2, 3, 4 };
    double truncationQuantile = 0.999;
    double stepSize = 1;
    double minInventory = -300;
    double maxInventory = 800;
    double holdingCost = 1;
    /**
     *****************************************************************
     * set demands length, for testing
     */
    int newLength = 6;
    double[][] demands = new double[iniMeanDemands.length][newLength];
    for (int i = 0; i < iniMeanDemands.length; i++) for (int j = 0; j < newLength; j++) {
        demands[i][j] = iniMeanDemands[i][j];
    }
    for (int iK = 0; iK < K.length; iK++) {
        for (int iv = 0; iv < v.length; iv++) {
            for (int ipai = 0; ipai < pai.length; ipai++) {
                for (// demands.length
                int idemand = 0; // demands.length
                idemand < demands.length; // demands.length
                idemand++) for (int icapacity = 0; icapacity < capacity.length; icapacity++) {
                    double[] meanDemand = demands[idemand];
                    double fixedOrderingCost = K[iK];
                    double proportionalOrderingCost = v[iv];
                    double penaltyCost = pai[ipai];
                    int maxOrderQuantity = (int) (Math.round(Arrays.stream(meanDemand).sum() / meanDemand.length) * capacity[icapacity]);
                    // get demand possibilities for each period
                    // 
                    int T = meanDemand.length;
                    Distribution[] distributions = IntStream.iterate(0, i -> i + 1).limit(T).mapToObj(// can be changed to other distributions
                    i -> new PoissonDist(meanDemand[i])).toArray(PoissonDist[]::new);
                    double[][][] pmf = new GetPmf(distributions, truncationQuantile, stepSize).getpmf();
                    // feasible actions
                    Function<State, double[]> getFeasibleAction = s -> {
                        double[] feasibleActions = new double[(int) (maxOrderQuantity / stepSize) + 1];
                        int index = 0;
                        for (double i = 0; i <= maxOrderQuantity; i = i + stepSize) {
                            feasibleActions[index] = i;
                            index++;
                        }
                        return feasibleActions;
                    };
                    // state transition function
                    StateTransitionFunction<State, Double, Double, State> stateTransition = (state, action, randomDemand) -> {
                        double nextInventory = state.getIniInventory() + action - randomDemand;
                        nextInventory = nextInventory > maxInventory ? maxInventory : nextInventory;
                        nextInventory = nextInventory < minInventory ? minInventory : nextInventory;
                        return new State(state.getPeriod() + 1, nextInventory);
                    };
                    // immediate value
                    ImmediateValueFunction<State, Double, Double, Double> immediateValue = (state, action, randomDemand) -> {
                        double fixedCost = 0, variableCost = 0, inventoryLevel = 0, holdingCosts = 0, penaltyCosts = 0;
                        fixedCost = action > 0 ? fixedOrderingCost : 0;
                        variableCost = proportionalOrderingCost * action;
                        inventoryLevel = state.getIniInventory() + action - randomDemand;
                        holdingCosts = holdingCost * Math.max(inventoryLevel, 0);
                        penaltyCosts = penaltyCost * Math.max(-inventoryLevel, 0);
                        double totalCosts = fixedCost + variableCost + holdingCosts + penaltyCosts;
                        return totalCosts;
                    };
                    /**
                     *****************************************************************
                     * Solve
                     */
                    Recursion recursion = new Recursion(OptDirection.MIN, pmf, getFeasibleAction, stateTransition, immediateValue);
                    // recursion.setTreeMapCacheAction(); // using tree map when finding levels for s and S
                    int period = 1;
                    double iniInventory = 0;
                    State initialState = new State(period, iniInventory);
                    long currTime = System.currentTimeMillis();
                    double finalValue = recursion.getExpectedValue(initialState);
                    System.out.println("final optimal expected value is: " + finalValue);
                    System.out.println("optimal order quantity in the first priod is : " + recursion.getAction(initialState));
                    double time = (System.currentTimeMillis() - currTime) / 1000;
                    System.out.println("running time is " + time + "s");
                    /**
                     *****************************************************************
                     * Simulating three level s S results
                     */
                    int sampleNum = 10000;
                    SimulateFitsS simuation = new SimulateFitsS(distributions, sampleNum, recursion);
                    double[][] optTable = recursion.getOptTable();
                    MIPFitsS findsS = new MIPFitsS(maxOrderQuantity, T);
                    double[][] optsS = findsS.getThreesS(optTable);
                    System.out.println(Arrays.deepToString(optsS));
                    simuation.simulateSDPGivenSamplNum(initialState);
                    double simFinalValue = simuation.simulateThreesS(initialState, optsS, maxOrderQuantity);
                    System.out.printf("Optimality gap is: %.2f%%\n", (simFinalValue - finalValue) / finalValue * 100);
                    /**
                     *****************************************************************
                     * Check K-convexity
                     */
                    int minInventorys = 0;
                    int maxInventorys = 100;
                    int xLength = maxInventorys - minInventorys + 1;
                    double[][] yG = new double[xLength][2];
                    int index = 0;
                    for (int initialInventory = minInventorys; initialInventory <= maxInventorys; initialInventory++) {
                        yG[index][0] = initialInventory;
                        yG[index][1] = recursion.getExpectedValue(new State(period, initialInventory));
                        index++;
                    }
                    String string = CheckKConvexity.checkCK(yG, fixedOrderingCost, (int) maxOrderQuantity);
                    String out = fixedOrderingCost + ",\t" + proportionalOrderingCost + ",\t" + holdingCost + ",\t" + iniInventory + ",\t" + penaltyCost + ",\t" + maxOrderQuantity + ",\t" + (idemand + 1) + ",\t" + finalValue + ",\t" + time + ",\t" + simFinalValue + ",\t" + (simFinalValue - finalValue) / finalValue + ",\t" + string;
                    WriteToCsv.writeToFile("./" + "test_results.csv", out);
                }
            }
        }
    }
}
Also used : PoissonDist(umontreal.ssj.probdist.PoissonDist) StateTransitionFunction(sdp.inventory.StateTransition.StateTransitionFunction) Recursion(sdp.inventory.Recursion) MIPFitsS(milp.MIPFitsS) ImmediateValueFunction(sdp.inventory.ImmediateValue.ImmediateValueFunction) Function(java.util.function.Function) StateTransitionFunction(sdp.inventory.StateTransition.StateTransitionFunction) State(sdp.inventory.State) GetPmf(sdp.inventory.GetPmf) ImmediateValueFunction(sdp.inventory.ImmediateValue.ImmediateValueFunction)

Aggregations

Function (java.util.function.Function)7 GetPmf (sdp.inventory.GetPmf)7 ImmediateValueFunction (sdp.inventory.ImmediateValue.ImmediateValueFunction)7 Recursion (sdp.inventory.Recursion)7 State (sdp.inventory.State)7 StateTransitionFunction (sdp.inventory.StateTransition.StateTransitionFunction)7 PoissonDist (umontreal.ssj.probdist.PoissonDist)6 MIPFitsS (milp.MIPFitsS)4 OptDirection (sdp.inventory.Recursion.OptDirection)4 NormalDist (umontreal.ssj.probdist.NormalDist)4 IntStream (java.util.stream.IntStream)3 Distribution (umontreal.ssj.probdist.Distribution)3 Arrays (java.util.Arrays)2 CheckKConvexity (sdp.inventory.CheckKConvexity)2 Drawing (sdp.inventory.Drawing)2 Simulation (sdp.inventory.Simulation)2 DiscreteDistribution (umontreal.ssj.probdist.DiscreteDistribution)2 ArrayList (java.util.ArrayList)1 DoubleStream (java.util.stream.DoubleStream)1 RecursionG (sdp.cash.multiItem.RecursionG)1