DefaultUtilityOptimizer(CustomerStructure customerStructure, List<CapacityBundle> bundles) {
    this.customerStructure = customerStructure;
    this.capacityBundles = bundles;
    this.evaluatorMap = new HashMap<>();

    // create evaluation wrappers and tariff evaluators for each bundle
    for (CapacityBundle bundle : bundles) {
      TariffSubscriberStructure subStructure = bundle.getSubscriberStructure();
      TariffEvaluator evaluator =
          new TariffEvaluator(new TariffEvaluationWrapper(bundle))
              .withChunkSize(Math.max(1, bundle.getPopulation() / 1000))
              .withTariffSwitchFactor(subStructure.getTariffSwitchFactor())
              .withPreferredContractDuration(subStructure.getExpectedDuration())
              .withInconvenienceWeight(subStructure.getInconvenienceWeight())
              .withRationality(subStructure.getLogitChoiceRationality())
              .withEvaluateAllTariffs(true);
      evaluator.initializeCostFactors(
          subStructure.getExpMeanPriceWeight(),
          subStructure.getMaxValuePriceWeight(),
          subStructure.getRealizedPriceWeight(),
          subStructure.getTariffVolumeThreshold());
      evaluator.initializeInconvenienceFactors(
          subStructure.getTouFactor(),
          subStructure.getTieredRateFactor(),
          subStructure.getVariablePricingFactor(),
          subStructure.getInterruptibilityFactor());
      evaluatorMap.put(bundle, evaluator);
    }
  }