Class: WeightedListRank::Strategies::Exponential
- Inherits:
-
WeightedListRank::Strategy
- Object
- WeightedListRank::Strategy
- WeightedListRank::Strategies::Exponential
- Defined in:
- lib/weighted_list_rank/strategies/exponential.rb
Instance Attribute Summary collapse
-
#average_list_length ⇒ Object
readonly
Returns the value of attribute average_list_length.
-
#bonus_pool_percentage ⇒ Object
readonly
Returns the value of attribute bonus_pool_percentage.
-
#exponent ⇒ Object
readonly
Returns the value of attribute exponent.
-
#include_unranked_items ⇒ Object
readonly
Returns the value of attribute include_unranked_items.
Instance Method Summary collapse
-
#calculate_score(list, item) ⇒ Float
Calculates the score of an item within a list based on its rank position, the total number of items, and the list’s weight, using an exponential formula.
-
#initialize(exponent: 1.5, bonus_pool_percentage: 1.0, average_list_length: nil, include_unranked_items: false) ⇒ Exponential
constructor
Initializes the Exponential strategy with optional parameters for exponent, bonus pool percentage, average list length, and whether to include unranked items in the bonus pool.
Constructor Details
#initialize(exponent: 1.5, bonus_pool_percentage: 1.0, average_list_length: nil, include_unranked_items: false) ⇒ Exponential
Initializes the Exponential strategy with optional parameters for exponent, bonus pool percentage, average list length, and whether to include unranked items in the bonus pool.
defaults to 1.0 (100%). defaults to nil. defaults to false for backward compatibility.
16 17 18 19 20 21 |
# File 'lib/weighted_list_rank/strategies/exponential.rb', line 16 def initialize(exponent: 1.5, bonus_pool_percentage: 1.0, average_list_length: nil, include_unranked_items: false) @exponent = exponent @bonus_pool_percentage = bonus_pool_percentage @average_list_length = average_list_length @include_unranked_items = include_unranked_items end |
Instance Attribute Details
#average_list_length ⇒ Object (readonly)
Returns the value of attribute average_list_length.
4 5 6 |
# File 'lib/weighted_list_rank/strategies/exponential.rb', line 4 def average_list_length @average_list_length end |
#bonus_pool_percentage ⇒ Object (readonly)
Returns the value of attribute bonus_pool_percentage.
4 5 6 |
# File 'lib/weighted_list_rank/strategies/exponential.rb', line 4 def bonus_pool_percentage @bonus_pool_percentage end |
#exponent ⇒ Object (readonly)
Returns the value of attribute exponent.
4 5 6 |
# File 'lib/weighted_list_rank/strategies/exponential.rb', line 4 def exponent @exponent end |
#include_unranked_items ⇒ Object (readonly)
Returns the value of attribute include_unranked_items.
4 5 6 |
# File 'lib/weighted_list_rank/strategies/exponential.rb', line 4 def include_unranked_items @include_unranked_items end |
Instance Method Details
#calculate_score(list, item) ⇒ Float
Calculates the score of an item within a list based on its rank position, the total number of items, and the list’s weight, using an exponential formula. The bonus pool for score adjustments is determined by the specified bonus pool percentage of the list’s total weight, adjusted by the average list length.
If include_unranked_items
is true, unranked items will also receive a portion of the bonus pool. Ranked items will receive an exponential bonus, while unranked items will split the remaining bonus pool evenly.
and the bonus pool percentage.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/weighted_list_rank/strategies/exponential.rb', line 35 def calculate_score(list, item) # Default score to the list's weight score = list.weight # Total number of items in the list total_items = list.items.count # Separate ranked and unranked items ranked_items = list.items.select { |i| i.position } num_ranked_items = ranked_items.count if num_ranked_items > 0 && item.position.nil? # If there are ranked items, unranked items get no bonus, only the list's weight score = list.weight else # Calculate the total bonus pool total_bonus_pool = list.weight * bonus_pool_percentage # Adjust the bonus pool based on the average list length adjusted_bonus_pool = if average_list_length && average_list_length > 0 total_bonus_pool * (total_items / average_list_length.to_f) else total_bonus_pool end if item.position.nil? # Unranked items get no bonus if there are ranked items if include_unranked_items && num_ranked_items == 0 unranked_bonus = adjusted_bonus_pool / total_items score += unranked_bonus end else # Check if the item's position is higher than the total number of items if item.position > total_items puts "Warning: Item position (#{item.position}) is higher than the total number of items (#{total_items}) in the list. Using total items as position." item_position = total_items else item_position = item.position end # Ranked items receive a bonus calculated using the exponential formula exponential_factor = (total_items + 1 - item_position)**exponent total_exponential_factor = (1..total_items).sum { |pos| (total_items + 1 - pos)**exponent } # Allocate a portion of the adjusted bonus pool based on the item's exponential factor item_bonus = (exponential_factor / total_exponential_factor) * adjusted_bonus_pool score += item_bonus end end # Apply score penalty if it exists, for both ranked and unranked items score = apply_penalty(score, item.score_penalty) # Ensure the score is not less than 1 [score, 1].max end |