Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 复杂生产线未来货物数量的计算算法_Java_Algorithm_Simulation - Fatal编程技术网

Java 复杂生产线未来货物数量的计算算法

Java 复杂生产线未来货物数量的计算算法,java,algorithm,simulation,Java,Algorithm,Simulation,这是一篇很长的文章,但只有前半部分才真正相关 第二部分只描述了我试图解决的问题,但在我看来效率太低的问题(这可能有助于了解我想要什么)。相关部分以粗体问题后的一行结束 我试图在一个想象中的工厂里模拟多个产品,以计算出每种已知类型的商品在最后会有多少。有几种不同的商品类型,它们都有特定的最大生产能力,只有在有足够的原料可用的情况下才能达到。生产线的外观示例如下: 底部的货物都有一个已知的运送到工厂的速度,因此对于这些货物来说,没有什么可计算的,尽管这个速度会随着时间的推移而变化(同时,最大生产能

这是一篇很长的文章,但只有前半部分才真正相关 第二部分只描述了我试图解决的问题,但在我看来效率太低的问题(这可能有助于了解我想要什么)。相关部分以粗体问题后的一行结束

我试图在一个想象中的工厂里模拟多个产品,以计算出每种已知类型的商品在最后会有多少。有几种不同的商品类型,它们都有特定的最大生产能力,只有在有足够的原料可用的情况下才能达到。生产线的外观示例如下:

底部的货物都有一个已知的运送到工厂的速度,因此对于这些货物来说,没有什么可计算的,尽管这个速度会随着时间的推移而变化(同时,最大生产能力也会在任何时间点发生变化,例如,可以通过增加工人或更多机器来增加产能)

如图所示,对于其他商品,有三个方面需要考虑:

  • 有些生产线从一条生产线到另一条生产线再生产一条
  • 有些生产线从另外两条生产线中选出一条
  • 一些行有一个好的用于创建多个新的好 (例如,请参见插图中间的“R8”)
我有以下资料:

  • 每种商品的最大生产率(例如,每小时生产5台)
  • 对于最底层的货物,我们有交付到工厂的数量(例如,每小时交付5次)
  • 现在每个产品的库存量是多少(因此,如果交付的数量不够,如果我们还有一些库存,我们就不需要减少生产)
  • 货物交付的时间会发生变化(可能发生在底部的任何货物上)
  • 一种商品的最大生产率会在什么时候发生变化(可能发生在任何不在底部的商品上)
有了这些信息,我想计算未来某一特定时间每种商品的数量。我希望这是尽可能有效的,因为我需要这些计算经常

我试图用Java实现这个,但是我遇到了一些问题。我没有修复它们,而是再次查看了我的算法,发现它看起来并不是很有效,因此我想知道是否有人已经看到或解决了此类问题?


我试图解决这个问题的方法如下:

  • 当生产(或交付)量发生变化时,我使用已知信息为每种货物创建最大生产(和交付)间隔
  • 我将所有资源放在底部的
    剩余的
    集合和
    已检查的
    集合中(底部的商品立即被检查)
  • 我计算每种商品的实际生产量:因此,我将剩余的每种商品都计算出来,并检查可以生产哪些商品,如果所有可以生产的商品都是由检查过的商品制成的,我将根据最高税率和可用商品来计算实际生产量(取决于制造物品的产量和库存量(如果数量较少)。此外,在这一步中,如果源货物产量较少,我会增加生产间隔(但在开始时会有一些库存)生产量需要减少。当完成产品时,新产品将从剩余产品集中移除,并添加新产品,同时添加到已检查的产品集中
  • 现在我们有了每种商品的所有实际商品产量,我们可以进行计算。为此,我们对每种商品进行循环,取实际产量,并使用时间间隔边界将其相加。我们现在有了未来所需时间的商品数量
  • 附加信息:我们不能做第4点。没有第3点。因为我们计算的货物的实际数量可以在下一个货物的生产中再次消耗,所以我们需要在两者之间进行这一步

    如果这有助于理解我做了什么(或想做什么),我会添加代码(不工作).该类已使用当前生产的每种已生产货物的最大生产速率间隔初始化。由于其他货物可能有库存,对于所有未包含的货物,我们将其初始化为零生产和一个间隔

    public class FactoryGoods {
        
        private long future;
        private long now;
        private Map<String, Integer> availableGoods;
        private Map<String, ArrayList<ProductionInterval>> hourlyGoodIncrease;
    
        /**
         * 
         * @param future long current time
         * @param now long last time the factory's resources got updates
         * @param availableGoods Map<String,Integer> of the goods in the factory
         * @param hourlyGoodIncrease Map<String,ArrayList<ProductionInterval>> of the intervals of production quantities for the goods
         */
        public factoryGoods(long future, long now, Map<String,Integer> availableGoods, Map<String,ArrayList<ProductionInterval>> hourlyGoodIncrease) {
            this.future = future;
            this.now = now;
            this.availableGoods = availableGoods;
            this.hourlyGoodIncrease = hourlyGoodIncrease;
        }
        
        /**
         * Calculates the resources present in a factory's storage
         * @return a Map of quantities mapped on the String name of the good
         */
        public Map<String,Integer> getResources() {
            // Make sure all goods to have all goods inside the loop, to work on goods,
            // that are produced, but also those which are only in store
            HashMap<String, Boolean> goodChecked = new HashMap<String,Boolean>();
            Set<String> remaining = new HashSet<String>();
            for (Goods good: Goods.values()) {
                String g = good.get();
                if (hourlyGoodIncrease.get(g) == null) {
                    ArrayList<ProductionInterval> prods = new ArrayList<ProductionInterval>();
                    ProductionInterval start = new ProductionInterval(now, 0);
                    prods.add(start);
                    hourlyGoodIncrease.put(g, prods);
                }
                if (availableGoods.get(g) == null) {
                    availableGoods.put(g, 0);
                }
                if (good.isPrimary()) {
                    goodChecked.put(g, true);
                } else {
                    goodChecked.put(g, false);
                }
                remaining.add(g);
            }
            
            // As long as goods are remaining to be checked loops over the goods, and
            // recalculates hourly good increases for goods, that have all its sources
            // already calculated
            while (remaining.size() > 0) {
                Set<String> removes = new HashSet<String>();
                
                for (String good: remaining) {
                    
                    if (goodChecked.get(good)) {
                        Good g = GoodFactory.get(good);
                        Set<String> to = new HashSet<String>();
                        Map<String,Float> from = new HashMap<String,Float>();
                        setUpFromAndToGoods(g, to, from, availableGoods);
                        if (areGoodsAlreadyCalculated(to, goodChecked)) {
                            //remaining.remove(good);
                            removes.add(good);
                        } else {
                            if (areGoodsReadyForCalculation(to, goodChecked)) {
                                // Get all resources we are working on now
                                Map<String,Float> fromDecrease = new HashMap<String,Float>();
                                for (String t: to) {
                                    for (String f: GoodFactory.get(t).isMadeFrom().keySet()) {
                                        from.put(f, (float) availableGoods.get(f));
                                    }
                                }
                                // Get all interval borders
                                ArrayList<Long> intervalBorders = new ArrayList<Long>();
                                for (String wGood: from.keySet()) {
                                    ArrayList<ProductionInterval> intervals = hourlyGoodIncrease.get(wGood);
                                    for (ProductionInterval interval: intervals) {
                                        long intervalStart = interval.getStartTime();
                                        if (!intervalBorders.contains(intervalStart)) {
                                            intervalBorders.add(intervalStart);
                                        }
                                    }
                                }
                                Collections.sort(intervalBorders);
                                intervalBorders.add(future);
                                for (String f: from.keySet()) {
                                    hourlyGoodIncrease.put(f, createNewProductionIntervalls(intervalBorders, hourlyGoodIncrease.get(f)));
                                }
                                // For all intervals
                                int iLast = intervalBorders.size() - 1;
                                for (int i = 0; i < iLast; i++) {
                                    long elapsedTime = intervalBorders.get(i + 1) - intervalBorders.get(i);
                                    for (String t: to) {
                                        Map<String, Float> source = GoodFactory.get(t).isMadeFrom();
                                        for (String s: source.keySet()) {
                                            Float decrease = fromDecrease.get(s);
                                            fromDecrease.put(s, (decrease != null ? decrease : 0) + source.get(s));
                                        }
                                    }
                                    // Calculate amount after normal maximum production
                                    Set<String> negatives = new HashSet<String>();
                                    Map<String,Float> nextFrom = new HashMap<String,Float>();
                                    for (String f: from.keySet()) {
                                        float delta = from.get(f) + (hourlyGoodIncrease.get(f).get(i).getHourlyIncrease() - fromDecrease.get(f)) * elapsedTime / (1000 * 60 * 60);
                                        nextFrom.put(f, delta);
                                        if (delta < 0) {
                                            negatives.add(f);
                                        }
                                    }
                                    // Check if got under zero
                                    if (negatives.size() == 0) {
                                        for (String f: from.keySet()) {
                                            float newIncrease = hourlyGoodIncrease.get(f).get(i).getHourlyIncrease() - fromDecrease.get(f);
                                            hourlyGoodIncrease.get(f).get(i).setHourlyIncrease(newIncrease);
                                            from.put(f, nextFrom.get(f));
                                        }
                                    } else {
                                        // TODO: handle case when more is used than exists
                                    }
                                    // Else calculate point where at least one from is zero and add an interval
                                    // before its maximum, after needs to be adjusted
                                }
                                
                                // Break to remove all calculated goods from the remaining set and rerun the loop
                                removes = to;
                                break;
                            }
                        }
                    }
                }
                for (String remove: removes) {
                    remaining.remove(remove);
                }
            }
            
            
            // Final calculation of the goods amounts that are available in the factory
            for (String good: goodChecked.keySet()) {
                ArrayList<ProductionInterval> intervals = hourlyGoodIncrease.get(good);
                intervals.add(new ProductionInterval(future, 0));
                float after = availableGoods.get(good);
                for (int i = 0; i < (intervals.size() - 1); i++) {
                    after += intervals.get(i).getHourlyIncrease() * (intervals.get(i + 1).getStartTime() - intervals.get(i).getStartTime()) / (1000 * 60 * 60);
                }
                availableGoods.put(good, (int) after);
            }
            
            return availableGoods;
        }
        
        private static ArrayList<ProductionInterval> createNewProductionIntervalls(ArrayList<Long> intervalBorders, ArrayList<ProductionInterval> hourlyIncreases) {
            System.out.print("intervalBorders\n");
            System.out.print(intervalBorders + "\n");
            
            System.out.print("hourlyIncreases\n");
            System.out.print(hourlyIncreases + "\n");
            
            ArrayList<ProductionInterval> intervalls = new ArrayList<ProductionInterval>();
            int i = 0;
            long iTime = 0;
            long nextTime = 0;
            for (long l: intervalBorders) {
                float increase = 0;
                iTime = hourlyIncreases.get(i).getStartTime();
                if (i + 1 < hourlyIncreases.size()) {
                    nextTime = hourlyIncreases.get(i + 1).getStartTime();
                }
                if (l == iTime) {
                    increase = hourlyIncreases.get(i).getHourlyIncrease();
                } else if (iTime < l && l < nextTime) {
                    increase = hourlyIncreases.get(i).getHourlyIncrease();
                } else if (l == nextTime) {
                    increase = hourlyIncreases.get(++i).getHourlyIncrease();
                }
                intervalls.add(new ProductionInterval(l, increase));
            }
            return intervalls;
        }
        
        private static void setUpFromAndToGoods(Good g, Set<String> to, Map<String,Float> from, Map<String,Integer> availableGoods) {
            Set<String> unchecked = g.isUsedToCreate();
            while (unchecked.size() > 0) {
                String good = unchecked.iterator().next();
                unchecked.remove(good);
                to.add(good);
                Set<String> madeFrom = GoodFactory.get(good).isMadeFrom().keySet();
                for (String fromGood: madeFrom) {
                    if (!from.containsKey(fromGood)) {
                        from.put(fromGood, (float) availableGoods.get(fromGood));
                        Set<String> additions = GoodFactory.get(fromGood).isUsedToCreate();
                        for (String addition: additions) {
                            if (!to.contains(addition) && !unchecked.contains(addition)) {
                                unchecked.add(addition);
                            }
                        }
                    }
                }
            }
        }
        
        private static boolean areGoodsReadyForCalculation(Set<String> toGoods, Map<String,Boolean> goodChecked) {
            for (String t: toGoods) {
                Good toGood = GoodFactory.get(t);
                for (String from: toGood.isMadeFrom().keySet()) {
                    if (!goodChecked.get(from)) {
                        return false;
                    }
                }
            }
            return true;
        }
        
        private static boolean areGoodsAlreadyCalculated(Set<String> toGoods, Map<String,Boolean> goodChecked) {
            for (String t: toGoods) {
                if (!goodChecked.get(t)) {
                    return false;
                }
            }
            return true;
        }
    
    }
    
    public class ProductionInterval {
        
        private long startTime;
        private float hourlyIncrease;
        
        public ProductionInterval(long startTime, float hourlyIncrease) {
            this.setStartTime(startTime);
            this.setHourlyIncrease(hourlyIncrease);
        }
    
        public float getHourlyIncrease() {
            return hourlyIncrease;
        }
    
        public void setHourlyIncrease(float hourlyIncrease) {
            this.hourlyIncrease = hourlyIncrease;
        }
    
        public long getStartTime() {
            return startTime;
        }
    
        public void setStartTime(long startTime) {
            this.startTime = startTime;
        }
        
        public String toString() {
            return "<starttime=" + this.startTime + ", hourlyIncrease=" + this.hourlyIncrease + ">";
        }
    
    }
    
    公共类工厂产品{
    私人长远发展;
    私人长现在;
    可获得的私有地图;
    私人地图小时增长;
    /**
    * 
    *@param未来长当前时间
    *@param现在是上次工厂资源更新的时候了
    *@param工厂内货物的可用goods地图
    *@param hourlygoodIngress商品生产数量间隔图
    */
    公共工厂商品(长期未来、长期现在、地图可用商品、地图小时增长){
    this.future=未来;
    this.now=现在;
    this.availableGoods=availableGoods;
    this.hourlyGoodIncrease=hourlyGoodIncrease;
    }
    /**
    *计算工厂存储中存在的资源
    *@返回货物字符串名称上映射的数量图
    */
    公共地图获取资源(){
    //确保所有货物都在回路中,以便处理货物,
    //这些都是生产出来的,但也有那些只在商店里
    HashMap goodChecked=新建HashMap();
    Set剩余=新的HashSet();
    对于(货物:good.values()){
    字符串g=good.get();
    if(hourlyGoodIncrease.get(g)==null){
    ArrayList prods=新的ArrayList();
    ProductionInterval开始=新ProductionInterval(现在为0);
    产品添加(开始);
    hourlyGoodIncrease.put(g,prods);
    
    #include <cassert>
    #include <iostream>
    #include <limits>
    #include <utility>
    #include <vector>
    
    // Identifies a type of good in some Factory.
    using Good = int;
    
    // Simulates a factory. The simulation is crude, assuming continuous,
    // fractional, zero-latency production. Nevertheless it may be accurate enough
    // for high production volumes over long periods of time.
    class Factory {
    public:
      // Declares a new raw material. `delivery_rate` is the amount of this good
      // delivered per hour.
      Good NewRawMaterial(double stock, double delivery_rate) {
        assert(stock >= 0.0);
        assert(delivery_rate >= 0.0);
        return NewGood(stock, delivery_rate, {});
      }
    
      // Declares a new manufactured good. `max_production_rate` is the max amount
      // of this good produced per hour. Producing one of this good consumes one
      // `input`.
      Good NewManufacturedGood(double stock, double max_production_rate,
                               Good input) {
        assert(stock >= 0.0);
        assert(max_production_rate >= 0.0);
        return NewGood(stock, max_production_rate, {input});
      }
    
      // Declares a new manufactured good. `max_production_rate` is the max amount
      // of this good produced per hour. Producing one of this good consumes one
      // `input_a` and one `input_b`.
      Good NewManufacturedGood(double stock, double max_production_rate,
                               Good input_a, Good input_b) {
        assert(stock >= 0.0);
        assert(max_production_rate >= 0.0);
        return NewGood(stock, max_production_rate, {input_a, input_b});
      }
    
      // Returns the number of hours since the start of the simulation.
      double Now() const { return current_time_; }
    
      // Advances the current time to `time` hours since the start of the
      // simulation.
      void AdvanceTo(double time);
    
      // Returns the amount of `good` in stock as of the current time.
      double Stock(Good good) const { return stock_[good]; }
    
      // Sets the delivery rate of `good` to `delivery_rate` as of the current time.
      void SetDeliveryRate(Good good, double delivery_rate) {
        assert(delivery_rate >= 0.0);
        max_production_rate_[good] = delivery_rate;
      }
    
      // Sets the max production rate of `good` to `max_production_rate` as of the
      // current time.
      void SetMaxProductionRate(Good good, double max_production_rate) {
        assert(max_production_rate >= 0.0);
        max_production_rate_[good] = max_production_rate;
      }
    
    private:
      // Floating-point tolerance.
      static constexpr double kEpsilon = 1e-06;
    
      // Declares a new good. We handle raw materials as goods with no inputs.
      Good NewGood(double stock, double max_production_rate,
                   std::vector<Good> inputs) {
        assert(stock >= 0.0);
        assert(max_production_rate >= 0.0);
        Good good = stock_.size();
        stock_.push_back(stock);
        max_production_rate_.push_back(max_production_rate);
        inputs_.push_back(std::move(inputs));
        return good;
      }
    
      // Returns the right-hand derivative of stock.
      std::vector<double> Derivative() const;
    
      // Returns the next time at which a good is newly out of stock, or positive
      // infinity if there is no such time.
      double NextStockOutTime(const std::vector<double> &derivative) const;
    
      // The current time, in hours since the start of the simulation.
      double current_time_ = 0.0;
    
      // `stock_[good]` is the amount of `good` in stock at the current time.
      std::vector<double> stock_;
    
      // `max_production_rate_[good]` is the max production rate of `good` at the
      // current time.
      std::vector<double> max_production_rate_;
    
      // `inputs_[good]` is the list of goods required to produce `good` (empty for
      // raw materials).
      std::vector<std::vector<Good>> inputs_;
    
      // Derivative of `stock_`.
      std::vector<double> stock_rate_;
    };
    
    void Factory::AdvanceTo(double time) {
      assert(time >= current_time_);
      bool caught_up = false;
      while (!caught_up) {
        auto derivative = Derivative();
        double next_time = NextStockOutTime(derivative);
        if (time <= next_time) {
          next_time = time;
          caught_up = true;
        }
        for (Good good = 0; good < stock_.size(); good++) {
          stock_[good] += (next_time - current_time_) * derivative[good];
        }
        current_time_ = next_time;
      }
    }
    
    std::vector<double> Factory::Derivative() const {
      // TODO: this code prioritizes limited supply by the order in which production
      // is declared. You probably want to use linear programming or something.
      std::vector<double> derivative = max_production_rate_;
      for (Good good = 0; good < stock_.size(); good++) {
        for (Good input : inputs_[good]) {
          if (stock_[input] <= kEpsilon) {
            derivative[good] = std::min(derivative[good], derivative[input]);
          }
        }
        for (Good input : inputs_[good]) {
          derivative[input] -= derivative[good];
        }
      }
      return derivative;
    }
    
    double Factory::NextStockOutTime(const std::vector<double> &derivative) const {
      double duration = std::numeric_limits<double>::infinity();
      for (Good good = 0; good < stock_.size(); good++) {
        if (stock_[good] > kEpsilon && derivative[good] < -kEpsilon) {
          duration = std::min(duration, stock_[good] / -derivative[good]);
        }
      }
      return current_time_ + duration;
    }
    
    int main() {
      Factory factory;
      Good r1 = factory.NewRawMaterial(60.0, 3.0);
      Good r2 = factory.NewRawMaterial(20.0, 1.0);
      Good r3 = factory.NewManufacturedGood(0.0, 2.0, r1);
      Good r4 = factory.NewManufacturedGood(0.0, 1.0, r1, r2);
      auto print_stocks = [&]() {
        std::cout << "t : " << factory.Now() << "\n";
        std::cout << "r1: " << factory.Stock(r1) << "\n";
        std::cout << "r2: " << factory.Stock(r2) << "\n";
        std::cout << "r3: " << factory.Stock(r3) << "\n";
        std::cout << "r4: " << factory.Stock(r4) << "\n";
        std::cout << "\n";
      };
      print_stocks();
      // Everything running smoothly
      factory.AdvanceTo(24.0);
      print_stocks();
      // Uh oh, r1 supply cut off. Stock out at 44 hours.
      factory.SetDeliveryRate(r1, 0.0);
      factory.AdvanceTo(48.0);
      print_stocks();
      // r1 supply at 50%. r3 production prioritized.
      factory.SetDeliveryRate(r1, 1.5);
      factory.AdvanceTo(72.0);
      print_stocks();
      // r1 oversupplied.
      factory.SetDeliveryRate(r1, 4.0);
      factory.AdvanceTo(96.0);
      print_stocks();
    }
    
    t : 0
    r1: 60
    r2: 20
    r3: 0
    r4: 0
    
    t : 24
    r1: 60
    r2: 20
    r3: 48
    r4: 24
    
    t : 48
    r1: 0
    r2: 24
    r3: 88
    r4: 44
    
    t : 72
    r1: 0
    r2: 48
    r3: 124
    r4: 44
    
    t : 96
    r1: 24
    r2: 48
    r3: 172
    r4: 68