Search in sources :

Example 1 with LostSaleChance

use of milp.LostSaleChance in project Stochastic-Inventory by RobinChen121.

the class CashSimulation method simulateSAA.

/**
 * simulate SAA for joint chance problem.
 * @param iniState
 * @param iniQ
 * @param serviceRate
 * @param sampleNums
 * @param prices
 * @param variCostUnits
 * @param overheadCosts
 * @param salvageValueUnit
 * @param holdCostUnit
 * @param scenarios
 * @param sampleNum
 * @return the final value with lost sale rate
 */
public double[] simulateSAA(CashState iniState, double iniQ, double serviceRate, int[] sampleNums, double[] prices, double[] variCostUnits, double[] overheadCosts, double salvageValueUnit, double holdCostUnit, double[][] scenarios, int sampleNum) {
    Sampling.resetStartStream();
    Sampling sampling = new Sampling();
    double[][] samples = sampling.generateLHSamples(distributions, sampleNum);
    double[] simuValues = new double[samples.length];
    int T = samples[0].length;
    int lostSaleCount = 0;
    for (int i = 0; i < samples.length; i++) {
        CashState state = iniState;
        boolean countBeforeBankrupt = false;
        boolean countLostBefore = false;
        double thisValue = 0;
        double optQ = 0;
        double thisServiceRate = 1;
        for (int t = 0; t < T; t++) {
            if (t == 0) {
                optQ = iniQ;
                thisServiceRate = serviceRate;
            }
            // integer samples to test sdp
            double randomDemand = Math.round(samples[i][t]);
            thisValue = state.iniCash + immediateValue.apply(state, optQ, randomDemand);
            if (state.getIniInventory() + optQ < randomDemand - 0.1 && countLostBefore == false) {
                lostSaleCount++;
                countLostBefore = true;
            }
            if (thisValue < -0.1 && countBeforeBankrupt == false) {
                simuValues[i] = 1;
                countBeforeBankrupt = true;
            }
            if (t < T - 1) {
                // very important
                double nextServiceRate = countLostBefore == true ? 0 : thisServiceRate / distributions[t].cdf(optQ + state.getIniInventory());
                state = stateTransition.apply(state, optQ, randomDemand);
                double iniCash = state.iniCash;
                double iniI = state.getIniInventory();
                double[] nextPrices = gettTArray(prices, t + 1);
                int[] nextSampleNums = gettTArray(sampleNums, t + 1);
                double[] nextVariCostUnits = gettTArray(variCostUnits, t + 1);
                Distribution[] nexDistributions = gettTArray(distributions, t + 1);
                double[] nextOverheadCosts = gettTArray(overheadCosts, t + 1);
                double[][] nextScenarios = gettTArray(scenarios, t + 1);
                LostSaleChance model = new LostSaleChance(nexDistributions, nextSampleNums, iniCash, iniI, nextPrices, nextVariCostUnits, salvageValueUnit, holdCostUnit, nextOverheadCosts, nextServiceRate, nextScenarios);
                double[] result = model.solveMaxSurvival();
                optQ = result[0];
                thisServiceRate = nextServiceRate;
            }
        }
    }
    double simFinalValue = 1 - Arrays.stream(simuValues).sum() / (double) samples.length;
    double lostSaleRate = (double) lostSaleCount / (double) sampleNum;
    int n = samples.length;
    double sigma = Math.sqrt(simFinalValue * (1 - simFinalValue) / n);
    double lowCI = simFinalValue - 1.96 * sigma;
    double upCI = simFinalValue + 1.96 * sigma;
    double error = 1.96 * sigma;
    System.out.printf("the confidence interval for simulated  SAA is [%.4f, %.4f], with error is %.4f. \n", lowCI, upCI, error);
    double[] result = { simFinalValue, lostSaleRate };
    return result;
}
Also used : Distribution(umontreal.ssj.probdist.Distribution) LostSaleChance(milp.LostSaleChance) Sampling(sdp.sampling.Sampling)

Example 2 with LostSaleChance

use of milp.LostSaleChance in project Stochastic-Inventory by RobinChen121.

the class ChanceCash method main.

