#! /usr/bin/env python

import openturns as ot

ot.TESTPREAMBLE()

# Defining parameters
dimension = 3
size = 100

# Build standard LHS algorithm
distribution = ot.JointDistribution([ot.Uniform(0.0, 1.0)] * dimension)
lhs = ot.LHSExperiment(distribution, size)
lhs.setRandomShift(False)  # centered
lhs.setAlwaysShuffle(True)  # randomized

# print the object
print("lhs=", lhs)
bounds = distribution.getRange()
print("Bounds of uniform distributions=", bounds)

# Generate design without optimization
design = lhs.generate()
print("design=", design)

# Defining space fillings
spaceFillingC2 = ot.SpaceFillingC2()
spaceFillingPhiP = ot.SpaceFillingPhiP()

# print the criteria on this design
print(
    "PhiP=%f, C2=%f"
    % (ot.SpaceFillingPhiP().evaluate(design), ot.SpaceFillingC2().evaluate(design))
)

# Parameters for drawing design ==> Number of points are for the "grid"
Nx = 50
Ny = 50

# --------------------------------------------------#
# ------------ MonteCarlo algorithm  ------------- #
# --------------------------------------------------#

# RandomBruteForce MonteCarlo with N designs
N = 100

# 1) LHS with C2 optimization
optimalLHSAlgorithm = ot.MonteCarloLHS(lhs, N, spaceFillingC2)
# print lhs
print("lhs=", optimalLHSAlgorithm)
design = optimalLHSAlgorithm.generate()
print("Generating design with MonteCarlo and C2 space filling=", design)
result = optimalLHSAlgorithm.getResult()
print("History criterion=", result.getAlgoHistory())
print("Final criteria: C2=%f, PhiP=%f" % (result.getC2(), result.getPhiP()))

# Criterion graph ==> Graph object
criterionGraph = result.drawHistoryCriterion()

# 2) LHS with PhiP optimization (=mindist optim)
optimalLHSAlgorithm = ot.MonteCarloLHS(lhs, N, spaceFillingPhiP)
print("lhs=", optimalLHSAlgorithm)
design = optimalLHSAlgorithm.generate()
print("Generating design with MonteCarlo and PhiP optimum=", design)
result = optimalLHSAlgorithm.getResult()
print("History criterion=", result.getAlgoHistory())
print("Final criteria: C2=%f, PhiP=%f" % (result.getC2(), result.getPhiP()))

# Graph of criterion
criterionGraph = result.drawHistoryCriterion()

# --------------------------------------------------#
# ------------- Simulated annealing  ------------- #
# --------------------------------------------------#
# Defining temperature profil ==> TO, iterations...
T0 = 10.0
iMax = 2000
c = 0.95
# Care, c should be in ]0,1[
# Geometric profil
geomProfile = ot.GeometricProfile(T0, c, iMax)

# 3) Simulated Annealing LHS with geometric temperature, C2 optimization
optimalLHSAlgorithm = ot.SimulatedAnnealingLHS(lhs, spaceFillingC2, geomProfile)
print("lhs=", optimalLHSAlgorithm)
design = optimalLHSAlgorithm.generate()
print(
    "Generating design using SimulatedAnnealing geometric temperature & C2 criterion=",
    design,
)
result = optimalLHSAlgorithm.getResult()
history = result.getAlgoHistory()
print("History criterion=", history[:, 0])
print("History temperature=", history[:, 1])
print("History probability=", history[:, 2])
print("Final criteria: C2=%f, PhiP=%f" % (result.getC2(), result.getPhiP()))

# Criteria drawing
# SA algorithms returns also Probability & temperature
criterionGraph = result.drawHistoryCriterion()
probaGraph = result.drawHistoryProbability()
tempGraph = result.drawHistoryTemperature()

# 4) Simulated Annealing LHS with geometric temperature, PhiP optimization
optimalLHSAlgorithm = ot.SimulatedAnnealingLHS(lhs, spaceFillingPhiP, geomProfile)
print("lhs=", optimalLHSAlgorithm)
design = optimalLHSAlgorithm.generate()
print(
    "Generating design using SimulatedAnnealing geometric temperature & C2 criterion=",
    design,
)
result = optimalLHSAlgorithm.getResult()
history = result.getAlgoHistory()
print("History criterion=", history[:, 0])
print("History temperature=", history[:, 1])
print("History probability=", history[:, 2])
print("Final criteria: C2=%f, PhiP=%f" % (result.getC2(), result.getPhiP()))

# Criteria drawing
criterionGraph = result.drawHistoryCriterion()
probaGraph = result.drawHistoryProbability()
tempGraph = result.drawHistoryTemperature()

# Linear profil
linearProfile = ot.LinearProfile(T0, iMax)

# 5) Simulated Annealing LHS with linear temperature, C2 optimization
optimalLHSAlgorithm = ot.SimulatedAnnealingLHS(lhs, spaceFillingC2, linearProfile)
print("lhs=", optimalLHSAlgorithm)
design = optimalLHSAlgorithm.generate()
print(
    "Generating design using linear temperature SimulatedAnnealing & C2 criterion =",
    design,
)
result = optimalLHSAlgorithm.getResult()
history = result.getAlgoHistory()
print("History criterion=", history[:, 0])
print("History temperature=", history[:, 1])
print("History probability=", history[:, 2])
print("Final criteria: C2=%f, PhiP=%f" % (result.getC2(), result.getPhiP()))

# Criteria drawing
criterionGraph = result.drawHistoryCriterion()
probaGraph = result.drawHistoryProbability()
tempGraph = result.drawHistoryTemperature()

# 6) Simulated Annealing LHS with linear temperature, PhiP optimization
optimalLHSAlgorithm = ot.SimulatedAnnealingLHS(lhs, spaceFillingPhiP, linearProfile)
print("lhs=", optimalLHSAlgorithm)
design = optimalLHSAlgorithm.generate()
print(
    "Generating design using linear temperature SimulatedAnnealing & PhiP criterion =",
    design,
)
result = optimalLHSAlgorithm.getResult()
history = result.getAlgoHistory()
print("History criterion=", history[:, 0])
print("History temperature=", history[:, 1])
print("History probability=", history[:, 2])
print("Final criteria: C2=%f, PhiP=%f" % (result.getC2(), result.getPhiP()))

# Criteria drawing
criterionGraph = result.drawHistoryCriterion()
probaGraph = result.drawHistoryProbability()
tempGraph = result.drawHistoryTemperature()

# 7) Simulated Annealing LHS with linear temperature, Phi optimization and nStart > 1
#  Result is a collection of LHSResult
nStart = 10
optimalDesign = optimalLHSAlgorithm.generateWithRestart(nStart)
for i in range(nStart):
    result = optimalLHSAlgorithm.getResult()
    design = result.getOptimalDesign(i)
    history = result.getAlgoHistory(i)
    print(
        "Generating design using linear temperature SimulatedAnnealing & PhiP criterion =",
        design,
    )
    print("History criterion=", history[:, 0])
    # print("History temperature=", history[:,1])
    # print("History probability=", history[:,2])
    print("Final criteria: C2=%f, PhiP=%f" % (result.getC2(i), result.getPhiP(i)))

    # decreasing criterion
    criterionGraph = result.drawHistoryCriterion(i)
    probaGraph = result.drawHistoryProbability(i)
    tempGraph = result.drawHistoryTemperature(i)
