Search in sources :

Example 1 with MipCashConstraint

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

the class CashConstraint method main.

// d=[8, 10, 10], iniCash=20, K=10; price=5, v=1; h = 1
public static void main(String[] args) {
    double[] meanDemand = { 10 };
    // double[] meanDemand = {20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20};
    double iniInventory = 0;
    double iniCash = 200;
    double fixOrderCost = 0;
    double variCost = 2;
    double[] price = { 6 };
    double depositeRate = 0;
    double salvageValue = 1;
    double holdingCost = 0;
    FindCCrieria criteria = FindCCrieria.XRELATE;
    // costs like wages or rents which is required to pay in each period
    double overheadCost = 0;
    // rate from revenue to pay overhead wages
    double overheadRate = 0;
    // maximum ordering quantity when having enough cash
    double maxOrderQuantity = 200;
    double truncationQuantile = 0.9999;
    int stepSize = 1;
    double minInventoryState = 0;
    double maxInventoryState = 500;
    // can affect results, should be smaller than minus fixedOrderCost
    double minCashState = -1000;
    double maxCashState = 2000;
    // large penalty cost cause big gaps for simulation results, since may generate zero demand
    double penaltyCost = 0;
    double discountFactor = 1;
    // 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])).toArray(Distribution[]::new);
    // double[] values1 = {6, 7};
    // double[] probs1 = {0.95, 0.05};
    // double[] values2 = {6, 7};
    // double[] probs2 = {0.95, 0.05};
    // DiscreteDistribution[] distributions = new DiscreteDistribution[T];
    // for (int i = 0; i < T; i++) {
    // if (i % 2 == 0)
    // distributions[i] = new DiscreteDistribution(values1, probs1, values1.length);
    // else
    // distributions[i] = new DiscreteDistribution(values2, probs2, values2.length);
    // }
    double[][][] pmf = new GetPmf(distributions, truncationQuantile, stepSize).getpmf();
    // feasible actions
    Function<CashState, double[]> getFeasibleAction = s -> {
        double maxQ = // maxOrderQuantity;
        (int) Math.min(maxOrderQuantity, Math.max(0, (s.getIniCash() - overheadCost - fixOrderCost) / variCost));
        return DoubleStream.iterate(0, i -> i + stepSize).limit((int) maxQ + 1).toArray();
    };
    // immediate value
    ImmediateValueFunction<CashState, Double, Double, Double> immediateValue = (state, action, randomDemand) -> {
        int t = state.getPeriod() - 1;
        double revenue = price[t] * Math.min(state.getIniInventory() + action, randomDemand);
        double fixedCost = action > 0 ? fixOrderCost : 0;
        double variableCost = variCost * action;
        double deposite = (state.getIniCash() - fixedCost - variableCost) * (1 + depositeRate);
        double inventoryLevel = state.getIniInventory() + action - randomDemand;
        double holdCosts = holdingCost * Math.max(inventoryLevel, 0);
        double cashIncrement = (1 - overheadRate) * revenue + deposite - holdCosts - overheadCost - state.getIniCash();
        double salValue = state.getPeriod() == T ? salvageValue * Math.max(inventoryLevel, 0) : 0;
        cashIncrement += salValue;
        double endCash = state.getIniCash() + cashIncrement;
        if (endCash < 0) {
            cashIncrement += penaltyCost * endCash;
        }
        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 * 10) / 10.0;
        return new CashState(state.getPeriod() + 1, nextInventory, nextCash);
    };
    /**
     *****************************************************************
     * Solve
     */
    CashRecursion recursion = new CashRecursion(OptDirection.MAX, pmf, getFeasibleAction, stateTransition, immediateValue, discountFactor);
    int period = 1;
    CashState initialState = new CashState(period, iniInventory, iniCash);
    long currTime = System.currentTimeMillis();
    recursion.setTreeMapCacheAction();
    double finalValue = iniCash + recursion.getExpectedValue(initialState);
    System.out.println("final optimal cash  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 sdp results
     * parameter vales like price, variCost, holdingCost etc.
     * are only for compute L(y), not very necessary
     */
    int sampleNum = 10000;
    // no need to add overheadCost in this class
    CashSimulation simulation = new CashSimulation(distributions, sampleNum, recursion, discountFactor);
    double simFinalValue = simulation.simulateSDPGivenSamplNum(initialState);
    double error = 0.0001;
    double confidence = 0.95;
    simulation.simulateSDPwithErrorConfidence(initialState, error, confidence);
    double defaultRisk = simulation.simulateDefaultProb(initialState);
    System.out.println("default risk is " + defaultRisk);
/**
 *****************************************************************
 * Find (s, C1, C2 S) by SDP and simulate
 */
// System.out.println("");
// double[][] optTable = recursion.getOptTable();
// FindsCS findsCS = new FindsCS(iniCash, distributions, fixOrderCost, price, variCost, holdingCost, salvageValue);
// double[][] optsC12S = findsCS.getsC12S(optTable, overheadCost, criteria);
// Map<State, Double> cacheC1Values = new TreeMap<>();
// Map<State, Double> cacheC2Values = new TreeMap<>();
// double simsCSFinalValue = simulation.simulatesCS(initialState, optsC12S, cacheC1Values, cacheC2Values,
// overheadCost, maxOrderQuantity, fixOrderCost, variCost);
// double gap1 = (finalValue -simsCSFinalValue)/finalValue;
// double gap2 = (simFinalValue -simsCSFinalValue)/simFinalValue;
// System.out.printf("Optimality gap for (s, C1, C2 S) is: %.2f%% or %.2f%%\n", gap1 * 100, gap2 * 100);
// 
// /*******************************************************************
// * Find (s, C1, S) by SDP and simulate
// */
// System.out.println("");
// System.out.println("************************************************");
// double[][] optsCS = findsCS.getsCS(optTable, overheadCost, criteria);
// cacheC1Values = findsCS.cacheC1Values;
// simsCSFinalValue = simulation.simulatesCS(initialState, optsCS, cacheC1Values,
// overheadCost, maxOrderQuantity, fixOrderCost, variCost);
// double gap21 = (finalValue -simsCSFinalValue)/finalValue;
// double gap22 = (simFinalValue -simsCSFinalValue)/simFinalValue;
// System.out.printf("Optimality gap for (s, C1, S) is: %.2f%% or %.2f%%\n", gap21 * 100, gap22 * 100);
// double[][] numFrequency = findsCS.getMaxSFrequency(optTable, overheadCost, criteria);
// System.out.println("most frequent S in each period");
// System.out.println(Arrays.deepToString(numFrequency));
/**
 *****************************************************************
 * Find (s, meanC, S) by SDP and simulate
 */
// System.out.println("");
// System.out.println("************************************************");
// optsCS = findsCS.getsCS(optTable, overheadCost, FindCCrieria.AVG);
// simsCSFinalValue = simulation.simulatesMeanCS(initialState, optsCS, overheadCost, maxOrderQuantity, fixOrderCost, variCost);
// double gap31 = (finalValue -simsCSFinalValue)/finalValue;
// double gap32 = (simFinalValue -simsCSFinalValue)/simFinalValue;
// System.out.printf("Optimality gap for (s, meanC, S) is: %.2f%% or %.2f%%\n", gap31 * 100, gap32 * 100);
/**
 *****************************************************************
 * Check (s, C1, C2, S) policy,
 * sometimes not always hold, because in certain period
 * for some state C is 12, and 13 in other state,
 * we use heuristic step by choosing maximum one
 */
// findsCS.checksCS(optsCS, optTable, overheadCost, maxOrderQuantity, fixOrderCost, variCost);
// System.out.printf(
// "\n*******************************************************************\n");
/**
 *****************************************************************
 * Find (s, C, S) by MIP and simulate
 */
// System.out.println("************************************************");
// MipCashConstraint mipHeuristic = new MipCashConstraint(iniInventory, iniCash, fixOrderCost, variCost, holdingCost, price, salvageValue, distributions, overheadCost);
// double[][] sCS = mipHeuristic.findsCSPieceWise();
// Map<State, Double> cacheCValues = new TreeMap<>();
// cacheCValues = mipHeuristic.cacheC1Values;
// double simsCSMIPValue = simulation.simulatesCS(initialState, sCS, cacheCValues, overheadCost, maxOrderQuantity, fixOrderCost, variCost);
// gap1 = (finalValue - simsCSMIPValue)/finalValue;
// gap2 = (simFinalValue - simsCSMIPValue)/simFinalValue;
// System.out.printf("Optimality gap is: %.2f%% or %.2f%%\n", gap1 * 100, gap2 * 100);
// /*******************************************************************
// * Check CK-convexity
// */
// 
// // immediate value
// boolean isForDrawGy = true;
// ImmediateValueFunction<CashState, Double, Double, Double> immediateValue2 = (state, action, randomDemand) -> {
// double revenue = 0;
// double fixedCost = 0;
// double variableCost = 0;
// double inventoryLevel = 0;
// if (isForDrawGy == true && state.getPeriod() == 1) {
// revenue = price * Math.min(state.getIniInventory(), randomDemand);
// fixedCost = 0;
// variableCost = variCost * state.getIniInventory();
// inventoryLevel = state.getIniInventory() - randomDemand;
// } else {
// revenue = price * Math.min(state.getIniInventory() + action, randomDemand);
// fixedCost = action > 0 ? fixOrderCost : 0;
// variableCost = variCost * action;
// inventoryLevel = state.getIniInventory() + action - randomDemand;
// }
// double holdCosts = holdingCost * Math.max(inventoryLevel, 0);
// double cashIncrement = revenue - fixedCost - variableCost - holdCosts - overheadCost;
// double salValue = state.getPeriod() == T ? salvageValue * Math.max(inventoryLevel, 0) : 0;
// cashIncrement += salValue;
// return cashIncrement;
// };
// 
// // state transition function 2
// StateTransitionFunction<CashState, Double, Double, CashState> stateTransition2 = (state, action,
// randomDemand) -> {
// double nextInventory = isForDrawGy && state.getPeriod() == 1 ? state.getIniInventory() - randomDemand
// : state.getIniInventory() + action - randomDemand;
// double nextCash = state.getIniCash() + immediateValue2.apply(state, action, randomDemand);
// if (isForDrawGy == true && state.getPeriod() == 1) // this is the only difference with transition function3
// nextCash -= fixOrderCost;
// nextCash = nextCash > maxCashState ? maxCashState : nextCash;
// nextCash = nextCash < minCashState ? minCashState : nextCash;
// nextInventory = nextInventory > maxInventoryState ? maxInventoryState : nextInventory;
// nextInventory = nextInventory < minInventoryState ? minInventoryState : nextInventory;
// return new CashState(state.getPeriod() + 1, nextInventory, nextCash);
// };
// 
// 
// int minInventorys = 0;
// int maxInventorys = 50; // for drawing pictures
// int xLength = maxInventorys - minInventorys + 1;
// int index = 0;
// CashRecursion recursion2 = new CashRecursion(OptDirection.MAX, pmf, getFeasibleAction, stateTransition2,
// immediateValue2, discountFactor);
// double[][] yG2 = new double[xLength][2];
// index = 0;
// for (int initialInventory = minInventorys; initialInventory <= maxInventorys; initialInventory++) {
// yG2[index][0] = initialInventory;
// yG2[index][1] = -recursion2.getExpectedValue(new CashState(period, initialInventory, iniCash));
// index++;
// }
// 
// int capacity = (int) Math.max(0, (iniCash - overheadCost - fixOrderCost) / variCost);
// Drawing drawing = new Drawing();
// drawing.drawSimpleG(yG2, iniCash, "K transfered in cash GB"); // GB
// System.out.println();
// System.out.println("CK convex of GB:");
// CheckKConvexity.checkCK(yG2, fixOrderCost, capacity); // check the CK convex of GB
// System.out.println();
// 
}
Also used : IntStream(java.util.stream.IntStream) ImmediateValueFunction(sdp.inventory.ImmediateValue.ImmediateValueFunction) FindCCrieria(cash.strongconstraint.FindsCS.FindCCrieria) CashSimulation(sdp.cash.CashSimulation) Arrays(java.util.Arrays) DiscreteDistribution(umontreal.ssj.probdist.DiscreteDistribution) WriteToCsv(sdp.write.WriteToCsv) CashRecursion(sdp.cash.CashRecursion) OptDirection(sdp.cash.CashRecursion.OptDirection) MipCashConstraint(milp.MipCashConstraint) CashState(sdp.cash.CashState) 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) CheckKConvexity(sdp.inventory.CheckKConvexity) TreeMap(java.util.TreeMap) Map(java.util.Map) State(sdp.inventory.State) PoissonDist(umontreal.ssj.probdist.PoissonDist) Drawing(sdp.inventory.Drawing) Distribution(umontreal.ssj.probdist.Distribution) CashSimulation(sdp.cash.CashSimulation) PoissonDist(umontreal.ssj.probdist.PoissonDist) MipCashConstraint(milp.MipCashConstraint) FindCCrieria(cash.strongconstraint.FindsCS.FindCCrieria) CashRecursion(sdp.cash.CashRecursion) DiscreteDistribution(umontreal.ssj.probdist.DiscreteDistribution) Distribution(umontreal.ssj.probdist.Distribution) CashState(sdp.cash.CashState) GetPmf(sdp.inventory.GetPmf)

