Warning: You won't be able to copy directly from Word to Xpress (Strange, huh). So, copy from Word to the Notepad and from the Notepad to Xpress.

The Euing Model that crashes the system....

! Euing Gas from Winston

! Illustrates modeling a piecewise-linear objective function

LET NGas = 2

LET NOil = 2

LET NRange = 4

TABLES

Profit(NGas) ! $/Gal profit for each gas

MaxOil2 ! Maximum gals of Oil 2 available

MaxOil1(NRange) ! Cumulative limit for each price range in gals

PriceOil1(NRange)! $/Gal price for Oil 1 in each range

CostOil1(NRange) ! Total cost at each limit in $'s assumes cost at 0 is $0

MinOil1(NGas) ! Minumum gals of Oil 1 in each gal of each gas.

DATA

Profit(1) = .12 .14

MaxOil2 = 1000

MaxOil1(1) = 500 1000 1500 2000

PriceOil1(1) = 0 25 20 15

MinOil1(1) = 0.5 0.6

VARIABLES

Oil(NOil)! Gals of each oil used

Gas(NGas)! Gals of each gas produced

OilGas(NOil,NGas)! Gals of each oil used to make each gas

Fract(NRange)! The weight used to represent Oil1 as an average of the range maximums

InRange(NRange) ! 1 if Oil1 is in the range, 0 otherwise.

! The problem is here. Either it's the comment after the & or it's the range 2:1 when irange = 1

ASSIGN

! Calculate the cumulative cost at each maximum from the prices

CostOil1(irange=1:NRange) = &

! The first piece + sum over ranges after that of Unit price * Gals in the Range

PriceOil1(1)*MaxOil1(1) + SUM(jrange = 2:irange)PriceOil1(jrange)*(MaxOil1(jrange) - MaxOil1(jrange-1))

!CONSTRAINTS

