model Lesson4_ChemistryCompetition
  options noimplicit
  uses "mmxprs", "mmsystem"

  parameters
    usedMaterials=5
    pH_goal=7
    numOfLogIntervals=17 ! changed from 18 to 17
  end-parameters

  declarations
    numOfMaterials=30 ! moved to declarations
    MATERIALS=1..numOfMaterials
    pH: array(MATERIALS) of real

    use_team1: array(MATERIALS) of mpvar
    use_team2: array(MATERIALS) of mpvar
    use_overall: array(MATERIALS) of mpvar

    logarg_team1:linctr
    logarg_team2:linctr
    OBJ:linctr
    startTime:time
    endTime:time
  end-declarations

  startTime:=time(SYS_NOW)

  pH::[8.13, 5.92, 5.98, 4.37, 8.6, 5.73, 7.84, 5.02, 4.22, 6.34, 9.07, 7.99, 9.3, 8.94, 1.43, 5.03, 8.64, 4.62, 5.97, 6.01, 7.93, 9.52, 6.39, 9.34, 9.38, 4.08, 11.29, 8.74, 3.84, 5.35]

  forall(m in MATERIALS) do
    use_team1(m) is_binary
    use_team2(m) is_binary
    use_overall(m) is_binary
  end-do

  sum(m in MATERIALS) use_team1(m) = usedMaterials
  sum(m in MATERIALS) use_team2(m) = usedMaterials

  forall(m in MATERIALS) do
    use_overall(m) = use_team1(m) + use_team2(m)
  end-do
  ! mutually exlusive elements use_team1, use_team2
  logarg_team1 := ( sum(m in MATERIALS) 10^(-pH(m))*use_team1(m) ) / usedMaterials
  logarg_team2 := ( sum(m in MATERIALS) 10^(-pH(m))*use_team2(m) ) / usedMaterials

  logarg_team1 <= 10^(-7)
  logarg_team2 <= 10^(-7)

  ! This is the objective function we would want, but it's non-linear:
  ! OBJ:= 1/2 * (-log(logarg_team1)/log(10) + -log(logarg_team2)/log(10))

  ! Excercise 1: Reformulate the above equation with Theorem 1 or 2.
  ! You will need to use the reformulation TWICE:
  ! once for x = logarg_team1, and once for x = logarg_team2.

  !Uncomment for log the tables:

  declarations
    logIntervals=1..numOfLogIntervals
    left: array(logIntervals) of real
    right: array(logIntervals) of real
    a: array(logIntervals) of real
    b: array(logIntervals) of real
    y_1,y_2: linctr
  end-declarations

  procedure PiecewiseLinear(logIntervals: range, x: linctr, y: linctr, M: real)

    declarations
      q: array(logIntervals) of mpvar
      p: array(logIntervals) of mpvar
    end-declarations

    forall(i in logIntervals) q(i) is_binary

    sum(i in logIntervals) q(i) = 1
    y := sum(i in logIntervals) (a(i)*p(i)+b(i)*q(i)) ! changed from = to :=
    ! alternatively: declare y as an mpvar and use = here

    forall(i in logIntervals) do

      p(i) <= right(i)*q(i)
      p(i) >= left(i)*q(i)
      p(i) <= M*q(i)
      p(i) >= -M*q(i)
      !p(i) <= x
      x+M*q(i)-M <= p(i)
      x-M*q(i)+M >= p(i)

    end-do

  end-procedure

  ! removed the last element of these 4 lists:
  left:: [0,10^(-12),10^(-11),10^(-10),10^(-9),10^(-8),10^(-7.75),10^(-7.5),10^(-7.25),10^(-7),10^(-6),10^(-5),10^(-4),10^(-3),10^(-2),0.1,0.5]
  right:: [10^(-12),10^(-11),10^(-10),10^(-9),10^(-8),10^(-7.75),10^(-7.5),10^(-7.25),10^(-7),10^(-6),10^(-5),10^(-4),10^(-3),10^(-2),0.1,0.5,1]
  a:: [-88*10^12,-11*10^10,-11*10^9,-11*10^8,-11*10^7,-32*10^6,-18*10^6,-101*10^5,-57*10^5,-11*10^5,-11*10^4,-11111,-1111,-111,-11.1,-1.75,-0.602]
  b:: [100,12.11,11.11,10.11,9.11,8.32,8.07,7.82,7.57,7.11,6.11,5.11,4.11,3.11,2.11,1.17,0.602]

  PiecewiseLinear(logIntervals, logarg_team1, y_1, 99999)
  PiecewiseLinear(logIntervals, logarg_team2, y_2, 99999)

  OBJ := 0.5*(y_1+y_2)

  minimise(OBJ)

  endTime:=time(SYS_NOW)

  writeln("Resulting average pH: ", getobjval)
  writeln("")

  writeln("Materials used Team 1:")
  forall(m in MATERIALS) do
    if(getsol(use_team1(m))=1) then
      writeln(m)
    end-if
  end-do
  writeln("")

  writeln("Materials used Team 2:")
  forall(m in MATERIALS) do
    if(getsol(use_team2(m))=1) then
      writeln(m)
    end-if
  end-do
  writeln("")

  writeln("Time elapsed: ", time(endTime-startTime))
end-model