public static void main(String[] args) {
    double iniCash = 150;
    double iniI = 0;
    double trunQuantile = 0.999;
    // the higher value results in slower running speed. maximum negative possibility rate is 1 - serviceRate.
    double serviceRate = 0.6;
    // sample number in each period, the number of samples in the first period can have big influence
    int[] sampleNums = { 5, 5, 5, 5 };
    double[] meanDemand = { 10, 5, 10, 5 };
    int T = sampleNums.length;
    int[] sampleNumsRolling = { 5, 5, 5, 5 };
    // rolling horizon length
    int rollingLength = 2;
    double meanDemandSum = Arrays.stream(meanDemand).sum();
    double rollingDemandSum = Arrays.stream(meanDemand).limit(rollingLength).sum();
    double portion = rollingDemandSum / meanDemandSum;
    double rollingServiceRate = Math.pow(serviceRate, portion);
    // simulating sample number in testing SAA and extended SAA
    int sampleNum = 100;
    double holdCostUnit = 0;
    double salvageValueUnit = 5;
    double[] prices = new double[T];
    double[] variCostUnits = new double[T];
    double[] overheadCosts = new double[T];
    double[] mus = new double[T];
    double sigmasCoe = 0.25;
    Arrays.fill(prices, 22);
    Arrays.fill(variCostUnits, 10);
    // overhead costs
    Arrays.fill(overheadCosts, 100);
    // Arrays.fill(mus, 3.6);
    // Arrays.fill(sigmas, 0.6);
    // maximum ordering quantity when having enough cash
    double maxOrderQuantity = 300;
    Distribution[] distributions = IntStream.iterate(0, i -> i + 1).limit(T).mapToObj(i -> new PoissonDist(meanDemand[i])).toArray(// Poisson demand
    Distribution[]::new);
    // .mapToObj(i -> new LognormalDist(mus[i], sigmas[i])).toArray(Distribution[]::new);
    /**
     * solve the problem by SAA
     */
    // generate scenarios, samples in each period form a scenario tree
    Sampling sampling = new Sampling();
    double[][] scenarios = sampling.generateLHSamples(distributions, sampleNums);
    int sampleNumTotal = IntStream.of(sampleNums).reduce(1, (a, b) -> a * b);
    int sampleNumTotalSimulate = IntStream.of(sampleNumsRolling).limit(rollingLength).reduce(1, (a, b) -> a * b);
    int negativeScenarioNumRequire = (int) (sampleNumTotal * (1 - serviceRate));
    LostSaleChance model = new LostSaleChance(distributions, sampleNums, iniCash, iniI, prices, variCostUnits, salvageValueUnit, holdCostUnit, overheadCosts, serviceRate, scenarios);
    long currTime = System.currentTimeMillis();
    double[] result;
    double time1;
    double positiveScenario;
    double survivalProb;
    double lostRate;
    NumberFormat nf = NumberFormat.getPercentInstance();
    nf.setMinimumFractionDigits(5);
    DecimalFormat df = new DecimalFormat("###, ###");
    result = model.solveMaxSurvival();
    time1 = (System.currentTimeMillis() - currTime) / 1000.00;
    currTime = System.currentTimeMillis();
    System.out.println("**********************************************");
    System.out.println("result of SAA-scenario tree before sorting scenarios: ");
    System.out.println("running time is " + time1 + "s");
    System.out.printf("first stage decison Q is: %.2f\n", result[0]);
    positiveScenario = result[1];
    System.out.printf("Objective value is: %.0f in %d scenarios\n", result[1], sampleNumTotal);
    survivalProb = 100 * result[1] / sampleNumTotal;
    System.out.printf("Survival probability is: %.5f%%\n", survivalProb);
    System.out.println("lost sale scenario number in the solution is : " + result[2]);
    System.out.println("maximum lost sale scenario number allowed is: " + negativeScenarioNumRequire);
    lostRate = result[2] / (double) sampleNumTotal;
    System.out.println("lost sale rate of SAA is: " + nf.format(lostRate));
    System.out.println("lost sale max required rate is: " + nf.format(1 - serviceRate));
    System.out.println();
    /**
     * Simulate the restult of SAA
     */
    int stepSize = 1;
    double fixOrderCost = 0;
    double depositeRate = 0;
    double minInventoryState = 0;
    double maxInventoryState = 500;
    // can affect results, should be smaller than minus fixedOrderCost
    double minCashState = -1000;
    double maxCashState = 2000;
    double discountFactor = 1;
    double[][][] pmf = new GetPmf(distributions, trunQuantile, stepSize).getpmf();
    // immediate value
    ImmediateValueFunction<CashState, Double, Double, Double> immediateValue = (state, action, randomDemand) -> {
        int t = state.getPeriod() - 1;
        double revenue = prices[t] * Math.min(state.getIniInventory() + action, randomDemand);
        double fixedCost = action > 0 ? fixOrderCost : 0;
        double variableCost = variCostUnits[t] * action;
        double deposite = (state.getIniCash() - fixedCost - variableCost) * (1 + depositeRate);
        double inventoryLevel = state.getIniInventory() + action - randomDemand;
        double holdCosts = holdCostUnit * Math.max(inventoryLevel, 0);
        double cashIncrement = revenue + deposite - holdCosts - overheadCosts[t] - state.getIniCash();
        double salValue = state.getPeriod() == T ? salvageValueUnit * Math.max(inventoryLevel, 0) : 0;
        cashIncrement += salValue;
        return cashIncrement;
    };
    // state transition function
    StateTransitionFunction<CashState, Double, Double, CashState> stateTransition = (state, action, randomDemand) -> {
        double nextInventory = Math.max(0, state.getIniInventory() + action - randomDemand);
        double nextCash = state.getIniCash() + immediateValue.apply(state, action, randomDemand);
        nextCash = nextCash > maxCashState ? maxCashState : nextCash;
        nextCash = nextCash < minCashState ? minCashState : nextCash;
        nextInventory = nextInventory > maxInventoryState ? maxInventoryState : nextInventory;
        nextInventory = nextInventory < minInventoryState ? minInventoryState : nextInventory;
        // cash is integer or not
        // the right should be a decimal
        nextCash = Math.round(nextCash * 1) / 1;
        return new CashState(state.getPeriod() + 1, nextInventory, nextCash);
    };
    int period = 1;
    CashState initialState = new CashState(period, iniI, iniCash);
    double[] result1;
    // no need to add overheadCost in this class
    CashSimulation simulation1 = new CashSimulation(distributions, sampleNum, immediateValue, stateTransition);
    double error;
    double thisServiceRate;
    result1 = simulation1.simulateSAA(initialState, result[0], serviceRate, sampleNums, prices, variCostUnits, overheadCosts, salvageValueUnit, holdCostUnit, scenarios, sampleNum);
    System.out.println("final simulated survival probability of SAA in " + df.format(sampleNum) + " samples is: " + nf.format(result1[0]));
    error = 1.96 * Math.sqrt(result1[1] * (1 - result1[1]) / sampleNum);
    thisServiceRate = 1 - result1[1];
    System.out.println("final simulated service sale rate of SAA " + " is: " + nf.format(thisServiceRate) + " with error " + nf.format(error));
    /**
     * solve the problem by extended formulation of SAA,
     * sort scenarios in the whole planning horizon
     */
    currTime = System.currentTimeMillis();
    // same result with soveSort or solveSort2, but less computational time
    result = model.solveSortWhole();
    // former name is solveSortFurther()
    time1 = (System.currentTimeMillis() - currTime) / 1000.00;
    currTime = System.currentTimeMillis();
    System.out.println("**********************************************");
    System.out.println("after sorting scenarios in the whole planning horizon, result of SAA-scenario tree: ");
    System.out.println("running time is " + time1 + "s");
    System.out.printf("first stage decison Q is: %.2f\n", result[0]);
    positiveScenario = result[1];
    System.out.printf("Objective value is: %.0f in %d scenarios\n", positiveScenario, sampleNumTotal);
    survivalProb = 100 * result[1] / sampleNumTotal;
    System.out.printf("Survival probability is: %.5f%%\n", survivalProb);
    System.out.println("lost sale scenario number in the solution is : " + result[2]);
    System.out.println("maximum lost sale scenario number allowed is: " + negativeScenarioNumRequire);
    lostRate = result[2] / (double) sampleNumTotal;
    System.out.println("lost sale rate of SAA is: " + nf.format(lostRate));
    System.out.println("lost sale max required rate is: " + nf.format(1 - serviceRate));
    System.out.println();
    /**
     * Simulate the result of extended SAA
     */
    result1 = simulation1.simulateExtendSAAWhole(initialState, result[0], serviceRate, sampleNums, prices, variCostUnits, overheadCosts, salvageValueUnit, holdCostUnit, scenarios, sampleNum);
    System.out.println("final simulated survival probability of extended SAA(sort whole planning horizon) in " + df.format(sampleNum) + " samples is: " + nf.format(result1[0]));
    error = 1.96 * Math.sqrt(result1[1] * (1 - result1[1]) / sampleNum);
    thisServiceRate = 1 - result1[1];
    System.out.println("final simulated service rate of extended SAA(sort whole planning horizon) " + " is: " + nf.format(thisServiceRate) + " with error " + nf.format(error));
    /**
     * solve the problem by extended formulation of SAA,
     * sort scenarios in each period.
     */
    // currTime = System.currentTimeMillis();
    // result = model.solveSortEach();	// same result with soveSort or solveSort2, but less computational time
    // // former name is solveSortFurther()
    // 
    // time1 = (System.currentTimeMillis() - currTime) / 1000.00;
    // currTime = System.currentTimeMillis();
    // System.out.println("**********************************************");
    // System.out.println("after sorting scenarios in each period, the result of SAA-scenario tree: ");
    // System.out.println("running time is " + time1 + "s");
    // System.out.printf("first stage decison Q is: %.2f\n", result[0]);
    // positiveScenario = result[1];
    // System.out.printf("Objective value is: %.0f in %d scenarios\n", positiveScenario, sampleNumTotal);
    // survivalProb = 100 * result[1] / sampleNumTotal;
    // System.out.printf("Survival probability is: %.5f%%\n", survivalProb);
    // System.out.println("lost sale scenario number in the solution is : " + result[2]);
    // System.out.println("maximum lost sale scenario number allowed is: " + negativeScenarioNumRequire);
    // lostRate = result[2] / (double) sampleNumTotal;
    // System.out.println("lost sale rate of SAA is: " + nf.format(lostRate));
    // System.out.println("lost sale max required rate is: " + nf.format(1 - serviceRate));
    // System.out.println();
    // 
    // /**
    // * Simulate the result of extended SAA sorting each period
    // */
    // result1 = simulation1.simulateExtendSAAEach(initialState, result[0], serviceRate, sampleNums, prices, variCostUnits, overheadCosts, salvageValueUnit, holdCostUnit, scenarios, sampleNum);
    // System.out.println("final simulated survival probability of extended SAA sorting each period in " + df.format(sampleNum) + " samples is: " + nf.format(result1[0]));
    // System.out.println("final simulated lost sale rate of extended SAA sorting each period " + " is: " + nf.format(result1[1]));
    /**
     * solve the problem by SDP when there is no joint chance constraint
     */
    // feasible actions
    Function<CashState, double[]> getFeasibleAction1 = s -> {
        int t = s.getPeriod() - 1;
        double thisPeriodServRate = (1 - serviceRate) / T;
        // double minQ = Math.ceil(distributions[t].inverseF(1 - thisPeriodServRate)); // minimum ordering quantity in each period
        double minQ = 0;
        return DoubleStream.iterate(minQ, i -> i + stepSize).limit((int) maxOrderQuantity + 1).toArray();
    };
    /**
     *****************************************************************
     * Solve
     */
    CashRecursion recursion = new CashRecursion(OptDirection.MAX, pmf, getFeasibleAction1, stateTransition, immediateValue, discountFactor);
    currTime = System.currentTimeMillis();
    recursion.setTreeMapCacheAction();
    double finalValue = recursion.getSurvProb(initialState);
    System.out.println("**********************************************");
    System.out.println("result of SDP with no service rate constraint is: ");
    System.out.println("survival probability for this initial state is: " + nf.format(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 sdp results
     */
    sampleNum = 10000;
    // no need to add overheadCost in this class
    CashSimulation simulation = new CashSimulation(distributions, sampleNum, recursion, discountFactor);
    double[] result2 = simulation.simulateSDPGivenSamplNum(initialState, immediateValue);
    System.out.println("final simulated survival probability in " + df.format(sampleNum) + " samples is: " + nf.format(result2[0]));
    System.out.println("final simulated lost sale rate " + " is: " + nf.format(result2[1]));
    /**
     *****************************************************************
     * solve the problem by SDP when there is individual chance constraint approximation
     */
    // feasible actions 2
    // in fact, no cash constraint in this paper
    Function<CashState, double[]> getFeasibleAction2 = s -> {
        int t = s.getPeriod() - 1;
        double thisPeriodServRate = (1 - serviceRate) / T;
        // minimum ordering quantity in each period
        double minQ = Math.ceil(distributions[t].inverseF(1 - thisPeriodServRate));
        return DoubleStream.iterate(minQ, i -> i + stepSize).limit((int) maxOrderQuantity + 1).toArray();
    };
    /**
     *****************************************************************
     * Solve
     */
    recursion = new CashRecursion(OptDirection.MAX, pmf, getFeasibleAction2, stateTransition, immediateValue, discountFactor);
    period = 1;
    initialState = new CashState(period, iniI, iniCash);
    currTime = System.currentTimeMillis();
    recursion.setTreeMapCacheAction();
    finalValue = recursion.getSurvProb(initialState);
    System.out.println("**********************************************");
    System.out.println("result of SDP with service rate constraint is: ");
    finalValue = finalValue * 100;
    System.out.printf("survival probability for this initial state is: %.2f%%\n", finalValue);
    System.out.println("optimal order quantity in the first priod is : " + recursion.getAction(initialState));
    time = (System.currentTimeMillis() - currTime) / 1000;
    System.out.println("running time is " + time + "s");
    /**
     *****************************************************************
     * Simulating sdp results
     */
    sampleNum = 10000;
    // no need to add overheadCost in this class
    simulation = new CashSimulation(distributions, sampleNum, recursion, discountFactor);
    result2 = simulation.simulateSDPGivenSamplNum(initialState, immediateValue);
    System.out.println("final simulated survival probability in " + df.format(sampleNum) + " samples is: " + nf.format(result2[0]));
    System.out.println("final simulated lost sale rate " + " is: " + nf.format(result2[1]));
    /**
     * solve the problem by rolling horizon of further SAA
     */
    // number of scenarios for rolling SAA
    sampleNum = 100;
    currTime = System.currentTimeMillis();
    System.out.println("**********************************************");
    result1 = simulation1.rollingHoirzonFurtherExtendSAA(rollingLength, initialState, rollingServiceRate, sampleNumsRolling, prices, variCostUnits, overheadCosts, salvageValueUnit, holdCostUnit, scenarios, sampleNum);
    time1 = (System.currentTimeMillis() - currTime) / 1000.00;
    System.out.println("after rolling horizon for length " + rollingLength + ", result of SAA-scenario tree: ");
    System.out.println("running time is " + time1 + "s");
    System.out.println("final simulated survival probability of rolling further SAA in " + df.format(sampleNum) + " samples is: " + nf.format(result1[0]));
    System.out.println("final simulated lost sale rate of rolling further SAA " + " is: " + nf.format(result1[1]));
}
Also used : IntStream(java.util.stream.IntStream) ImmediateValueFunction(sdp.inventory.ImmediateValue.ImmediateValueFunction) CashSimulation(sdp.cash.CashSimulation) Arrays(java.util.Arrays) GRBException(gurobi.GRBException) CashRecursion(sdp.cash.CashRecursion) OptDirection(sdp.cash.CashRecursion.OptDirection) CashState(sdp.cash.CashState) Function(java.util.function.Function) IntPredicate(java.util.function.IntPredicate) NumberFormat(java.text.NumberFormat) ArrayList(java.util.ArrayList) GRBModel(gurobi.GRBModel) PositiveCashChance(milp.PositiveCashChance) Printable(java.awt.print.Printable) Collector(java.util.stream.Collector) Result(com.sun.net.httpserver.Authenticator.Result) PoissonDist(umontreal.ssj.probdist.PoissonDist) Distribution(umontreal.ssj.probdist.Distribution) IntFunction(java.util.function.IntFunction) LostSaleChance(milp.LostSaleChance) GRBVar(gurobi.GRBVar) SimulateChanceCash(milp.SimulateChanceCash) BufferedWriter(java.io.BufferedWriter) GRBLinExpr(gurobi.GRBLinExpr) FileWriter(java.io.FileWriter) DecimalFormat(java.text.DecimalFormat) NormalDist(umontreal.ssj.probdist.NormalDist) IOException(java.io.IOException) LognormalDist(umontreal.ssj.probdist.LognormalDist) Sampling(sdp.sampling.Sampling) Collectors(java.util.stream.Collectors) StateTransitionFunction(sdp.inventory.StateTransition.StateTransitionFunction) DoubleStream(java.util.stream.DoubleStream) GetPmf(sdp.inventory.GetPmf) List(java.util.List) CartesianProduct(sdp.sampling.CartesianProduct) GRBEnv(gurobi.GRBEnv) GRB(gurobi.GRB) CashSimulation(sdp.cash.CashSimulation) PoissonDist(umontreal.ssj.probdist.PoissonDist) DecimalFormat(java.text.DecimalFormat) CashRecursion(sdp.cash.CashRecursion) Distribution(umontreal.ssj.probdist.Distribution) CashState(sdp.cash.CashState) LostSaleChance(milp.LostSaleChance) Sampling(sdp.sampling.Sampling) GetPmf(sdp.inventory.GetPmf) NumberFormat(java.text.NumberFormat)

Example 3 with LostSaleChance

use of milp.LostSaleChance in project Stochastic-Inventory by RobinChen121.

the class CashSimulation method simulateExtendSAAWhole.

/**
 * simulate the extended SAA sorting the whole planning horizon.
 * @param iniState
 * @param iniQ
 * @param serviceRate
 * @param sampleNums
 * @param prices
 * @param variCostUnits
 * @param overheadCosts
 * @param salvageValueUnit
 * @param holdCostUnit
 * @param scenarios
 * @param sampleNum
 * @return the final value with lost sale rate.
 */
public double[] simulateExtendSAAWhole(CashState iniState, double iniQ, double serviceRate, int[] sampleNums, double[] prices, double[] variCostUnits, double[] overheadCosts, double salvageValueUnit, double holdCostUnit, double[][] scenarios, int sampleNum) {
    Sampling.resetStartStream();
    Sampling sampling = new Sampling();
    double[][] samples = sampling.generateLHSamples(distributions, sampleNum);
    double[] simuValues = new double[samples.length];
    int T = samples[0].length;
    int lostSaleCount = 0;
    for (int i = 0; i < samples.length; i++) {
        CashState state = iniState;
        boolean countBeforeBankrupt = false;
        boolean countLostBefore = false;
        double thisValue = 0;
        double optQ = 0;
        double thisServiceRate = 1;
        for (int t = 0; t < T; t++) {
            if (t == 0) {
                optQ = iniQ;
                thisServiceRate = serviceRate;
            }
            // integer samples to test sdp
            double randomDemand = Math.round(samples[i][t]);
            thisValue = state.iniCash + immediateValue.apply(state, optQ, randomDemand);
            if (state.getIniInventory() + optQ < randomDemand - 0.1 && countLostBefore == false) {
                lostSaleCount++;
                countLostBefore = true;
            }
            if (thisValue < -0.1 && countBeforeBankrupt == false) {
                simuValues[i] = 1;
                countBeforeBankrupt = true;
            }
            if (t < T - 1) {
                // revise
                double thisPeriodServRate = distributions[t].cdf(optQ + state.getIniInventory());
                double nextServiceRate = 0;
                if (countLostBefore == true)
                    nextServiceRate = 0;
                else {
                    nextServiceRate = thisPeriodServRate < thisServiceRate ? thisServiceRate : thisServiceRate / thisPeriodServRate;
                }
                // very important
                state = stateTransition.apply(state, optQ, randomDemand);
                double iniCash = state.iniCash;
                double iniI = state.getIniInventory();
                double[] nextPrices = gettTArray(prices, t + 1);
                int[] nextSampleNums = gettTArray(sampleNums, t + 1);
                double[] nextVariCostUnits = gettTArray(variCostUnits, t + 1);
                Distribution[] nexDistributions = gettTArray(distributions, t + 1);
                double[] nextOverheadCosts = gettTArray(overheadCosts, t + 1);
                double[][] nextScenarios = gettTArray(scenarios, t + 1);
                LostSaleChance model = new LostSaleChance(nexDistributions, nextSampleNums, iniCash, iniI, nextPrices, nextVariCostUnits, salvageValueUnit, holdCostUnit, nextOverheadCosts, nextServiceRate, nextScenarios);
                double[] result = model.solveSortWhole();
                optQ = result[0];
                thisServiceRate = nextServiceRate;
            }
        }
    }
    int n = samples.length;
    double simFinalValue = 1 - Arrays.stream(simuValues).sum() / (double) samples.length;
    double sigma = Math.sqrt(simFinalValue * (1 - simFinalValue) / n);
    double lowCI = simFinalValue - 1.96 * sigma;
    double upCI = simFinalValue + 1.96 * sigma;
    double error = 1.96 * sigma;
    System.out.printf("the confidence interval for simulated extened SAA sorting whole is [%.4f, %.4f], with error %.4f\n", lowCI, upCI, error);
    double lostSaleRate = (double) lostSaleCount / (double) sampleNum;
    double[] result = { simFinalValue, lostSaleRate };
    return result;
}
Also used : Distribution(umontreal.ssj.probdist.Distribution) LostSaleChance(milp.LostSaleChance) Sampling(sdp.sampling.Sampling)

Example 4 with LostSaleChance

use of milp.LostSaleChance in project Stochastic-Inventory by RobinChen121.

the class CashSimulation method simulateSAA2.

/**
 * simulate SAA for joint chance problem with another chance updating method.
 * @param iniState
 * @param iniQ
 * @param serviceRate
 * @param sampleNums
 * @param prices
 * @param variCostUnits
 * @param overheadCosts
 * @param salvageValueUnit
 * @param holdCostUnit
 * @param scenarios
 * @param sampleNum
 * @return the final value with lost sale rate
 */
public double[] simulateSAA2(CashState iniState, double iniQ, double serviceRate, int[] sampleNums, double[] prices, double[] variCostUnits, double[] overheadCosts, double salvageValueUnit, double holdCostUnit, double[][] scenarios, int sampleNum) {
    Sampling.resetStartStream();
    Sampling sampling = new Sampling();
    double[][] samples = sampling.generateLHSamples2(distributions, sampleNum);
    int maxLostScenarioNum = (int) (sampleNum * (1 - serviceRate));
    double[] simuValues = new double[samples.length];
    int T = samples[0].length;
    CashState[] state = new CashState[samples.length];
    Arrays.fill(state, iniState);
    double[] optQ = new double[samples.length];
    Arrays.fill(optQ, iniQ);
    boolean[] countLostBefore = new boolean[samples.length];
    boolean[] countBeforeBankrupt = new boolean[samples.length];
    int lostSaleCount = 0;
    for (int t = 0; t < T; t++) {
        double thisValue = 0;
        for (int i = 0; i < samples.length; i++) {
            double randomDemand = Math.round(samples[i][t]);
            if (state[i].getIniInventory() + optQ[i] < randomDemand - 0.1 && countLostBefore[i] == false) {
                lostSaleCount++;
                countLostBefore[i] = true;
            }
            thisValue = state[i].iniCash + immediateValue.apply(state[i], optQ[i], randomDemand);
            if (thisValue < -0.1 && countBeforeBankrupt[i] == false) {
                simuValues[i] = 1;
                countBeforeBankrupt[i] = true;
            }
            state[i] = stateTransition.apply(state[i], optQ[i], randomDemand);
        }
        double lostRate = (double) (maxLostScenarioNum - lostSaleCount) / (double) (sampleNum - lostSaleCount);
        double updateServiceRate = 1 - lostRate;
        for (int i = 0; i < samples.length; i++) {
            if (t < T - 1) {
                // very important
                double nextServiceRate = countLostBefore[i] == true ? 0 : updateServiceRate;
                double iniCash = state[i].iniCash;
                double iniI = state[i].getIniInventory();
                double[] nextPrices = gettTArray(prices, t + 1);
                int[] nextSampleNums = gettTArray(sampleNums, t + 1);
                double[] nextVariCostUnits = gettTArray(variCostUnits, t + 1);
                Distribution[] nexDistributions = gettTArray(distributions, t + 1);
                double[] nextOverheadCosts = gettTArray(overheadCosts, t + 1);
                double[][] nextScenarios = gettTArray(scenarios, t + 1);
                LostSaleChance model = new LostSaleChance(nexDistributions, nextSampleNums, iniCash, iniI, nextPrices, nextVariCostUnits, salvageValueUnit, holdCostUnit, nextOverheadCosts, nextServiceRate, nextScenarios);
                double[] result = model.solveMaxSurvival();
                optQ[i] = result[0];
            }
        }
    }
    double simFinalValue = 1 - Arrays.stream(simuValues).sum() / (double) samples.length;
    double lostSaleRate = (double) lostSaleCount / (double) sampleNum;
    double[] result = { simFinalValue, lostSaleRate };
    return result;
}
Also used : Distribution(umontreal.ssj.probdist.Distribution) LostSaleChance(milp.LostSaleChance) Sampling(sdp.sampling.Sampling)

Example 5 with LostSaleChance

use of milp.LostSaleChance in project Stochastic-Inventory by RobinChen121.

the class CashSimulation method simulateExtendSAA2.

/**
 * simulate extended SAA for another lost sale updating
 * @param iniState
 * @param iniQ
 * @param serviceRate
 * @param sampleNums
 * @param prices
 * @param variCostUnits
 * @param overheadCosts
 * @param salvageValueUnit
 * @param holdCostUnit
 * @param scenarios
 * @param sampleNum
 * @return
 */
public double[] simulateExtendSAA2(CashState iniState, double iniQ, double serviceRate, int[] sampleNums, double[] prices, double[] variCostUnits, double[] overheadCosts, double salvageValueUnit, double holdCostUnit, double[][] scenarios, int sampleNum) {
    Sampling.resetStartStream();
    Sampling sampling = new Sampling();
    double[][] samples = sampling.generateLHSamples2(distributions, sampleNum);
    int maxLostScenarioNum = (int) (sampleNum * (1 - serviceRate));
    double[] simuValues = new double[samples.length];
    int T = samples[0].length;
    CashState[] state = new CashState[samples.length];
    Arrays.fill(state, iniState);
    double[] optQ = new double[samples.length];
    Arrays.fill(optQ, iniQ);
    boolean[] countLostBefore = new boolean[samples.length];
    boolean[] countBeforeBankrupt = new boolean[samples.length];
    double[] periodServiceRate = new double[samples.length];
    Arrays.fill(periodServiceRate, serviceRate);
    int lostSaleCount = 0;
    for (int t = 0; t < T; t++) {
        double thisValue = 0;
        for (int i = 0; i < samples.length; i++) {
            double randomDemand = Math.round(samples[i][t]);
            if (state[i].getIniInventory() + optQ[i] < randomDemand - 0.1 && countLostBefore[i] == false) {
                lostSaleCount++;
                countLostBefore[i] = true;
            }
            thisValue = state[i].iniCash + immediateValue.apply(state[i], optQ[i], randomDemand);
            if (thisValue < -0.1 && countBeforeBankrupt[i] == false) {
                simuValues[i] = 1;
                countBeforeBankrupt[i] = true;
            }
            state[i] = stateTransition.apply(state[i], optQ[i], randomDemand);
        }
        double lostRate = (double) (maxLostScenarioNum - lostSaleCount) / (double) (sampleNum - lostSaleCount);
        double updateServiceRate = Math.max(serviceRate, 1 - lostRate);
        for (int i = 0; i < samples.length; i++) {
            if (t < T - 1) {
                double thisPeriodServRate = distributions[t].cdf(optQ[i] + state[i].getIniInventory());
                periodServiceRate[i] = Math.max(updateServiceRate, thisPeriodServRate);
                // updateServiceRate; //very important
                double nextServiceRate = countLostBefore[i] == true ? 0 : periodServiceRate[i];
                double iniCash = state[i].iniCash;
                double iniI = state[i].getIniInventory();
                double[] nextPrices = gettTArray(prices, t + 1);
                int[] nextSampleNums = gettTArray(sampleNums, t + 1);
                double[] nextVariCostUnits = gettTArray(variCostUnits, t + 1);
                Distribution[] nexDistributions = gettTArray(distributions, t + 1);
                double[] nextOverheadCosts = gettTArray(overheadCosts, t + 1);
                double[][] nextScenarios = gettTArray(scenarios, t + 1);
                LostSaleChance model = new LostSaleChance(nexDistributions, nextSampleNums, iniCash, iniI, nextPrices, nextVariCostUnits, salvageValueUnit, holdCostUnit, nextOverheadCosts, nextServiceRate, nextScenarios);
                double[] result = model.solveSortEach();
                optQ[i] = result[0];
            }
        }
    }
    double simFinalValue = 1 - Arrays.stream(simuValues).sum() / (double) samples.length;
    double lostSaleRate = (double) lostSaleCount / (double) sampleNum;
    double[] result = { simFinalValue, lostSaleRate };
    return result;
}
Also used : Distribution(umontreal.ssj.probdist.Distribution) LostSaleChance(milp.LostSaleChance) Sampling(sdp.sampling.Sampling)

Aggregations

LostSaleChance (milp.LostSaleChance)7 Sampling (sdp.sampling.Sampling)7 Distribution (umontreal.ssj.probdist.Distribution)7 Result (com.sun.net.httpserver.Authenticator.Result)1 GRB (gurobi.GRB)1 GRBEnv (gurobi.GRBEnv)1 GRBException (gurobi.GRBException)1 GRBLinExpr (gurobi.GRBLinExpr)1 GRBModel (gurobi.GRBModel)1 GRBVar (gurobi.GRBVar)1 Printable (java.awt.print.Printable)1 BufferedWriter (java.io.BufferedWriter)1 FileWriter (java.io.FileWriter)1 IOException (java.io.IOException)1 DecimalFormat (java.text.DecimalFormat)1 NumberFormat (java.text.NumberFormat)1 ArrayList (java.util.ArrayList)1 Arrays (java.util.Arrays)1 List (java.util.List)1 Function (java.util.function.Function)1