! NetProfit: SUM(igas = 1:NGas)Profit(igas)*Gas(igas) - &The profit from sales ($'s)

! SUM(irange = 1:NRange) CostOil1(irange)*Fract(irange) $ ! The cost of the Oil 1 ($'s)

! Total gallons of oil = sum of gallons used in each gas (gallons)

! OilUses(ioil=1:NOil): SUM(igas = 1:NGas)OiilGas(ioil,igas) = Oil(ioil)

! Total gallons of Gas = sum of gallons of oils used to make it (gallons)

! GasProduction(igas = 1:NGas): SUM(ioil=1:NOil)OilGas(ioil,igas) = Gas(igas)

! Composition Constraints ensuring the appropriate gallons of oil 1 in each gas

! Composition(igas = 1:NGas): MinOil1(igas)*Gas(igas) < OilGas(1,igas)

! The "interesting stuff starts here: How to represent the piecewise linear costs of Oil 1

! Express Oil1 as a weighted average of the Maximums for each range

! Oil1Weights: Oil(1) = SUM(irange = 1:NRange) MaxOil1(irange)*Fract(irange)

! The weights used in Oil1Weights should add to one -- We have supressed the weight on 0 (the beginning of

! the first range) so the weights can add to something less than one.

! SumTo1: SUM(irange = 1:NRange) Fract(irange) < 1

! Limit the weights to two consecutive limits. We can use the weight for range irange (except the last one)

! if we are in irange or irange+1

! LimitWeights (irange = 1:NRange-1): Fract(irange) < InRange(irange) + InRange(irange+1)

! We can only use the last weight if we are in the last range

! LastLimit: Fract(NRange) < InRange(NRange)

! We can only be in one range

! OneRange: SUM(irange = 1:NRange) InRange(irange) = 1

! BOUNDS

! Oil(2) < MaxOil2 ! Gallons

! InRange(irange=1:NRange).BV. ! Binary

The Euing Model that runs, but gives the wrong answer: Fract(4) = .75 the rest of the Fract variables are 0

! Euing Gas from Winston

! Illustrates modeling a piecewise-linear objective function

LET NGas = 2

LET NOil = 2

LET NRange = 4

TABLES

Profit(NGas) ! $/Gal profit for each gas

MaxOil2 ! Maximum gals of Oil 2 available

MaxOil1(NRange) ! Cumulative limit for each price range in gals

PriceOil1(NRange)! $/Gal price for Oil 1 in each range

CostOil1(NRange) ! Total cost at each limit in $'s assumes cost at 0 is $0

MinOil1(NGas) ! Minumum gals of Oil 1 in each gal of each gas.

DATA

Profit(1) = .12 .14

MaxOil2 = 1000

MaxOil1(1) = 500 1000 1500 2000

PriceOil1(1) = 0 25 20 15

MinOil1(1) = 0.5 0.6

VARIABLES

Oil(NOil)! Gals of each oil used

Gas(NGas)! Gals of each gas produced

OilGas(NOil,NGas)! Gals of each oil used to make each gas

Fract(NRange)! The weight used to represent Oil1 as an average of the range maximums

InRange(NRange) ! 1 if Oil1 is in the range, 0 otherwise.

! We fix this and the model runs, but gives the wrong answer

ASSIGN

! Calculate the cumulative cost at each maximum from the prices

! The first piece + sum over ranges after that of Unit price * Gals in the Range

CostOil1(1) = PriceOil1(1)*MaxOil1(1)

CostOil1(irange=2:NRange) = &

PriceOil1(1)*MaxOil1(1) + SUM(jrange = 2:irange)PriceOil1(jrange)*(MaxOil1(jrange) - MaxOil1(jrange-1))

CONSTRAINTS

NetProfit: SUM(igas = 1:NGas)Profit(igas)*Gas(igas) - &The profit from sales ($'s)

SUM(irange = 1:NRange) CostOil1(irange)*Fract(irange) $ ! The cost of the Oil 1 ($'s)

! Total gallons of oil = sum of gallons used in each gas (gallons)

OilUses(ioil=1:NOil): SUM(igas = 1:NGas)OiilGas(ioil,igas) = Oil(ioil)

! Total gallons of Gas = sum of gallons of oils used to make it (gallons)

GasProduction(igas = 1:NGas): SUM(ioil=1:NOil)OilGas(ioil,igas) = Gas(igas)

! Composition Constraints ensuring the appropriate gallons of oil 1 in each gas

Composition(igas = 1:NGas): MinOil1(igas)*Gas(igas) < OilGas(1,igas)

! The "interesting stuff starts here: How to represent the piecewise linear costs of Oil 1

! Express Oil1 as a weighted average of the Maximums for each range

Oil1Weights: Oil(1) = SUM(irange = 1:NRange) MaxOil1(irange)*Fract(irange)

! The weights used in Oil1Weights should add to one -- We have supressed the weight on 0 (the beginning of

! the first range) so the weights can add to something less than one.

SumTo1: SUM(irange = 1:NRange) Fract(irange) < 1

! Limit the weights to two consecutive limits. We can use the weight for range irange (except the last one)

! if we are in irange or irange+1

LimitWeights (irange = 1:NRange-1): Fract(irange) < InRange(irange) + InRange(irange+1)

! We can only use the last weight if we are in the last range

LastLimit: Fract(NRange) < InRange(NRange)

! We can only be in one range

OneRange: SUM(irange = 1:NRange) InRange(irange) = 1

BOUNDS

Oil(2) < MaxOil2 ! Gallons

InRange(irange=1:NRange).BV. ! Binary

The Correct Euing Model

! Euing Gas from Winston

! Illustrates modeling a piecewise-linear objective function

LET NGas = 2

LET NOil = 2

LET NRange = 4

TABLES

Profit(NGas) ! $/Gal profit for each gas

MaxOil2 ! Maximum gals of Oil 2 available

MaxOil1(NRange) ! Cumulative limit for each price range in gals

PriceOil1(NRange)! $/Gal price for Oil 1 in each range

CostOil1(NRange) ! Total cost at each limit in $'s assumes cost at 0 is $0

MinOil1(NGas) ! Minumum gals of Oil 1 in each gal of each gas.

DATA

Profit(1) = .12 .14

MaxOil2 = 1000

MaxOil1(1) = 500 1000 1500 2000

PriceOil1(1) = 0 25 20 15

MinOil1(1) = 0.5 0.6

VARIABLES

Oil(NOil)! Gals of each oil used

Gas(NGas)! Gals of each gas produced

OilGas(NOil,NGas)! Gals of each oil used to make each gas

Fract0 ! The weight on 0 we ignored before

Fract(NRange)! The weight used to represent Oil1 as an average of the range maximums

InRange(NRange) ! 1 if Oil1 is in the range, 0 otherwise.

ASSIGN

! Calculate the cumulative cost at each maximum from the prices

! The first piece + sum over ranges after that of Unit price * Gals in the Range

CostOil1(1) = PriceOil1(1)*MaxOil1(1)

CostOil1(irange=2:NRange) = &

PriceOil1(1)*MaxOil1(1) + SUM(jrange = 2:irange)PriceOil1(jrange)*(MaxOil1(jrange) - MaxOil1(jrange-1))

CONSTRAINTS

NetProfit: SUM(igas = 1:NGas)Profit(igas)*Gas(igas) - &The profit from sales ($'s)

SUM(irange = 1:NRange) CostOil1(irange)*Fract(irange) $ ! The cost of the Oil 1 ($'s)

! Total gallons of oil = sum of gallons used in each gas (gallons)

OilUses(ioil=1:NOil): SUM(igas = 1:NGas)OiilGas(ioil,igas) = Oil(ioil)

! Total gallons of Gas = sum of gallons of oils used to make it (gallons)

GasProduction(igas = 1:NGas): SUM(ioil=1:NOil)OilGas(ioil,igas) = Gas(igas)

! Composition Constraints ensuring the appropriate gallons of oil 1 in each gas

Composition(igas = 1:NGas): MinOil1(igas)*Gas(igas) < OilGas(1,igas)

! The "interesting stuff starts here: How to represent the piecewise linear costs of Oil 1

! Express Oil1 as a weighted average of the Maximums for each range

Oil1Weights: Oil(1) = SUM(irange = 1:NRange) MaxOil1(irange)*Fract(irange)

! The weights used in Oil1Weights should add to one -- We have supressed the weight on 0 (the beginning of

! the first range) so the weights can add to something less than one.

SumTo1: Fract0 + SUM(irange = 1:NRange) Fract(irange) = 1

! Limit the weights to two consecutive limits. We can use the weight for range irange (except the last one)

! if we are in irange or irange+1

LimitWeights (irange = 1:NRange-1): Fract(irange) < InRange(irange) + InRange(irange+1)

! We can only use the last weight if we are in the last range

LastLimit: Fract(NRange) < InRange(NRange)

! We can only use the first weight if we are in the first range

LimitFirst: Fract0 < InRange(1)

! We can only be in one range

OneRange: SUM(irange = 1:NRange) InRange(irange) = 1

BOUNDS

Oil(2) < MaxOil2 ! Gallons

InRange(irange=1:NRange).BV. ! Binary