Hone logo
Hone
Problems

Implementing a Dynamic Cost Model for Resource Allocation

Many businesses need to model costs associated with resource usage. This challenge asks you to implement a flexible cost model in Python that can handle various resource types, usage metrics, and pricing structures. A well-designed cost model is crucial for accurate budgeting, pricing strategies, and resource optimization.

Problem Description

You are tasked with creating a CostModel class in Python. This class should allow users to define different resource types, associate them with specific usage metrics (e.g., CPU hours, data transfer, storage GB), and assign pricing rules to each resource. The model should then be able to calculate the total cost for a given set of resource usage data.

Key Requirements:

  • Resource Definition: The CostModel should allow adding resources with a name, a usage metric (string), and a pricing rule (a function).
  • Pricing Rules: Pricing rules are functions that take the usage amount (a number) as input and return the cost for that usage. These functions can be simple (e.g., a fixed price per unit) or more complex (e.g., tiered pricing).
  • Cost Calculation: The CostModel should have a method to calculate the total cost given a dictionary where keys are resource names and values are the usage amounts.
  • Flexibility: The design should be extensible to accommodate new resource types and pricing models easily.

Expected Behavior:

The CostModel class should be instantiated without arguments. It should provide methods to:

  • add_resource(self, resource_name, usage_metric, pricing_rule): Adds a new resource to the model.
  • calculate_cost(self, usage_data): Calculates the total cost based on the provided usage data.

Edge Cases to Consider:

  • Resource names in usage_data that are not defined in the CostModel. These should be ignored, and a warning message should be printed to the console.
  • Usage amounts that are negative. These should be treated as zero.
  • Empty usage_data. The total cost should be zero.
  • Pricing rules that raise exceptions (handle gracefully, potentially returning 0 cost for that resource).

Examples

Example 1:

Input:
cost_model = CostModel()
cost_model.add_resource("CPU", "hours", lambda x: 0.1 * x)
cost_model.add_resource("Storage", "GB", lambda x: 0.05 * x)
usage_data = {"CPU": 100, "Storage": 500, "Network": 20}
output = cost_model.calculate_cost(usage_data)
Output: 15.0
Explanation: CPU cost is 0.1 * 100 = 10.0, Storage cost is 0.05 * 500 = 25.0. Network is ignored. Total cost is 10.0 + 25.0 = 15.0

Example 2:

Input:
cost_model = CostModel()
cost_model.add_resource("Bandwidth", "GB", lambda x: 0.02 * x if x <= 1000 else 0.01 * x)
usage_data = {"Bandwidth": 1500}
output = cost_model.calculate_cost(usage_data)
Output: 30.0
Explanation: Bandwidth usage is 1500 GB. The first 1000 GB cost 0.02 * 1000 = 20.0. The remaining 500 GB cost 0.01 * 500 = 5.0. Total cost is 20.0 + 5.0 = 25.0

Example 3: (Edge Case)

Input:
cost_model = CostModel()
cost_model.add_resource("Memory", "GB", lambda x: 0.01 * x)
usage_data = {"Memory": -10, "Disk": 200}
output = cost_model.calculate_cost(usage_data)
Output: 0.0
Explanation: Memory usage is -10, which is treated as 0. Disk is ignored. Total cost is 0.0.

Constraints

  • The pricing_rule function must accept a single numerical argument (the usage amount) and return a numerical cost.
  • Resource names must be strings.
  • Usage amounts must be numbers (int or float).
  • The calculate_cost method should return a float representing the total cost.
  • The code should be well-documented and easy to understand.

Notes

  • Consider using a dictionary to store the resources and their pricing rules.
  • Error handling is important. Gracefully handle cases where a resource is not found or the pricing rule raises an exception.
  • Think about how to make the CostModel extensible to support more complex pricing models in the future (e.g., tiered pricing, volume discounts).
  • The warning message for unknown resources should be printed to stderr (using sys.stderr.write). This is standard practice for warnings.
  • You don't need to implement input validation beyond what's specified in the edge cases.
Loading editor...
python