Example 2 with MipCashConstraint

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

the class MIPTesting method main.

public static void main(String[] args) {
    String headString = "K, v, h, I0, price, salvageValue, B0, DemandPatt, Time(sec), simMIPValue";
    WriteToCsv.writeToFile("./" + "testMIP_results.csv", headString);
    double[][] iniMeanDemands = { { 15, 15, 15, 15, 15, 15, 15, 15 }, { 21.15, 18.9, 17.7, 16.5, 15.15, 13.95, 12.75, 11.55 }, { 6.6, 9.3, 11.1, 12.9, 16.8, 21.6, 24, 26.4 }, { 9, 13, 20, 16, 10, 16, 22, 15 }, { 22, 18, 11, 16, 22, 12, 14, 21 }, { 41.8, 6.6, 2, 21.8, 44.8, 9.6, 2.6, 17 }, { 4.08, 12.16, 37.36, 21.44, 39.12, 35.68, 19.84, 22.48 }, { 4.7, 8.1, 23.6, 39.4, 16.4, 28.7, 50.8, 39.1 }, { 4.4, 11.6, 26.4, 14.4, 14.6, 19.8, 7.4, 18.3 }, { 4.9, 18.8, 6.4, 27.9, 45.3, 22.4, 22.3, 51.7 } };
    double[] K = { 10, 20 };
    double[] v = { 1, 3 };
    // ini cash can order 5 or 10 items
    double[] B0 = { 5, 10 };
    double[] p = { 4, 8 };
    double[] h = { 1, 3 };
    double salvageValue = 0.5;
    // generally 1 for the cash constrained problem
    double discountFactor = 1;
    // minimum cash balance the retailer can withstand
    double minCashRequired = 0;
    // maximum ordering quantity when having enough cash
    double maxOrderQuantity = 200;
    double minInventoryState = 0;
    double maxInventoryState = 500;
    // can affect results, should be smaller than minus fixedOrderCost
    double minCashState = -100;
    double maxCashState = 2000;
    double overheadCost = 0;
    /**
     *****************************************************************
     * set demands length, for testing
     */
    int newLength = 8;
    double[][] meanDemands = new double[iniMeanDemands.length][newLength];
    for (int i = 0; i < iniMeanDemands.length; i++) for (int j = 0; j < newLength; j++) {
        meanDemands[i][j] = iniMeanDemands[i][j];
    }
    for (int idemand = 0; idemand < 10; idemand++) for (int iK = 0; iK < K.length; iK++) for (int iv = 0; iv < v.length; iv++) for (int ip = 0; ip < p.length; ip++) for (int ih = 0; ih < h.length; ih++) for (int iB = 0; iB < B0.length; iB++) {
        double[] meanDemand = meanDemands[idemand];
        double fixOrderCost = K[iK];
        double variCost = v[iv];
        double price = p[ip];
        double iniCash = fixOrderCost + variCost * B0[iB];
        double holdingCost = h[ih];
        double iniInventory = 0;
        // 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
        i -> new PoissonDist(meanDemand[i])).toArray(PoissonDist[]::new);
        // immediate value
        ImmediateValueFunction<CashState, Double, Double, Double> immediateValue = (state, action, randomDemand) -> {
            double revenue = price * Math.min(state.getIniInventory() + action, randomDemand);
            double fixedCost = action > 0 ? fixOrderCost : 0;
            double variableCost = variCost * action;
            double inventoryLevel = state.getIniInventory() + action - randomDemand;
            double holdCosts = holdingCost * Math.max(inventoryLevel, 0);
            double cashIncrement = revenue - fixedCost - variableCost - holdCosts;
            double salValue = state.getPeriod() == T ? salvageValue * 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 revenue = price * Math.min(state.getIniInventory() + action, randomDemand);
            double fixedCost = action > 0 ? fixOrderCost : 0;
            double variableCost = variCost * action;
            double holdCosts = holdingCost * Math.max(nextInventory, 0);
            double nextCash = state.getIniCash() + revenue - fixedCost - variableCost - holdCosts;
            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
            nextCash = Math.round(nextCash * 1) / 1;
            return new CashState(state.getPeriod() + 1, nextInventory, nextCash);
        };
        /**
         *****************************************************************
         * Find (s, C, S) by MIP and simulate
         */
        Map<State, Double> cacheC1Values = new TreeMap<>();
        long currTime = System.currentTimeMillis();
        MipCashConstraint mipHeuristic = new MipCashConstraint(iniInventory, iniCash, fixOrderCost, variCost, holdingCost, price, salvageValue, distributions, overheadCost);
        int period = 1;
        int sampleNum = 10000;
        CashState initialState = new CashState(period, iniInventory, iniCash);
        double[][] sCS = mipHeuristic.findsCS();
        double time = (System.currentTimeMillis() - currTime) / 1000;
        System.out.println("running time is " + time + "s");
        CashSimulation simuation = new CashSimulation(distributions, sampleNum, immediateValue, stateTransition, discountFactor);
        cacheC1Values = mipHeuristic.cacheC1Values;
        double simsCSMIPValue = simuation.simulatesCS(initialState, sCS, cacheC1Values, minCashRequired, maxOrderQuantity, fixOrderCost, variCost);
        String out = fixOrderCost + ",\t" + variCost + ",\t" + holdingCost + ",\t" + iniInventory + ",\t" + price + ",\t" + salvageValue + ",\t" + iniCash + ",\t" + (idemand + 1) + ",\t" + time + ",\t" + simsCSMIPValue;
        WriteToCsv.writeToFile("./" + "testMIP_results.csv", out);
    }
}
Also used : CashSimulation(sdp.cash.CashSimulation) PoissonDist(umontreal.ssj.probdist.PoissonDist) StateTransitionFunction(sdp.inventory.StateTransition.StateTransitionFunction) MipCashConstraint(milp.MipCashConstraint) MipCashConstraint(milp.MipCashConstraint) CashState(sdp.cash.CashState) TreeMap(java.util.TreeMap) Map(java.util.Map) ImmediateValueFunction(sdp.inventory.ImmediateValue.ImmediateValueFunction)

