Make buyers part of model

Buyers are now part of the model, rather than being fixed. This means
that the model can choose from among all buyers and determine the most
profitable option.

Accomplishing this meant replacing the if-else control flow with a large
quantity of half-reified constraints.
This commit is contained in:
Jeremy Saklad 2021-06-13 17:37:39 -05:00
parent 52a509bd19
commit d571167742
Signed by: Jeremy Saklad
GPG Key ID: 9CA2149583EDBF84
1 changed files with 356 additions and 294 deletions

View File

@ -1172,12 +1172,23 @@ def Solve():
for embellishment in Embellishment: for embellishment in Embellishment:
actions[embellishment] = model.NewIntVar(0, cp_model.INT32_MAX, embellishment.value.name) actions[embellishment] = model.NewIntVar(0, cp_model.INT32_MAX, embellishment.value.name)
# Buyer
for buyer in Buyer:
actions[buyer] = model.NewBoolVar(buyer.value.name)
# One torso # One torso
model.Add(cp_model.LinearExpr.Sum([value for (key, value) in actions.items() if isinstance(key, Torso)]) == 1) model.Add(cp_model.LinearExpr.Sum([value for (key, value) in actions.items() if isinstance(key, Torso)]) == 1)
# One declaration # One declaration
model.Add(cp_model.LinearExpr.Sum([value for (key, value) in actions.items() if isinstance(key, Declaration)]) == 1) model.Add(cp_model.LinearExpr.Sum([value for (key, value) in actions.items() if isinstance(key, Declaration)]) == 1)
# One buyer
model.Add(cp_model.LinearExpr.Sum([value for (key, value) in actions.items() if isinstance(key, Buyer)]) == 1)
# Set buyer
if BUYER is not None:
model.Add(actions[BUYER] == 1)
# Value calculation # Value calculation
original_value = model.NewIntVar(0, cp_model.INT32_MAX, 'original value') original_value = model.NewIntVar(0, cp_model.INT32_MAX, 'original value')
model.Add(original_value == cp_model.LinearExpr.ScalProd(actions.values(), [action.value.value for action in actions.keys()])) model.Add(original_value == cp_model.LinearExpr.ScalProd(actions.values(), [action.value.value for action in actions.keys()]))
@ -1265,7 +1276,6 @@ def Solve():
# Profit intermediate variables # Profit intermediate variables
value_remainder = model.NewIntVar(0, cp_model.INT32_MAX, 'value remainder')
primary_revenue = model.NewIntVar(0, cp_model.INT32_MAX, 'primary revenue') primary_revenue = model.NewIntVar(0, cp_model.INT32_MAX, 'primary revenue')
secondary_revenue = model.NewIntVar(0, cp_model.INT32_MAX, 'secondary revenue') secondary_revenue = model.NewIntVar(0, cp_model.INT32_MAX, 'secondary revenue')
total_revenue = model.NewIntVar(0, cp_model.INT32_MAX*2, 'total revenue') total_revenue = model.NewIntVar(0, cp_model.INT32_MAX*2, 'total revenue')
@ -1537,309 +1547,361 @@ def Solve():
model.Add(cp_model.LinearExpr.ScalProd(actions.values(), [action.value.tails_needed for action in actions.keys()]) == 0).OnlyEnforceIf(actions[Appendage.SKIP_TAILS].Not()) model.Add(cp_model.LinearExpr.ScalProd(actions.values(), [action.value.tails_needed for action in actions.keys()]) == 0).OnlyEnforceIf(actions[Appendage.SKIP_TAILS].Not())
model.Add(cp_model.LinearExpr.ScalProd(actions.values(), [action.value.tails_needed for action in actions.keys()]) >= 0).OnlyEnforceIf(actions[Appendage.SKIP_TAILS]) model.Add(cp_model.LinearExpr.ScalProd(actions.values(), [action.value.tails_needed for action in actions.keys()]) >= 0).OnlyEnforceIf(actions[Appendage.SKIP_TAILS])
if BUYER == Buyer.A_PALAEONTOLOGIST_WITH_HOARDING_PROPENSITIES:
model.Add(skeleton_in_progress >= 100)
# Revenue # A Palaeontologist with Hoarding Propensities
model.Add(primary_revenue == value + 5) model.Add(skeleton_in_progress >= 100).OnlyEnforceIf(actions[Buyer.A_PALAEONTOLOGIST_WITH_HOARDING_PROPENSITIES])
model.Add(secondary_revenue == 500)
# Difficulty Level model.Add(primary_revenue == value + 5).OnlyEnforceIf(actions[Buyer.A_PALAEONTOLOGIST_WITH_HOARDING_PROPENSITIES])
model.Add(difficulty_level == 40*implausibility) model.Add(secondary_revenue == 500).OnlyEnforceIf(actions[Buyer.A_PALAEONTOLOGIST_WITH_HOARDING_PROPENSITIES])
# Added Exhaustion model.Add(difficulty_level == 40*implausibility).OnlyEnforceIf(actions[Buyer.A_PALAEONTOLOGIST_WITH_HOARDING_PROPENSITIES])
model.Add(added_exhaustion == 0)
elif BUYER == Buyer.A_NAIVE_COLLECTOR:
model.Add(skeleton_in_progress >= 100)
model.Add(added_exhaustion == 0).OnlyEnforceIf(actions[Buyer.A_PALAEONTOLOGIST_WITH_HOARDING_PROPENSITIES])
# A Naive Collector
model.Add(skeleton_in_progress >= 100).OnlyEnforceIf(actions[Buyer.A_NAIVE_COLLECTOR])
value_remainder = model.NewIntVar(0, 249, '{}: {}'.format(Buyer.A_NAIVE_COLLECTOR.name, 'value remainder'))
model.AddModuloEquality(value_remainder, value, 250) model.AddModuloEquality(value_remainder, value, 250)
# Revenue model.Add(primary_revenue == value - value_remainder).OnlyEnforceIf(actions[Buyer.A_NAIVE_COLLECTOR])
model.Add(primary_revenue == value - value_remainder) model.Add(secondary_revenue == 0).OnlyEnforceIf(actions[Buyer.A_NAIVE_COLLECTOR])
model.Add(secondary_revenue == 0)
# Difficulty Level model.Add(difficulty_level == 25*implausibility).OnlyEnforceIf(actions[Buyer.A_NAIVE_COLLECTOR])
model.Add(difficulty_level == 25*implausibility)
# Added Exhaustion model.Add(added_exhaustion == 0).OnlyEnforceIf(actions[Buyer.A_NAIVE_COLLECTOR])
model.Add(added_exhaustion == 0)
elif BUYER == Buyer.A_FAMILIAR_BOHEMIAN_SCULPTRESS:
model.Add(skeleton_in_progress >= 100)
model.Add(antiquity <= 0)
del value_remainder
# A Familiar Bohemian Sculptress
model.Add(skeleton_in_progress >= 100).OnlyEnforceIf(actions[Buyer.A_FAMILIAR_BOHEMIAN_SCULPTRESS])
model.Add(antiquity <= 0).OnlyEnforceIf(actions[Buyer.A_FAMILIAR_BOHEMIAN_SCULPTRESS])
value_remainder = model.NewIntVar(0, 249, '{}: {}'.format(Buyer.A_FAMILIAR_BOHEMIAN_SCULPTRESS.name, 'value remainder'))
model.AddModuloEquality(value_remainder, value, 250) model.AddModuloEquality(value_remainder, value, 250)
# Revenue model.Add(primary_revenue == value - value_remainder + 1000).OnlyEnforceIf(actions[Buyer.A_FAMILIAR_BOHEMIAN_SCULPTRESS])
model.Add(primary_revenue == value - value_remainder + 1000) model.Add(secondary_revenue == 250*counter_church).OnlyEnforceIf(actions[Buyer.A_FAMILIAR_BOHEMIAN_SCULPTRESS])
model.Add(secondary_revenue == 250*counter_church)
# Difficulty Level model.Add(difficulty_level == 50*implausibility).OnlyEnforceIf(actions[Buyer.A_FAMILIAR_BOHEMIAN_SCULPTRESS])
model.Add(difficulty_level == 50*implausibility)
# Added Exhaustion model.Add(added_exhaustion == 0).OnlyEnforceIf(actions[Buyer.A_FAMILIAR_BOHEMIAN_SCULPTRESS])
model.Add(added_exhaustion == 0)
elif BUYER == Buyer.A_PEDAGOGICALLY_INCLINED_GRANDMOTHER:
model.Add(skeleton_in_progress >= 100)
model.Add(menace <= 0)
del value_remainder
# A Pedagogically Inclined Grandmother
model.Add(skeleton_in_progress >= 100).OnlyEnforceIf(actions[Buyer.A_PEDAGOGICALLY_INCLINED_GRANDMOTHER])
model.Add(menace <= 0).OnlyEnforceIf(actions[Buyer.A_PEDAGOGICALLY_INCLINED_GRANDMOTHER])
value_remainder = model.NewIntVar(0, 49, '{}: {}'.format(Buyer.A_PEDAGOGICALLY_INCLINED_GRANDMOTHER.name, 'value remainder'))
model.AddModuloEquality(value_remainder, value, 50) model.AddModuloEquality(value_remainder, value, 50)
# Revenue model.Add(primary_revenue == value - value_remainder + 1000).OnlyEnforceIf(actions[Buyer.A_PEDAGOGICALLY_INCLINED_GRANDMOTHER])
model.Add(primary_revenue == value - value_remainder + 1000) model.Add(secondary_revenue == 0).OnlyEnforceIf(actions[Buyer.A_PEDAGOGICALLY_INCLINED_GRANDMOTHER])
model.Add(secondary_revenue == 0)
# Difficulty Level model.Add(difficulty_level == 50*implausibility).OnlyEnforceIf(actions[Buyer.A_PEDAGOGICALLY_INCLINED_GRANDMOTHER])
model.Add(difficulty_level == 50*implausibility)
# Added Exhaustion model.Add(added_exhaustion == 0).OnlyEnforceIf(actions[Buyer.A_PEDAGOGICALLY_INCLINED_GRANDMOTHER])
model.Add(added_exhaustion == 0)
elif BUYER == Buyer.A_THEOLOGIAN_OF_THE_OLD_SCHOOL:
model.Add(skeleton_in_progress >= 100)
model.Add(amalgamy <= 0)
del value_remainder
# A Theologian of the Old School
model.Add(skeleton_in_progress >= 100).OnlyEnforceIf(actions[Buyer.A_THEOLOGIAN_OF_THE_OLD_SCHOOL])
model.Add(amalgamy <= 0).OnlyEnforceIf(actions[Buyer.A_THEOLOGIAN_OF_THE_OLD_SCHOOL])
value_remainder = model.NewIntVar(0, 249, '{}: {}'.format(Buyer.A_THEOLOGIAN_OF_THE_OLD_SCHOOL.name, 'value remainder'))
model.AddModuloEquality(value_remainder, value, 250) model.AddModuloEquality(value_remainder, value, 250)
# Revenue model.Add(primary_revenue == value - value_remainder + 1000).OnlyEnforceIf(actions[Buyer.A_THEOLOGIAN_OF_THE_OLD_SCHOOL])
model.Add(primary_revenue == value - value_remainder + 1000) model.Add(secondary_revenue == 0).OnlyEnforceIf(actions[Buyer.A_THEOLOGIAN_OF_THE_OLD_SCHOOL])
model.Add(secondary_revenue == 0)
# Difficulty Level model.Add(difficulty_level == 50*implausibility).OnlyEnforceIf(actions[Buyer.A_THEOLOGIAN_OF_THE_OLD_SCHOOL])
model.Add(difficulty_level == 50*implausibility)
# Added Exhaustion model.Add(added_exhaustion == 0).OnlyEnforceIf(actions[Buyer.A_THEOLOGIAN_OF_THE_OLD_SCHOOL])
model.Add(added_exhaustion == 0)
elif BUYER == Buyer.AN_ENTHUSIAST_OF_THE_ANCIENT_WORLD:
model.Add(skeleton_in_progress >= 100)
model.Add(antiquity > 0)
del value_remainder
# An Enthusiast of the Ancient World
model.Add(skeleton_in_progress >= 100).OnlyEnforceIf(actions[Buyer.AN_ENTHUSIAST_OF_THE_ANCIENT_WORLD])
model.Add(antiquity > 0).OnlyEnforceIf(actions[Buyer.AN_ENTHUSIAST_OF_THE_ANCIENT_WORLD])
value_remainder = model.NewIntVar(0, 49, '{}: {}'.format(Buyer.AN_ENTHUSIAST_OF_THE_ANCIENT_WORLD.name, 'value remainder'))
model.AddModuloEquality(value_remainder, value, 50) model.AddModuloEquality(value_remainder, value, 50)
# Revenue model.Add(primary_revenue == value - value_remainder).OnlyEnforceIf(actions[Buyer.AN_ENTHUSIAST_OF_THE_ANCIENT_WORLD])
model.Add(primary_revenue == value - value_remainder) model.Add(secondary_revenue == 250*antiquity + (250 if BONE_MARKET_FLUCTUATIONS == Fluctuation.ANTIQUITY else 0)).OnlyEnforceIf(actions[Buyer.AN_ENTHUSIAST_OF_THE_ANCIENT_WORLD])
model.Add(secondary_revenue == 250*antiquity + (250 if BONE_MARKET_FLUCTUATIONS == Fluctuation.ANTIQUITY else 0))
# Difficulty Level model.Add(difficulty_level == 45*implausibility).OnlyEnforceIf(actions[Buyer.AN_ENTHUSIAST_OF_THE_ANCIENT_WORLD])
model.Add(difficulty_level == 45*implausibility)
# Added Exhaustion model.Add(added_exhaustion == 0).OnlyEnforceIf(actions[Buyer.AN_ENTHUSIAST_OF_THE_ANCIENT_WORLD])
model.Add(added_exhaustion == 0)
elif BUYER == Buyer.MRS_PLENTY:
model.Add(skeleton_in_progress >= 100)
model.Add(menace > 0)
del value_remainder
# Mrs Plenty
model.Add(skeleton_in_progress >= 100).OnlyEnforceIf(actions[Buyer.MRS_PLENTY])
model.Add(menace > 0).OnlyEnforceIf(actions[Buyer.MRS_PLENTY])
value_remainder = model.NewIntVar(0, 49, '{}: {}'.format(Buyer.MRS_PLENTY.name, 'value remainder'))
model.AddModuloEquality(value_remainder, value, 50) model.AddModuloEquality(value_remainder, value, 50)
# Revenue model.Add(primary_revenue == value - value_remainder).OnlyEnforceIf(actions[Buyer.MRS_PLENTY])
model.Add(primary_revenue == value - value_remainder) model.Add(secondary_revenue == 250*menace).OnlyEnforceIf(actions[Buyer.MRS_PLENTY])
model.Add(secondary_revenue == 250*menace)
# Difficulty Level model.Add(difficulty_level == 45*implausibility).OnlyEnforceIf(actions[Buyer.MRS_PLENTY])
model.Add(difficulty_level == 45*implausibility)
# Added Exhaustion model.Add(added_exhaustion == 0).OnlyEnforceIf(actions[Buyer.MRS_PLENTY])
model.Add(added_exhaustion == 0)
elif BUYER == Buyer.A_TENTACLED_SERVANT:
model.Add(skeleton_in_progress >= 100)
model.Add(amalgamy > 0)
del value_remainder
# A Tentacled Servant
model.Add(skeleton_in_progress >= 100).OnlyEnforceIf(actions[Buyer.A_TENTACLED_SERVANT])
model.Add(amalgamy > 0).OnlyEnforceIf(actions[Buyer.A_TENTACLED_SERVANT])
value_remainder = model.NewIntVar(0, 49, '{}: {}'.format(Buyer.A_TENTACLED_SERVANT.name, 'value remainder'))
model.AddModuloEquality(value_remainder, value, 50) model.AddModuloEquality(value_remainder, value, 50)
# Revenue model.Add(primary_revenue == value - value_remainder + 250).OnlyEnforceIf(actions[Buyer.A_TENTACLED_SERVANT])
model.Add(primary_revenue == value - value_remainder + 250) model.Add(secondary_revenue == 250*amalgamy + (250 if BONE_MARKET_FLUCTUATIONS == Fluctuation.AMALGAMY else 0)).OnlyEnforceIf(actions[Buyer.A_TENTACLED_SERVANT])
model.Add(secondary_revenue == 250*amalgamy + (250 if BONE_MARKET_FLUCTUATIONS == Fluctuation.AMALGAMY else 0))
# Difficulty Level model.Add(difficulty_level == 45*implausibility).OnlyEnforceIf(actions[Buyer.A_TENTACLED_SERVANT])
model.Add(difficulty_level == 45*implausibility)
# Added Exhaustion model.Add(added_exhaustion == 0).OnlyEnforceIf(actions[Buyer.A_TENTACLED_SERVANT])
model.Add(added_exhaustion == 0)
elif BUYER == Buyer.AN_INVESTMENT_MINDED_AMBASSADOR:
model.Add(skeleton_in_progress >= 100)
model.Add(antiquity > 0)
antiquity_squared = model.NewIntVar(0, cp_model.INT32_MAX, 'antiquity squared') del value_remainder
# An Investment-Minded Ambassador
model.Add(skeleton_in_progress >= 100).OnlyEnforceIf(actions[Buyer.AN_INVESTMENT_MINDED_AMBASSADOR])
model.Add(antiquity > 0).OnlyEnforceIf(actions[Buyer.AN_INVESTMENT_MINDED_AMBASSADOR])
antiquity_squared = model.NewIntVar(0, cp_model.INT32_MAX, '{}: {}'.format(Buyer.AN_INVESTMENT_MINDED_AMBASSADOR.name, 'antiquity squared'))
model.AddMultiplicationEquality(antiquity_squared, [antiquity, antiquity]) model.AddMultiplicationEquality(antiquity_squared, [antiquity, antiquity])
tailfeathers = model.NewIntVar(0, cp_model.INT32_MAX, 'tailfeathers') tailfeathers = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, '{}: {}'.format(Buyer.AN_INVESTMENT_MINDED_AMBASSADOR.name, 'tailfeathers'))
if BONE_MARKET_FLUCTUATIONS == Fluctuation.ANTIQUITY: if BONE_MARKET_FLUCTUATIONS == Fluctuation.ANTIQUITY:
model.AddApproximateExponentiationEquality(tailfeathers, antiquity, 2.2, MAXIMUM_ATTRIBUTE) model.AddApproximateExponentiationEquality(tailfeathers, antiquity, 2.2, MAXIMUM_ATTRIBUTE)
else: else:
model.Add(tailfeathers == antiquity_squared) model.Add(tailfeathers == antiquity_squared).OnlyEnforceIf(actions[Buyer.AN_INVESTMENT_MINDED_AMBASSADOR])
value_remainder = model.NewIntVar(0, 49, '{}: {}'.format(Buyer.AN_INVESTMENT_MINDED_AMBASSADOR.name, 'value remainder'))
model.AddModuloEquality(value_remainder, value, 50) model.AddModuloEquality(value_remainder, value, 50)
extra_value = model.NewIntermediateBoolVar('extra value', value_remainder, cp_model.Domain.FromFlatIntervals([0, cp_model.INT_MAX])) extra_value = model.NewIntermediateBoolVar('{}: {}'.format(Buyer.AN_INVESTMENT_MINDED_AMBASSADOR.name, 'extra value'), value_remainder, cp_model.Domain.FromFlatIntervals([0, cp_model.INT_MAX]))
# Revenue model.Add(primary_revenue == value + 50*extra_value + 250).OnlyEnforceIf(actions[Buyer.AN_INVESTMENT_MINDED_AMBASSADOR])
model.Add(primary_revenue == value + 50*extra_value + 250) model.Add(secondary_revenue == 250*tailfeathers).OnlyEnforceIf(actions[Buyer.AN_INVESTMENT_MINDED_AMBASSADOR])
model.Add(secondary_revenue == 250*tailfeathers)
# Difficulty Level model.Add(difficulty_level == 75*implausibility).OnlyEnforceIf(actions[Buyer.AN_INVESTMENT_MINDED_AMBASSADOR])
model.Add(difficulty_level == 75*implausibility)
# Added Exhaustion # The indirection is necessary for applying an enforcement literal
model.AddDivisionEquality(added_exhaustion, antiquity_squared, 20) derived_exhaustion = model.NewIntVar(0, cp_model.INT32_MAX, '{}: {}'.format(Buyer.AN_INVESTMENT_MINDED_AMBASSADOR.name, 'derived exhaustion'))
elif BUYER == Buyer.A_TELLER_OF_TERRORS: model.AddDivisionEquality(derived_exhaustion, antiquity_squared, 20)
model.Add(skeleton_in_progress >= 100) model.Add(added_exhaustion == derived_exhaustion).OnlyEnforceIf(actions[Buyer.AN_INVESTMENT_MINDED_AMBASSADOR])
model.Add(menace > 0)
menace_squared = model.NewIntVar(0, cp_model.INT32_MAX, 'menace squared') del antiquity_squared, tailfeathers, value_remainder, extra_value, derived_exhaustion
# A Teller of Terrors
model.Add(skeleton_in_progress >= 100).OnlyEnforceIf(actions[Buyer.A_TELLER_OF_TERRORS])
model.Add(menace > 0).OnlyEnforceIf(actions[Buyer.A_TELLER_OF_TERRORS])
menace_squared = model.NewIntVar(0, cp_model.INT32_MAX, '{}: {}'.format(Buyer.A_TELLER_OF_TERRORS.name, 'menace squared'))
model.AddMultiplicationEquality(menace_squared, [menace, menace]) model.AddMultiplicationEquality(menace_squared, [menace, menace])
value_remainder = model.NewIntVar(0, 9, '{}: {}'.format(Buyer.A_TELLER_OF_TERRORS.name, 'value remainder'))
model.AddModuloEquality(value_remainder, value, 10) model.AddModuloEquality(value_remainder, value, 10)
# Revenue model.Add(primary_revenue == value - value_remainder + 50).OnlyEnforceIf(actions[Buyer.A_TELLER_OF_TERRORS])
model.Add(primary_revenue == value - value_remainder + 50) model.Add(secondary_revenue == 50*menace_squared).OnlyEnforceIf(actions[Buyer.A_TELLER_OF_TERRORS])
model.Add(secondary_revenue == 50*menace_squared)
# Difficulty Level model.Add(difficulty_level == 75*implausibility).OnlyEnforceIf(actions[Buyer.A_TELLER_OF_TERRORS])
model.Add(difficulty_level == 75*implausibility)
# Added Exhaustion # The indirection is necessary for applying an enforcement literal
model.AddDivisionEquality(added_exhaustion, menace_squared, 100) derived_exhaustion = model.NewIntVar(0, cp_model.INT32_MAX, '{}: {}'.format(Buyer.A_TELLER_OF_TERRORS.name, 'derived exhaustion'))
elif BUYER == Buyer.A_TENTACLED_ENTREPRENEUR: model.AddDivisionEquality(derived_exhaustion, menace_squared, 100)
model.Add(skeleton_in_progress >= 100) model.Add(added_exhaustion == derived_exhaustion).OnlyEnforceIf(actions[Buyer.A_TELLER_OF_TERRORS])
model.Add(amalgamy > 0)
amalgamy_squared = model.NewIntVar(0, cp_model.INT32_MAX, 'amalgamy squared') del menace_squared, value_remainder, derived_exhaustion
# A Tentacled Entrepreneur
model.Add(skeleton_in_progress >= 100).OnlyEnforceIf(actions[Buyer.A_TENTACLED_ENTREPRENEUR])
model.Add(amalgamy > 0).OnlyEnforceIf(actions[Buyer.A_TENTACLED_ENTREPRENEUR])
amalgamy_squared = model.NewIntVar(0, cp_model.INT32_MAX, '{}: {}'.format(Buyer.A_TENTACLED_ENTREPRENEUR.name, 'amalgamy squared'))
model.AddMultiplicationEquality(amalgamy_squared, [amalgamy, amalgamy]) model.AddMultiplicationEquality(amalgamy_squared, [amalgamy, amalgamy])
final_breaths = model.NewIntVar(0, cp_model.INT32_MAX, 'final breaths') final_breaths = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, '{}: {}'.format(Buyer.A_TENTACLED_ENTREPRENEUR.name, 'final breaths'))
if BONE_MARKET_FLUCTUATIONS == Fluctuation.AMALGAMY: if BONE_MARKET_FLUCTUATIONS == Fluctuation.AMALGAMY:
model.AddApproximateExponentiationEquality(final_breaths, amalgamy, 2.2, MAXIMUM_ATTRIBUTE) model.AddApproximateExponentiationEquality(final_breaths, amalgamy, 2.2, MAXIMUM_ATTRIBUTE)
else: else:
model.Add(final_breaths == amalgamy_squared) model.Add(final_breaths == amalgamy_squared).OnlyEnforceIf(actions[Buyer.A_TENTACLED_ENTREPRENEUR])
value_remainder = model.NewIntVar(0, 49, '{}: {}'.format(Buyer.A_TENTACLED_ENTREPRENEUR.name, 'value remainder'))
model.AddModuloEquality(value_remainder, value, 50) model.AddModuloEquality(value_remainder, value, 50)
# Revenue model.Add(primary_revenue == value - value_remainder + 250).OnlyEnforceIf(actions[Buyer.A_TENTACLED_ENTREPRENEUR])
model.Add(primary_revenue == value - value_remainder + 250) model.Add(secondary_revenue == 50*final_breaths).OnlyEnforceIf(actions[Buyer.A_TENTACLED_ENTREPRENEUR])
model.Add(secondary_revenue == 50*final_breaths)
# Difficulty Level model.Add(difficulty_level == 75*implausibility).OnlyEnforceIf(actions[Buyer.A_TENTACLED_ENTREPRENEUR])
model.Add(difficulty_level == 75*implausibility)
# Added Exhaustion # The indirection is necessary for applying an enforcement literal
model.AddDivisionEquality(added_exhaustion, amalgamy_squared, 100) derived_exhaustion = model.NewIntVar(0, cp_model.INT32_MAX, '{}: {}'.format(Buyer.A_TENTACLED_ENTREPRENEUR.name, 'derived exhaustion'))
elif BUYER == Buyer.AN_AUTHOR_OF_GOTHIC_TALES: model.AddDivisionEquality(derived_exhaustion, amalgamy_squared, 100)
model.Add(skeleton_in_progress >= 100) model.Add(added_exhaustion == derived_exhaustion).OnlyEnforceIf(actions[Buyer.A_TENTACLED_ENTREPRENEUR])
model.Add(antiquity > 0)
model.Add(menace > 0)
antiquity_times_menace = model.NewIntVar(0, cp_model.INT32_MAX, 'antiquity times menace') del amalgamy_squared, final_breaths, value_remainder, derived_exhaustion
# An Author of Gothic Tales
model.Add(skeleton_in_progress >= 100).OnlyEnforceIf(actions[Buyer.AN_AUTHOR_OF_GOTHIC_TALES])
model.Add(antiquity > 0).OnlyEnforceIf(actions[Buyer.AN_AUTHOR_OF_GOTHIC_TALES])
model.Add(menace > 0).OnlyEnforceIf(actions[Buyer.AN_AUTHOR_OF_GOTHIC_TALES])
antiquity_times_menace = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, '{}: {}'.format(Buyer.AN_AUTHOR_OF_GOTHIC_TALES.name, 'antiquity times menace'))
model.AddMultiplicationEquality(antiquity_times_menace, [antiquity, menace]) model.AddMultiplicationEquality(antiquity_times_menace, [antiquity, menace])
value_remainder = model.NewIntVar(0, 49, '{}: {}'.format(Buyer.AN_AUTHOR_OF_GOTHIC_TALES.name, 'value remainder'))
model.AddModuloEquality(value_remainder, value, 50) model.AddModuloEquality(value_remainder, value, 50)
# Revenue model.Add(primary_revenue == value - value_remainder + 250).OnlyEnforceIf(actions[Buyer.AN_AUTHOR_OF_GOTHIC_TALES])
model.Add(primary_revenue == value - value_remainder + 250) model.Add(secondary_revenue == 250*antiquity_times_menace + 250*(menace if BONE_MARKET_FLUCTUATIONS == Fluctuation.ANTIQUITY else 0)).OnlyEnforceIf(actions[Buyer.AN_AUTHOR_OF_GOTHIC_TALES])
model.Add(secondary_revenue == 250*antiquity_times_menace + 250*(menace if BONE_MARKET_FLUCTUATIONS == Fluctuation.ANTIQUITY else 0))
# Difficulty Level model.Add(difficulty_level == 75*implausibility).OnlyEnforceIf(actions[Buyer.AN_AUTHOR_OF_GOTHIC_TALES])
model.Add(difficulty_level == 75*implausibility)
# Added Exhaustion # The indirection is necessary for applying an enforcement literal
model.AddDivisionEquality(added_exhaustion, antiquity_times_menace, 20) derived_exhaustion = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, '{}: {}'.format(Buyer.AN_AUTHOR_OF_GOTHIC_TALES.name, 'derived exhaustion'))
elif BUYER == Buyer.A_ZAILOR_WITH_PARTICULAR_INTERESTS: model.AddDivisionEquality(derived_exhaustion, antiquity_times_menace, 20)
model.Add(skeleton_in_progress >= 100) model.Add(added_exhaustion == derived_exhaustion).OnlyEnforceIf(actions[Buyer.AN_AUTHOR_OF_GOTHIC_TALES])
model.Add(antiquity > 0)
model.Add(amalgamy > 0)
amalgamy_times_antiquity = model.NewIntVar(0, cp_model.INT32_MAX, 'amalgamy times antiquity') del antiquity_times_menace, value_remainder, derived_exhaustion
# A Zailor with Particular Interests
model.Add(skeleton_in_progress >= 100).OnlyEnforceIf(actions[Buyer.A_ZAILOR_WITH_PARTICULAR_INTERESTS])
model.Add(antiquity > 0).OnlyEnforceIf(actions[Buyer.A_ZAILOR_WITH_PARTICULAR_INTERESTS])
model.Add(amalgamy > 0).OnlyEnforceIf(actions[Buyer.A_ZAILOR_WITH_PARTICULAR_INTERESTS])
amalgamy_times_antiquity = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, '{}: {}'.format(Buyer.A_ZAILOR_WITH_PARTICULAR_INTERESTS.name, 'amalgamy times antiquity'))
model.AddMultiplicationEquality(amalgamy_times_antiquity, [amalgamy, antiquity]) model.AddMultiplicationEquality(amalgamy_times_antiquity, [amalgamy, antiquity])
value_remainder = model.NewIntVar(0, 9, '{}: {}'.format(Buyer.A_ZAILOR_WITH_PARTICULAR_INTERESTS.name, 'value remainder'))
model.AddModuloEquality(value_remainder, value, 10) model.AddModuloEquality(value_remainder, value, 10)
# Revenue model.Add(primary_revenue == value - value_remainder + 250).OnlyEnforceIf(actions[Buyer.A_ZAILOR_WITH_PARTICULAR_INTERESTS])
model.Add(primary_revenue == value - value_remainder + 250) model.Add(secondary_revenue == 250*amalgamy_times_antiquity + 250*(amalgamy if BONE_MARKET_FLUCTUATIONS == Fluctuation.ANTIQUITY else antiquity if BONE_MARKET_FLUCTUATIONS == Fluctuation.AMALGAMY else 0)).OnlyEnforceIf(actions[Buyer.A_ZAILOR_WITH_PARTICULAR_INTERESTS])
model.Add(secondary_revenue == 250*amalgamy_times_antiquity + 250*(amalgamy if BONE_MARKET_FLUCTUATIONS == Fluctuation.ANTIQUITY else antiquity if BONE_MARKET_FLUCTUATIONS == Fluctuation.AMALGAMY else 0))
# Difficulty Level model.Add(difficulty_level == 75*implausibility).OnlyEnforceIf(actions[Buyer.A_ZAILOR_WITH_PARTICULAR_INTERESTS])
model.Add(difficulty_level == 75*implausibility)
# Added Exhaustion # The indirection is necessary for applying an enforcement literal
model.AddDivisionEquality(added_exhaustion, amalgamy_times_antiquity, 20) derived_exhaustion = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, '{}: {}'.format(Buyer.A_ZAILOR_WITH_PARTICULAR_INTERESTS.name, 'derived exhaustion'))
elif BUYER == Buyer.A_RUBBERY_COLLECTOR: model.AddDivisionEquality(derived_exhaustion, amalgamy_times_antiquity, 20)
model.Add(skeleton_in_progress >= 100) model.Add(added_exhaustion == derived_exhaustion).OnlyEnforceIf(actions[Buyer.A_ZAILOR_WITH_PARTICULAR_INTERESTS])
model.Add(amalgamy > 0)
model.Add(menace > 0)
amalgamy_times_menace = model.NewIntVar(0, cp_model.INT32_MAX, 'amalgamy times menace') del amalgamy_times_antiquity, value_remainder, derived_exhaustion
# A Rubbery Collector
model.Add(skeleton_in_progress >= 100).OnlyEnforceIf(actions[Buyer.A_RUBBERY_COLLECTOR])
model.Add(amalgamy > 0).OnlyEnforceIf(actions[Buyer.A_RUBBERY_COLLECTOR])
model.Add(menace > 0).OnlyEnforceIf(actions[Buyer.A_RUBBERY_COLLECTOR])
amalgamy_times_menace = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, '{}: {}'.format(Buyer.A_RUBBERY_COLLECTOR.name, 'amalgamy times menace'))
model.AddMultiplicationEquality(amalgamy_times_menace, [amalgamy, menace]) model.AddMultiplicationEquality(amalgamy_times_menace, [amalgamy, menace])
value_remainder = model.NewIntVar(0, 49, '{}: {}'.format(Buyer.A_RUBBERY_COLLECTOR.name, 'value remainder'))
model.AddModuloEquality(value_remainder, value, 50) model.AddModuloEquality(value_remainder, value, 50)
# Revenue model.Add(primary_revenue == value - value_remainder + 250).OnlyEnforceIf(actions[Buyer.A_RUBBERY_COLLECTOR])
model.Add(primary_revenue == value - value_remainder + 250) model.Add(secondary_revenue == 250*amalgamy_times_menace + 250*(menace if BONE_MARKET_FLUCTUATIONS == Fluctuation.AMALGAMY else 0)).OnlyEnforceIf(actions[Buyer.A_RUBBERY_COLLECTOR])
model.Add(secondary_revenue == 250*amalgamy_times_menace + 250*(menace if BONE_MARKET_FLUCTUATIONS == Fluctuation.AMALGAMY else 0))
# Difficulty Level model.Add(difficulty_level == 75*implausibility).OnlyEnforceIf(actions[Buyer.A_RUBBERY_COLLECTOR])
model.Add(difficulty_level == 75*implausibility)
# Added Exhaustion # The indirection is necessary for applying an enforcement literal
model.AddDivisionEquality(added_exhaustion, amalgamy_times_menace, 20) derived_exhaustion = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, '{}: {}'.format(Buyer.A_RUBBERY_COLLECTOR.name, 'derived exhaustion'))
elif BUYER == Buyer.A_CONSTABLE: model.AddDivisionEquality(derived_exhaustion, amalgamy_times_menace, 20)
model.AddLinearExpressionInDomain(skeleton_in_progress, cp_model.Domain.FromFlatIntervals([110, 119])) model.Add(added_exhaustion == derived_exhaustion).OnlyEnforceIf(actions[Buyer.A_RUBBERY_COLLECTOR])
del amalgamy_times_menace, value_remainder, derived_exhaustion
# A Constable
model.AddLinearExpressionInDomain(skeleton_in_progress, cp_model.Domain.FromFlatIntervals([110, 119])).OnlyEnforceIf(actions[Buyer.A_CONSTABLE])
value_remainder = model.NewIntVar(0, 49, '{}: {}'.format(Buyer.A_CONSTABLE.name, 'value remainder'))
model.AddModuloEquality(value_remainder, value, 50) model.AddModuloEquality(value_remainder, value, 50)
# Revenue model.Add(primary_revenue == value - value_remainder + 1000).OnlyEnforceIf(actions[Buyer.A_CONSTABLE])
model.Add(primary_revenue == value - value_remainder + 1000) model.Add(secondary_revenue == 0).OnlyEnforceIf(actions[Buyer.A_CONSTABLE])
model.Add(secondary_revenue == 0)
# Difficulty Level model.Add(difficulty_level == 50*implausibility).OnlyEnforceIf(actions[Buyer.A_CONSTABLE])
model.Add(difficulty_level == 50*implausibility)
# Added Exhaustion model.Add(added_exhaustion == 0).OnlyEnforceIf(actions[Buyer.A_CONSTABLE])
model.Add(added_exhaustion == 0)
elif BUYER == Buyer.AN_ENTHUSIAST_IN_SKULLS:
model.Add(skeleton_in_progress >= 100)
model.Add(skulls >= 2)
extra_skulls = model.NewIntVar(0, cp_model.INT32_MAX, 'extra skulls') del value_remainder
model.Add(extra_skulls == skulls - 1)
vital_intelligence = model.NewIntVar(0, cp_model.INT32_MAX, 'vital intelligence')
# An Enthusiast in Skulls
model.Add(skeleton_in_progress >= 100).OnlyEnforceIf(actions[Buyer.AN_ENTHUSIAST_IN_SKULLS])
model.Add(skulls >= 2).OnlyEnforceIf(actions[Buyer.AN_ENTHUSIAST_IN_SKULLS])
extra_skulls = model.NewIntVar(0, cp_model.INT32_MAX, '{}: {}'.format(Buyer.AN_ENTHUSIAST_IN_SKULLS.name, 'extra skulls'))
model.Add(extra_skulls == skulls - 1).OnlyEnforceIf(actions[Buyer.AN_ENTHUSIAST_IN_SKULLS])
vital_intelligence = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, '{}: {}'.format(Buyer.AN_ENTHUSIAST_IN_SKULLS.name, 'vital intelligence'))
model.AddApproximateExponentiationEquality(vital_intelligence, extra_skulls, 1.8, MAXIMUM_ATTRIBUTE) model.AddApproximateExponentiationEquality(vital_intelligence, extra_skulls, 1.8, MAXIMUM_ATTRIBUTE)
# Revenue model.Add(primary_revenue == value).OnlyEnforceIf(actions[Buyer.AN_ENTHUSIAST_IN_SKULLS])
model.Add(primary_revenue == value) model.Add(secondary_revenue == 1250*vital_intelligence).OnlyEnforceIf(actions[Buyer.AN_ENTHUSIAST_IN_SKULLS])
model.Add(secondary_revenue == 1250*vital_intelligence)
# Difficulty Level model.Add(difficulty_level == 60*implausibility).OnlyEnforceIf(actions[Buyer.AN_ENTHUSIAST_IN_SKULLS])
model.Add(difficulty_level == 60*implausibility)
# Added Exhaustion # The indirection is necessary for applying an enforcement literal
model.AddDivisionEquality(added_exhaustion, vital_intelligence, 4) derived_exhaustion = model.NewIntVar(0, cp_model.INT32_MAX, '{}: {}'.format(Buyer.AN_ENTHUSIAST_IN_SKULLS.name, 'derived exhaustion'))
elif BUYER == Buyer.A_DREARY_MIDNIGHTER: model.AddDivisionEquality(derived_exhaustion, vital_intelligence, 4)
model.AddLinearExpressionInDomain(skeleton_in_progress, cp_model.Domain.FromFlatIntervals([110, 299])) model.Add(added_exhaustion == derived_exhaustion).OnlyEnforceIf(actions[Buyer.AN_ENTHUSIAST_IN_SKULLS])
model.Add(amalgamy <= 0)
model.Add(counter_church <= 0)
del extra_skulls, vital_intelligence, derived_exhaustion
# A Dreary Midnighter
model.AddLinearExpressionInDomain(skeleton_in_progress, cp_model.Domain.FromFlatIntervals([110, 299])).OnlyEnforceIf(actions[Buyer.A_DREARY_MIDNIGHTER])
model.Add(amalgamy <= 0).OnlyEnforceIf(actions[Buyer.A_DREARY_MIDNIGHTER])
model.Add(counter_church <= 0).OnlyEnforceIf(actions[Buyer.A_DREARY_MIDNIGHTER])
value_remainder = model.NewIntVar(0, 2, '{}: {}'.format(Buyer.A_DREARY_MIDNIGHTER.name, 'value remainder'))
model.AddModuloEquality(value_remainder, value, 3) model.AddModuloEquality(value_remainder, value, 3)
# Revenue model.Add(primary_revenue == value - value_remainder + 300).OnlyEnforceIf(actions[Buyer.A_DREARY_MIDNIGHTER])
model.Add(primary_revenue == value - value_remainder + 300) model.Add(secondary_revenue == 250).OnlyEnforceIf(actions[Buyer.A_DREARY_MIDNIGHTER])
model.Add(secondary_revenue == 250)
# Difficulty Level model.Add(difficulty_level == 100*implausibility).OnlyEnforceIf(actions[Buyer.A_DREARY_MIDNIGHTER])
model.Add(difficulty_level == 100*implausibility)
# Added Exhaustion model.Add(added_exhaustion == 0).OnlyEnforceIf(actions[Buyer.A_DREARY_MIDNIGHTER])
model.Add(added_exhaustion == 0)
elif BUYER == Buyer.THE_DUMBWAITER_OF_BALMORAL:
model.AddLinearExpressionInDomain(skeleton_in_progress, cp_model.Domain.FromFlatIntervals([180, 189]))
model.Add(value >= 250)
del value_remainder
# The Dumbwaiter of Balmoral
model.AddLinearExpressionInDomain(skeleton_in_progress, cp_model.Domain.FromFlatIntervals([180, 189])).OnlyEnforceIf(actions[Buyer.THE_DUMBWAITER_OF_BALMORAL])
model.Add(value >= 250).OnlyEnforceIf(actions[Buyer.THE_DUMBWAITER_OF_BALMORAL])
value_remainder = model.NewIntVar(0, 249, '{}: {}'.format(Buyer.THE_DUMBWAITER_OF_BALMORAL.name, 'value remainder'))
model.AddModuloEquality(value_remainder, value, 250) model.AddModuloEquality(value_remainder, value, 250)
# Revenue model.Add(primary_revenue == value - value_remainder).OnlyEnforceIf(actions[Buyer.THE_DUMBWAITER_OF_BALMORAL])
model.Add(primary_revenue == value - value_remainder) model.Add(secondary_revenue == 0).OnlyEnforceIf(actions[Buyer.THE_DUMBWAITER_OF_BALMORAL])
model.Add(secondary_revenue == 0)
# Difficulty Level model.Add(difficulty_level == 200).OnlyEnforceIf(actions[Buyer.THE_DUMBWAITER_OF_BALMORAL])
model.Add(difficulty_level == 200)
# Added Exhaustion model.Add(added_exhaustion == 0).OnlyEnforceIf(actions[Buyer.THE_DUMBWAITER_OF_BALMORAL])
model.Add(added_exhaustion == 0)
del value_remainder
# Maximize profit margin # Maximize profit margin