This guide will take you from zero to your first working optimization in about 15 minutes. We'll create a simple but complete example that demonstrates the key features of globalMOO.
# Model configuration
MODEL_NAME = "My First Optimization"
INPUT_COUNT = 3
OUTPUT_COUNT = 5
MIN_VALUES = [0.0, 0.0, 0.0]
MAX_VALUES = [10.0, 10.0, 10.0]
INPUT_TYPES = [InputType.FLOAT] * INPUT_COUNT
# Create a model
model = client.execute_request(CreateModel(
name=MODEL_NAME
))
logger.info(f"Created model with ID: {model.id}")
# Create a project with input specifications
project = client.execute_request(CreateProject(
model_id=model.id,
input_count=INPUT_COUNT,
minimums=MIN_VALUES,
maximums=MAX_VALUES,
input_types=INPUT_TYPES,
categories=[] # Empty list since we have no categorical variables
))
logger.info(f"Created project with ID: {project.id}")
// Model configuration
const MODEL_NAME = "My First Optimization";
const INPUT_COUNT = 3;
const OUTPUT_COUNT = 5;
const MIN_VALUES = [0.0, 0.0, 0.0];
const MAX_VALUES = [10.0, 10.0, 10.0];
const INPUT_TYPES = Array(INPUT_COUNT).fill("float");
// Create a model
const model = await client.createModel({
name: MODEL_NAME
});
console.log(`Created model with ID: ${model.id}`);
// Create a project with input specifications
const project = await client.createProject({
modelId: model.id,
inputCount: INPUT_COUNT,
minimums: MIN_VALUES,
maximums: MAX_VALUES,
inputTypes: INPUT_TYPES,
categories: [] // Empty list since we have no categorical variables
});
console.log(`Created project with ID: ${project.id}`);
// Model configuration
$MODEL_NAME = "My First Optimization";
$INPUT_COUNT = 3;
$OUTPUT_COUNT = 5;
$MIN_VALUES = [0.0, 0.0, 0.0];
$MAX_VALUES = [10.0, 10.0, 10.0];
$INPUT_TYPES = array_fill(0, $INPUT_COUNT, "float");
// Create a model
$model = $client->createModel([
'name' => $MODEL_NAME
]);
echo "Created model with ID: {$model->id}\n";
// Create a project with input specifications
$project = $client->createProject([
'model_id' => $model->id,
'input_count' => $INPUT_COUNT,
'minimums' => $MIN_VALUES,
'maximums' => $MAX_VALUES,
'input_types' => $INPUT_TYPES,
'categories' => [] // Empty list since we have no categorical variables
]);
echo "Created project with ID: {$project->id}\n";
# Get input cases from the project
input_cases = project.input_cases
logger.info(f"Received {len(input_cases)} input cases")
# Compute outputs for each input case
output_cases = [my_function(single_case) for single_case in input_cases]
logger.info(f"Computed {len(output_cases)} output cases")
# Create trial with the computed outputs
trial = client.execute_request(LoadOutputCases(
model_id=model.id,
project_id=project.id,
output_count=OUTPUT_COUNT,
output_cases=output_cases
))
logger.info(f"Successfully created trial with ID: {trial.id}")
// Get input cases from the project
const inputCases = project.inputCases;
console.log(`Received ${inputCases.length} input cases`);
// Compute outputs for each input case
const outputCases = inputCases.map(singleCase => myFunction(singleCase));
console.log(`Computed ${outputCases.length} output cases`);
// Create trial with the computed outputs
const trial = await client.loadOutputCases({
modelId: model.id,
projectId: project.id,
outputCount: OUTPUT_COUNT,
outputCases: outputCases
});
console.log(`Successfully created trial with ID: ${trial.id}`);
// Get input cases from the project
$inputCases = $project->getInputCases();
echo "Received " . count($inputCases) . " input cases\n";
// Compute outputs for each input case
$outputCases = array_map('myFunction', $inputCases);
echo "Computed " . count($outputCases) . " output cases\n";
// Create trial with the computed outputs
$trial = $client->loadOutputCases([
'model_id' => $model->id,
'project_id' => $project->id,
'output_count' => $OUTPUT_COUNT,
'output_cases' => $outputCases
]);
echo "Successfully created trial with ID: {$trial->id}\n";
# Define our target values and how we want to achieve them
TRUTHCASE = [5.4321, 5.4321, 5.4321] # The inputs we're trying to find
objectives = my_function(TRUTHCASE) # The outputs we want to match
# Define how precise we want each objective to be
OBJECTIVE_TYPES = [ObjectiveType.PERCENT] * OUTPUT_COUNT # Use percentage-based matching
PERCENT_BELOW = [-1.0] * OUTPUT_COUNT # Allow 1% below target
PERCENT_ABOVE = [ 1.0] * OUTPUT_COUNT # Allow 1% above target
# By convention, the last entry in input_cases is the center of the search space,
# which serves as a good starting point for the optimization
initial_input = input_cases[-1]
initial_output = output_cases[-1]
# Initialize the optimization
objective = client.execute_request(LoadObjectives(
model_id=model.id,
project_id=project.id,
trial_id=trial.id,
objectives=objectives, # What outputs we want
objective_types=OBJECTIVE_TYPES, # How to match each output
initial_input=initial_input, # Where to start from
initial_output=initial_output, # Its corresponding output
minimum_bounds=PERCENT_BELOW, # How far below target is acceptable
maximum_bounds=PERCENT_ABOVE, # How far above target is acceptable
desired_l1_norm=0.0 # Required, defaults to 0.0
))
logger.info("Initialized inverse optimization")
// Define our target values and how we want to achieve them
const TRUTHCASE = [5.4321, 5.4321, 5.4321]; // The inputs we're trying to find
const objectives = myFunction(TRUTHCASE); // The outputs we want to match
// Define how precise we want each objective to be
const OBJECTIVE_TYPES = Array(OUTPUT_COUNT).fill("percent"); // Use percentage-based matching
const PERCENT_BELOW = Array(OUTPUT_COUNT).fill(-1.0); // Allow 1% below target
const PERCENT_ABOVE = Array(OUTPUT_COUNT).fill(1.0); // Allow 1% above target
// By convention, the last entry in input_cases is the center of the search space,
// which serves as a good starting point for the optimization
const initial_input = inputCases[inputCases.length - 1];
const initial_output = outputCases[outputCases.length - 1];
// Initialize the optimization
const objective = await client.loadObjectives({
modelId: model.id,
projectId: project.id,
trialId: trial.id,
objectives: objectives, // What outputs we want
objectiveTypes: OBJECTIVE_TYPES, // How to match each output
initialInput: initial_input, // Where to start from
initialOutput: initial_output, // Its corresponding output
minimumBounds: PERCENT_BELOW, // How far below target is acceptable
maximumBounds: PERCENT_ABOVE, // How far above target is acceptable
desiredL1Norm: 0.0 // Required, defaults to 0.0
});
console.log("Initialized inverse optimization");
// Define our target values and how we want to achieve them
$TRUTHCASE = [5.4321, 5.4321, 5.4321]; // The inputs we're trying to find
$objectives = myFunction($TRUTHCASE); // The outputs we want to match
// Define how precise we want each objective to be
$OBJECTIVE_TYPES = array_fill(0, $OUTPUT_COUNT, "percent"); // Use percentage-based matching
$PERCENT_BELOW = array_fill(0, $OUTPUT_COUNT, -1.0); // Allow 1% below target
$PERCENT_ABOVE = array_fill(0, $OUTPUT_COUNT, 1.0); // Allow 1% above target
// By convention, the last entry in input_cases is the center of the search space,
// which serves as a good starting point for the optimization
$initial_input = end($inputCases);
$initial_output = end($outputCases);
// Initialize the optimization
$objective = $client->loadObjectives([
'model_id' => $model->id,
'project_id' => $project->id,
'trial_id' => $trial->id,
'objectives' => $objectives, // What outputs we want
'objective_types' => $OBJECTIVE_TYPES, // How to match each output
'initial_input' => $initial_input, // Where to start from
'initial_output' => $initial_output, // Its corresponding output
'minimum_bounds' => $PERCENT_BELOW, // How far below target is acceptable
'maximum_bounds' => $PERCENT_ABOVE, // How far above target is acceptable
'desired_l1_norm' => 0.0 // Required, defaults to 0.0
]);
echo "Initialized inverse optimization\n";
# Run optimization loop
max_iterations = 10
for iteration in range(max_iterations):
# Get next suggested experiment
inverse = client.execute_request(SuggestInverse(
model_id=model.id,
project_id=project.id,
trial_id=trial.id,
objective_id=objective.id
))
logger.info(f"Iteration {iteration + 1}: Received suggestion")
# Run the experiment
next_output = my_function(inverse.input)
# Load the experimental results
inverse = client.execute_request(LoadInversedOutput(
model_id=model.id,
project_id=project.id,
trial_id=trial.id,
objective_id=objective.id,
output=next_output
))
# Log detailed results
logger.info("Current solution details:")
logger.info(f" Input: {[f'{x:.4f}' for x in inverse.input]}")
logger.info(f" Output: {[f'{x:.4f}' for x in next_output]}")
logger.info(f" Target: {[f'{x:.4f}' for x in objectives]}")
if inverse.results:
for result in inverse.results:
logger.info(f"\nObjective {result.number}:")
logger.info(f" Type: {result.type}")
logger.info(f" Error: {result.error:.6f}")
logger.info(f" Satisfied: {'✓' if result.satisfied else '✗'}")
logger.info(f" Detail: {result.detail}")
# Check if we've found a satisfactory solution
if inverse.should_stop():
if inverse.satisfied_at:
logger.info("Found satisfactory solution!")
else:
logger.info(f"Search stopped: {inverse.get_stop_reason().description()}")
break
logger.info(f"Completed iteration {iteration + 1}")
# Report final results
logger.info("\nFinal Results:")
if inverse.satisfied_at:
logger.info("Solution satisfied all objectives!")
logger.info("Satisfaction details:")
for i, (satisfied, detail) in enumerate(zip(inverse.get_satisfaction_status(), inverse.get_result_details())):
logger.info(f" Objective {i}: {'✓' if satisfied else '✗'} - {detail}")
else:
logger.info("Solution did not satisfy all objectives")
logger.info("Status per objective:")
for i, (satisfied, detail) in enumerate(zip(inverse.get_satisfaction_status(), inverse.get_result_details())):
logger.info(f" Objective {i}: {'✓' if satisfied else '✗'} - {detail}")
logger.info(f"\nFinal solution:")
logger.info(f" Input values: {[f'{x:.4f}' for x in inverse.input]}")
logger.info(f" Output values: {[f'{x:.4f}' for x in next_output]}")
logger.info(f" Target values: {[f'{x:.4f}' for x in objectives]}")
logger.info(f" Error values: {[f'{e:.6f}' for e in inverse.get_objective_errors()]}")
# Don't forget to close the client
client.http_client.close()
logger.info("Closed client connection")