Example 3 with MipCashConstraint

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

the class CashConstraintTest method main.

// d=[10, 10, 10, 10], coe = 10, iniCash=20, K=0; price=1.3, v=1; h = 0, salvageValue = 0.5, interestRate = 0.1
public static void main(String[] args) {
    double[] meanDemand = { 20, 7, 2, 14 };
    double iniInventory = 0;
    double iniCash = 33;
    double fixOrderCost = 24;
    double variCost = 1;
    double holdingCost = 0;
    double price = 4;
    double salvageValue = 0;
    double interestRate = 0;
    FindCCrieria criteria = FindCCrieria.XRELATE;
    // minimum cash balance the retailer can withstand
    double minCashRequired = 0;
    // maximum ordering quantity when having enough cash
    double maxOrderQuantity = 200;
    double truncationQuantile = 0.9999;
    // ordering quantity stepsize
    double stepSize = 1;
    double minInventoryState = 0;
    double maxInventoryState = 500;
    // can affect results, should be smaller than minus fixedOrderCost
    double minCashState = -100;
    double maxCashState = 2000;
    double discountFactor = 1;
    // 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])).toArray(Distribution[]::new);
    // double[] values1 = {6, 7};
    // double[] probs1 = {0.95, 0.05};
    // double[] values2 = {6, 7};
    // double[] probs2 = {0.95, 0.05};
    // DiscreteDistribution[] distributions = new DiscreteDistribution[T];
    // for (int i = 0; i < T; i++) {
    // if (i % 2 == 0)
    // distributions[i] = new DiscreteDistribution(values1, probs1, values1.length);
    // else
    // distributions[i] = new DiscreteDistribution(values2, probs2, values2.length);
    // }
    double[][][] pmf = new GetPmf(distributions, truncationQuantile, stepSize).getpmf();
    // feasible actions
    Function<CashState, double[]> getFeasibleAction = s -> {
        double maxQ = (int) Math.min(maxOrderQuantity, Math.max(0, (s.getIniCash() - minCashRequired - fixOrderCost) / variCost));
        return DoubleStream.iterate(0, i -> i + stepSize).limit((int) maxQ + 1).toArray();
    };
    // immediate value
    ImmediateValueFunction<CashState, Double, Double, Double> immediateValue = (state, action, randomDemand) -> {
        double revenue = price * Math.min(state.getIniInventory() + action, randomDemand);
        double fixedCost = action > 0 ? fixOrderCost : 0;
        double variableCost = variCost * action;
        double inventoryLevel = state.getIniInventory() + action - randomDemand;
        double holdCosts = holdingCost * Math.max(inventoryLevel, 0);
        double interests = interestRate * (state.getIniCash() - action * variCost);
        double cashIncrement = revenue - fixedCost - variableCost - holdCosts + interests;
        double salValue = state.getPeriod() == T ? salvageValue * 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, inventory is integer or not
        nextCash = Math.round(nextCash * 0.1) / 0.1;
        nextInventory = Math.round(nextInventory * 0.1) / 0.1;
        return new CashState(state.getPeriod() + 1, nextInventory, nextCash);
    };
    /**
     *****************************************************************
     * Solve
     */
    CashRecursion recursion = new CashRecursion(OptDirection.MAX, pmf, getFeasibleAction, stateTransition, immediateValue, discountFactor);
    int period = 1;
    CashState initialState = new CashState(period, iniInventory, iniCash);
    long currTime = System.currentTimeMillis();
    recursion.setTreeMapCacheAction();
    double finalValue = iniCash + recursion.getExpectedValue(initialState);
    System.out.println("final optimal cash 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 sdp results
     */
    int sampleNum = 10000;
    CashSimulation simuation = new CashSimulation(distributions, sampleNum, recursion, discountFactor);
    double simFinalValue = simuation.simulateSDPGivenSamplNum(initialState);
    double error = 0.0001;
    double confidence = 0.95;
    simuation.simulateSDPwithErrorConfidence(initialState, error, confidence);
    /**
     *****************************************************************
     * Find (s, C, S) by SDP and simulate
     */
    System.out.println("");
    double[][] optTable = recursion.getOptTable();
    FindsCS findsCS = new FindsCS(iniCash, distributions, fixOrderCost, price, variCost, holdingCost, salvageValue);
    double[][] optsCS = findsCS.getsCS(optTable, minCashRequired, criteria);
    Map<State, Double> cacheC1Values = new TreeMap<>();
    // Map<State, Double> cacheC2Values = new TreeMap<>();
    cacheC1Values = findsCS.cacheC1Values;
    // cacheC2Values = findsCS.cacheC2Values;
    double simsCSFinalValue = simuation.simulatesCS(initialState, optsCS, cacheC1Values, minCashRequired, maxOrderQuantity, fixOrderCost, variCost);
    double gap1 = (finalValue - simsCSFinalValue) / finalValue;
    double gap2 = (simFinalValue - simsCSFinalValue) / simFinalValue;
    System.out.printf("Optimality gap is: %.2f%% or %.2f%%\n", gap1 * 100, gap2 * 100);
    /**
     *****************************************************************
     * Check (s, C, S) policy,
     * sometimes not always hold, because in certain period
     * for some state C is 12, and 13 in other state,
     * we use heuristic step by choosing maximum one
     */
    findsCS.checksCS(optsCS, optTable, minCashRequired, maxOrderQuantity, fixOrderCost, variCost);
    System.out.printf("\n*******************************************************************\n");
    /**
     *****************************************************************
     * Find (s, C, S) by MIP and simulate
     */
    MipCashConstraint mipHeuristic = new MipCashConstraint(iniInventory, iniCash, fixOrderCost, variCost, holdingCost, price, salvageValue, distributions);
    double[][] sCS = mipHeuristic.findsCS();
    cacheC1Values = mipHeuristic.cacheC1Values;
    double simsCSMIPValue = simuation.simulatesCS(initialState, sCS, cacheC1Values, minCashRequired, maxOrderQuantity, fixOrderCost, variCost);
    gap1 = (finalValue - simsCSMIPValue) / finalValue;
    gap2 = (simFinalValue - simsCSMIPValue) / simFinalValue;
    System.out.printf("Optimality gap is: %.2f%% or %.2f%%\n", gap1 * 100, gap2 * 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 CashState(period, initialInventory, iniCash));
// index++;
// }
// int capacity = (int) Math.max(0, (iniCash - minCashRequired - fixOrderCost) / variCost);
// CheckKConvexity.checkCK(yG, fixOrderCost, capacity);
}
Also used : IntStream(java.util.stream.IntStream) ImmediateValueFunction(sdp.inventory.ImmediateValue.ImmediateValueFunction) FindCCrieria(cash.strongconstraint.FindsCS.FindCCrieria) CashSimulation(sdp.cash.CashSimulation) Arrays(java.util.Arrays) CashRecursion(sdp.cash.CashRecursion) OptDirection(sdp.cash.CashRecursion.OptDirection) MipCashConstraint(milp.MipCashConstraint) CashState(sdp.cash.CashState) Function(java.util.function.Function) StateTransitionFunction(sdp.inventory.StateTransition.StateTransitionFunction) DoubleStream(java.util.stream.DoubleStream) GetPmf(sdp.inventory.GetPmf) TreeMap(java.util.TreeMap) Map(java.util.Map) State(sdp.inventory.State) PoissonDist(umontreal.ssj.probdist.PoissonDist) Distribution(umontreal.ssj.probdist.Distribution) CashSimulation(sdp.cash.CashSimulation) PoissonDist(umontreal.ssj.probdist.PoissonDist) TreeMap(java.util.TreeMap) MipCashConstraint(milp.MipCashConstraint) MipCashConstraint(milp.MipCashConstraint) FindCCrieria(cash.strongconstraint.FindsCS.FindCCrieria) CashRecursion(sdp.cash.CashRecursion) CashState(sdp.cash.CashState) State(sdp.inventory.State) Distribution(umontreal.ssj.probdist.Distribution) CashState(sdp.cash.CashState) GetPmf(sdp.inventory.GetPmf)

Example 4 with MipCashConstraint

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

the class CashConstraintTesting method main.

// average computation time for 10 periods is 500s, 9 periods is 150s, or 305s,
// or 400s
public static void main(String[] args) {
    String headString = "K, v, h, I0, price, salvageValue, B0, DemandPatt, OptValue, Time(sec), simValue, " + "totalStates, " + "simsC1C2SValue, gap1, gap2, " + "simsC1SValue, gap1, gap2, " + "simsMeanCSValue, gap1, gap2, " + "firstQ, capacity, mipValue, gap11, gap22, time2";
    WriteToCsv.writeToFile("./" + "test_results.csv", headString);
    double[][] iniMeanDemands = { { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 }, { 21.15, 18.9, 17.7, 16.5, 15.15, 13.95, 12.75, 11.55, 10.35, 9.15 }, { 6.6, 9.3, 11.1, 12.9, 16.8, 21.6, 24, 26.4, 31.5, 33.9 }, { 12.1, 10, 7.9, 7, 7.9, 10, 12.1, 13, 12.1, 10 }, { 15.7, 10, 4.3, 2, 4.3, 10, 15.7, 18, 15.7, 10 }, { 41.8, 6.6, 2, 21.8, 44.8, 9.6, 2.6, 17, 30, 35.4 }, { 4.08, 12.16, 37.36, 21.44, 39.12, 35.68, 19.84, 22.48, 29.04, 12.4 }, { 4.7, 8.1, 23.6, 39.4, 16.4, 28.7, 50.8, 39.1, 75.4, 69.4 }, { 4.4, 11.6, 26.4, 14.4, 14.6, 19.8, 7.4, 18.3, 20.4, 11.4 }, { 4.9, 18.8, 6.4, 27.9, 45.3, 22.4, 22.3, 51.7, 29.1, 54.7 } };
    double[] K = { 10, 15, 20 };
    double[] v = { 1 };
    // ini cash can order 4 or 6 items
    double[] B0 = { 3, 5, 7 };
    // margin is 4, 5, 6
    double[] p = { 5, 6, 7 };
    double[] h = { 0 };
    double penaltyCost = 0;
    double salvageValue = 0.5;
    FindCCrieria criteria = FindCCrieria.XRELATE;
    double truncationQuantile = 0.999;
    int stepSize = 1;
    // minimum cash balance the retailer can withstand
    double overheadCost = 0;
    // maximum ordering quantity when having enough cash
    double maxOrderQuantity = 150;
    double minInventoryState = 0;
    double maxInventoryState = 200;
    // can affect results, should be smaller than minus fixedOrderCost
    double minCashState = -100;
    double maxCashState = 1500;
    // generally 1 for the cash constrained problem
    double discountFactor = 1;
    /**
     *****************************************************************
     * set demands length, for testing
     */
    int newLength = iniMeanDemands[0].length;
    double[][] meanDemands = new double[iniMeanDemands.length][newLength];
    for (int i = 0; i < iniMeanDemands.length; i++) for (int j = 0; j < newLength; j++) {
        meanDemands[i][j] = iniMeanDemands[i][j];
    }
    for (int idemand = 0; idemand < iniMeanDemands.length; idemand++) for (int iK = 0; iK < K.length; iK++) for (int iv = 0; iv < v.length; iv++) for (int ip = 0; ip < p.length; ip++) for (int ih = 0; ih < h.length; ih++) for (int iB = 0; iB < B0.length; iB++) {
        double[] meanDemand = meanDemands[idemand];
        double fixOrderCost = K[iK];
        double variCost = v[iv];
        double price = p[ip];
        double iniCash = fixOrderCost + overheadCost + variCost * B0[iB];
        double holdingCost = h[ih];
        double iniInventory = 0;
        // 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])).toArray(Distribution[]::new);
        double[][][] pmf = new GetPmf(distributions, truncationQuantile, stepSize).getpmf();
        // feasible actions
        Function<CashState, double[]> getFeasibleAction = s -> {
            double maxQ = (int) Math.min(maxOrderQuantity, Math.max(0, (s.getIniCash() - overheadCost - fixOrderCost) / variCost));
            return DoubleStream.iterate(0, i -> i + stepSize).limit((int) maxQ + 1).toArray();
        };
        // immediate value
        ImmediateValueFunction<CashState, Double, Double, Double> immediateValue = (state, action, randomDemand) -> {
            double revenue = price * Math.min(state.getIniInventory() + action, randomDemand);
            double fixedCost = action > 0 ? fixOrderCost : 0;
            double variableCost = variCost * action;
            double inventoryLevel = state.getIniInventory() + action - randomDemand;
            double holdCosts = holdingCost * Math.max(inventoryLevel, 0);
            double cashIncrement = revenue - fixedCost - variableCost - holdCosts - overheadCost;
            double salValue = state.getPeriod() == T ? salvageValue * Math.max(inventoryLevel, 0) : 0;
            cashIncrement += salValue;
            double endCash = state.getIniCash() + cashIncrement;
            if (endCash < 0) {
                cashIncrement += penaltyCost * endCash;
            }
            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
            nextCash = Math.round(nextCash * 1) / 1;
            return new CashState(state.getPeriod() + 1, nextInventory, nextCash);
        };
        /**
         *****************************************************************
         * Solve
         */
        CashRecursion recursion = new CashRecursion(OptDirection.MAX, pmf, getFeasibleAction, stateTransition, immediateValue, discountFactor);
        int period = 1;
        CashState initialState = new CashState(period, iniInventory, iniCash);
        long currTime = System.currentTimeMillis();
        recursion.setTreeMapCacheAction();
        double finalValue = recursion.getExpectedValue(initialState) + iniCash;
        System.out.println("final optimal expected cash is: " + finalValue);
        double firstQ = recursion.getAction(initialState);
        System.out.println("optimal order quantity in the first priod is : " + firstQ);
        double time = (System.currentTimeMillis() - currTime) / 1000.0;
        System.out.println("running time is " + time + "s");
        /**
         *****************************************************************
         * Simulating sdp results
         */
        int sampleNum = 100000;
        CashSimulation simuation = new CashSimulation(distributions, sampleNum, recursion, discountFactor);
        double simFinalValue = simuation.simulateSDPGivenSamplNum(initialState);
        /**
         *****************************************************************
         * Find (s, C1, C2, S) and simulate
         */
        System.out.println("");
        System.out.println("************************************************");
        double[][] optTable = recursion.getOptTable();
        FindsCS findsCS = new FindsCS(iniCash, distributions, fixOrderCost, price, variCost, holdingCost, salvageValue);
        double[][] optsCS = findsCS.getsC12S(optTable, overheadCost, criteria);
        Map<State, Double> cacheC1Values = new TreeMap<>();
        Map<State, Double> cacheC2Values = new TreeMap<>();
        cacheC1Values = findsCS.cacheC1Values;
        cacheC2Values = findsCS.cacheC2Values;
        double simsC1C2SFinalValue = simuation.simulatesCS(initialState, optsCS, cacheC1Values, cacheC2Values, overheadCost, maxOrderQuantity, fixOrderCost, variCost);
        double gapsC1C2S1 = (finalValue - simsC1C2SFinalValue) / finalValue;
        double gapsC1C2S2 = (simFinalValue - simsC1C2SFinalValue) / simFinalValue;
        System.out.printf("Optimality gap for (s, C1, C2, S) is: %.2f%% or %.2f%%\n", gapsC1C2S1 * 100, gapsC1C2S2 * 100);
        /**
         *****************************************************************
         * Find (s, C1, S) and simulate
         */
        System.out.println("");
        System.out.println("************************************************");
        optsCS = findsCS.getsCS(optTable, overheadCost, criteria);
        cacheC1Values = findsCS.cacheC1Values;
        double simsC1SFinalValue = simuation.simulatesCS(initialState, optsCS, cacheC1Values, overheadCost, maxOrderQuantity, fixOrderCost, variCost);
        double gapsC1S1 = (finalValue - simsC1SFinalValue) / finalValue;
        double gapsC1S2 = (simFinalValue - simsC1SFinalValue) / simFinalValue;
        System.out.printf("Optimality gap for (s, C1, S) is: %.2f%% or %.2f%%\n", gapsC1S1 * 100, gapsC1S2 * 100);
        double[][] numFrequency = findsCS.getMaxSFrequency(optTable, overheadCost, criteria);
        // System.out.println("most frequent S in each period");
        // System.out.println(Arrays.deepToString(numFrequency));
        /**
         *****************************************************************
         * Find (s, meanC, S) by SDP and simulate
         */
        System.out.println("");
        System.out.println("************************************************");
        optsCS = findsCS.getsCS(optTable, overheadCost, FindCCrieria.AVG);
        double simsMeanCSFinalValue = simuation.simulatesMeanCS(initialState, optsCS, overheadCost, maxOrderQuantity, fixOrderCost, variCost);
        double gapsMeanCS1 = (finalValue - simsMeanCSFinalValue) / finalValue;
        double gapsMeanCS2 = (simFinalValue - simsMeanCSFinalValue) / simFinalValue;
        System.out.printf("Optimality gap for (s, meanC, S) is: %.2f%% or %.2f%%\n", gapsMeanCS1 * 100, gapsMeanCS2 * 100);
        // /*******************************************************************
        // * Check (s, C, S) policy, sometimes not always hold
        // */
        // int nonOptCount = findsCS.checksCS(optsCS, optTable, overheadCost, maxOrderQuantity,
        // fixOrderCost, variCost);
        /**
         *****************************************************************
         * Find (s, C, S) by MIP and simulate
         */
        double simsCSMIPValue = 0;
        double gap11 = 0;
        double gap22 = 0;
        double time2 = 0;
        currTime = System.currentTimeMillis();
        MipCashConstraint mipHeuristic = new MipCashConstraint(iniInventory, iniCash, fixOrderCost, variCost, holdingCost, price, salvageValue, distributions, overheadCost);
        double[][] sCS = mipHeuristic.findsCSPieceWise();
        time2 = (System.currentTimeMillis() - currTime) / 1000.0;
        System.out.println("running time is " + time2 + "s");
        cacheC1Values = mipHeuristic.cacheC1Values;
        simsCSMIPValue = simuation.simulatesCS(initialState, sCS, cacheC1Values, overheadCost, maxOrderQuantity, fixOrderCost, variCost);
        gap11 = (finalValue - simsCSMIPValue) / finalValue;
        gap22 = (simFinalValue - simsCSMIPValue) / simFinalValue;
        System.out.printf("Optimality gap by Mip is: %.2f%% or %.2f%%\n", gap11 * 100, gap22 * 100);
        System.out.printf("\n*******************************************************************\n");
        // 
        String convexity = "";
        // double[][] yG = new double[xLength][2];
        // index = 0;
        // for (int initialInventory = minInventorys; initialInventory <= maxInventorys; initialInventory++) {
        // yG[index][0] = initialInventory;
        // yG[index][1] = -recursion2
        // .getExpectedValue(new CashState(period, initialInventory, iniCash));
        // index++;
        // }
        // convexity = CheckKConvexity.checkCK(yG3, fixOrderCost, capacity);
        // System.out.printf(
        // "\n*******************************************************************\n");
        long totalStates = optTable.length;
        String out = fixOrderCost + ",\t" + variCost + ",\t" + holdingCost + ",\t" + iniInventory + ",\t" + price + ",\t" + salvageValue + ",\t" + iniCash + ",\t" + (idemand + 1) + ",\t" + finalValue + ",\t" + time + ",\t" + simFinalValue + ",\t" + totalStates + ",\t" + simsC1C2SFinalValue + ",\t" + gapsC1C2S1 + ",\t" + gapsC1C2S2 + ",\t" + simsC1SFinalValue + ",\t" + gapsC1S1 + ",\t" + gapsC1S2 + ",\t" + simsMeanCSFinalValue + ",\t" + gapsMeanCS1 + ",\t" + gapsMeanCS2 + ",\t" + firstQ + ",\t" + B0[iB] + ",\t" + simsCSMIPValue + ",\t" + gap11 + ",\t" + gap22 + ",\t" + time2;
        WriteToCsv.writeToFile("./" + "test_results.csv", out);
    }
}
Also used : CashSimulation(sdp.cash.CashSimulation) PoissonDist(umontreal.ssj.probdist.PoissonDist) StateTransitionFunction(sdp.inventory.StateTransition.StateTransitionFunction) MipCashConstraint(milp.MipCashConstraint) MipCashConstraint(milp.MipCashConstraint) FindCCrieria(cash.strongconstraint.FindsCS.FindCCrieria) ImmediateValueFunction(sdp.inventory.ImmediateValue.ImmediateValueFunction) Function(java.util.function.Function) StateTransitionFunction(sdp.inventory.StateTransition.StateTransitionFunction) CashRecursion(sdp.cash.CashRecursion) Distribution(umontreal.ssj.probdist.Distribution) CashState(sdp.cash.CashState) TreeMap(java.util.TreeMap) Map(java.util.Map) GetPmf(sdp.inventory.GetPmf) ImmediateValueFunction(sdp.inventory.ImmediateValue.ImmediateValueFunction)

Aggregations

Map (java.util.Map)4 TreeMap (java.util.TreeMap)4 MipCashConstraint (milp.MipCashConstraint)4 CashSimulation (sdp.cash.CashSimulation)4 CashState (sdp.cash.CashState)4 ImmediateValueFunction (sdp.inventory.ImmediateValue.ImmediateValueFunction)4 StateTransitionFunction (sdp.inventory.StateTransition.StateTransitionFunction)4 PoissonDist (umontreal.ssj.probdist.PoissonDist)4 FindCCrieria (cash.strongconstraint.FindsCS.FindCCrieria)3 Function (java.util.function.Function)3 CashRecursion (sdp.cash.CashRecursion)3 GetPmf (sdp.inventory.GetPmf)3 Distribution (umontreal.ssj.probdist.Distribution)3 Arrays (java.util.Arrays)2 DoubleStream (java.util.stream.DoubleStream)2 IntStream (java.util.stream.IntStream)2 OptDirection (sdp.cash.CashRecursion.OptDirection)2 State (sdp.inventory.State)2 ArrayList (java.util.ArrayList)1 CheckKConvexity (sdp.inventory.CheckKConvexity)1