Getting Started with globalMOO

Welcome to the globalMOO API documentation. This guide will help you get started with using our API and SDKs.

Overview

globalMOO provides a powerful API for multi-objective optimization. With our API, you can:

  • Create and manage optimization models

  • Define objectives and constraints

  • Run optimization trials

  • Analyze results

Installation

Choose your preferred SDK:

pip install globalmoo-sdk

Quick Start

Here's a simple example to get you started:

"""
Example showing optimization of a simple linear system of equations.

This example demonstrates how to use globalMOO to find inputs that produce 
specific outputs in a 3-input, 5-output linear system. It illustrates:

1. Setting up a model with proper input and output specifications
2. Creating a project with appropriate boundaries
3. Using percentage-based objectives for optimization
4. Running the inverse optimization process with customizable convergence criteria
5. Interpreting optimization results and solution quality

Linear systems are ideal for demonstrating globalMOO's capabilities since
they have clear mathematical relationships between inputs and outputs,
making it easier to understand the optimization process.
"""
from typing import List
from dotenv import load_dotenv

from globalmoo.client import Client
from globalmoo.request.create_model import CreateModel
from globalmoo.request.create_project import CreateProject
from globalmoo.request.load_output_cases import LoadOutputCases
from globalmoo.request.load_objectives import LoadObjectives
from globalmoo.request.suggest_inverse import SuggestInverse
from globalmoo.request.load_inversed_output import LoadInversedOutput
from globalmoo.enums.input_type import InputType
from globalmoo.enums.objective_type import ObjectiveType
from globalmoo.utils.console import (
    print_satisfaction_status,
    print_section_header,
    print_values,
    print_info,
    print_success
)

def LinearTestFunction(input: List[float]) -> List[float]:
    """
    Simple linear problem with 3 inputs and 5 outputs.
    
    This function defines a system of linear equations where each output
    is a linear combination of the inputs with different coefficients.
    
    In real applications, this could represent:
    - Chemical processes where reactant concentrations affect multiple product yields
    - Financial models where investment allocations affect multiple performance metrics
    - Engineering systems where control parameters affect multiple performance indicators
    
    Args:
        input (List[float]): List of 3 input values [v01, v02, v03]
        
    Returns:
        List[float]: List of 5 output values representing different linear combinations
    """
    v01 = input[0]
    v02 = input[1]
    v03 = input[2]
    
    # Each output is a distinct linear combination of inputs
    # The coefficients represent different sensitivities to each input
    o01 = 1.25 * v01 + 2.0 * v02 + 2.75 * v03
    o02 = 1.19 * (v01 - 2.0) + 0.71 * (v02 - 2.0) + 0.51 * v03
    o03 = 1.11 * (v01 - 2.0) + 0.65 * v02 + 0.56 * (v03 - 2.0)
    o04 = 1.02 * v01 + 0.49 * (v02 - 2.0) + 0.62 * (v03 - 2.0)
    o05 = 3.0 * v01 + 2.0 * v02 + 1.0 * v03
    return [o01, o02, o03, o04, o05]

def main():
    # Load environment variables
    load_dotenv()

    # Model configuration - matching SimpleExample
    # These constants define the characteristics of our optimization problem
    MODEL_NAME = "SimpleExample"
    INPUT_COUNT = 3                                  # Number of input variables
    OUTPUT_COUNT = 5                                 # Number of output variables
    MIN_VALUES = [0.0, 0.0, 0.0]                     # Lower bounds for inputs
    MAX_VALUES = [10.0, 10.0, 10.0]                  # Upper bounds for inputs
    INPUT_TYPES = [InputType.FLOAT, InputType.FLOAT, InputType.FLOAT]  # All inputs are floating-point
    
    # Convergence criteria - how close we need to be to the target
    # These define when the optimization is considered successful
    PERCENT_BELOW = [-1.0, -1.0, -1.0, -1.0, -1.0]  # Allow 1% below target
    PERCENT_ABOVE = [ 1.0,  1.0,  1.0,  1.0,  1.0]  # Allow 1% above target

    # "Truth case" - the target input values we're trying to find
    # In real applications, you would only know the desired outputs, not the inputs
    TRUTHCASE = [5.4321, 5.4321, 5.4321]
    
    # Calculate the target outputs from our truth case
    # These are the output values we'll try to achieve through optimization
    objectives = LinearTestFunction(TRUTHCASE)

    # All objectives use percentage-based convergence criteria
    OBJECTIVE_TYPES = [ObjectiveType.PERCENT] * OUTPUT_COUNT
    
    # Define the starting point for your inverse solution process
    # This is where the optimization algorithm will begin searching
    INITIAL_INPUT = [5.0, 5.0, 5.0]
    INITIAL_OUTPUT = LinearTestFunction(INITIAL_INPUT)
    
    try:
        # Initialize the client
        client = Client()
        print(client)
        print_info("Successfully initialized globalMOO client")

        # STEP 1: Create a model
        # Models are the top-level containers for your optimization data
        model = client.execute_request(CreateModel(
            name=MODEL_NAME,
            description="Demonstration of optimization for a simple linear system of equations"
        ))
        print_info(f"Created model with ID: {model.id}")

        # STEP 2: Create a project for the model
        # Projects define the input and output characteristics
        project = client.execute_request(CreateProject(
            model_id=model.id,
            name="Linear Model Project",
            input_count=INPUT_COUNT,
            minimums=MIN_VALUES,
            maximums=MAX_VALUES,
            input_types=INPUT_TYPES,
            categories=[] # Set to empty list, no categorical variables
        ))
        print_info(f"Created project with ID: {project.id}")

        # Get input cases from the project
        # globalMOO generates test points to explore the input space
        input_cases = project.input_cases
        print_info(f"Received {len(input_cases)} input cases")

        # STEP 3: Run inputs locally to compute outputs
        # In real applications, this might involve running simulations or experiments
        output_cases = [LinearTestFunction(single_case) for single_case in input_cases]
        print_info(f"Computed {len(output_cases)} output cases")
        
        # STEP 4: Create trial by loading the output cases
        # A trial represents a set of evaluations of your model
        trial = client.execute_request(LoadOutputCases(
            project_id=project.id,
            output_count=OUTPUT_COUNT,
            output_cases=output_cases
        ))
        print_info(f"Successfully created trial with ID: {trial.id}")

        # STEP 5: Initialize inverse with values matching SimpleExample
        # This defines what outputs we're trying to achieve and how close we need to be
        objective = client.execute_request(LoadObjectives(
            trial_id=trial.id,
            objectives=objectives,              # Target output values
            objective_types=OBJECTIVE_TYPES,    # Type of objective for each output
            initial_input=INITIAL_INPUT,        # Starting point for optimization
            initial_output=INITIAL_OUTPUT,      # Output at starting point
            minimum_bounds=PERCENT_BELOW,       # Lower acceptable bounds
            maximum_bounds=PERCENT_ABOVE,       # Upper acceptable bounds
            desired_l1_norm=0.0                 # Target error (0 = perfect match)
        ))
        print_info("Initialized inverse optimization")

        # STEP 6: Run optimization loop
        # This is where globalMOO iteratively suggests new inputs to try
        max_iterations = 20

        for iteration in range(max_iterations):
            # Get next suggested experiment
            inverse = client.execute_request(SuggestInverse(
                objective_id=objective.id
            ))
            print_info(f"Iteration {iteration + 1}: Received suggestion")
            
            # Run the experiment (our test function)
            # In real applications, this would be your experiment or simulation
            next_output = LinearTestFunction(inverse.input)
            
            # Load the experimental results
            # This helps globalMOO improve its next suggestion
            inverse = client.execute_request(LoadInversedOutput(
                inverse_id=inverse.id,
                output=next_output
            ))

            # Log detailed results with nice formatting
            print_section_header("Current solution details:")
            print_values("Input", inverse.input)
            print_values("Output", next_output)
            print_values("Target", objective.objectives)
            
            if inverse.results:
                for i, result in enumerate(inverse.results):
                    print_satisfaction_status(i, result.satisfied, result.detail)
                    print_info(f"    Type: {result.objective_type}")
                    print_info(f"    Error: {result.error}")

            # Check if we need to stop
            # globalMOO will indicate when it has found a satisfactory solution
            if inverse.should_stop():
                print_info(f"Optimization stopped: {inverse.get_stop_reason().description()}")
                break

            print_info(f"Completed iteration {iteration + 1}")

        # STEP 7: Report final results
        print_section_header("Final Results")
        if inverse.satisfied_at:
            print_success("Solution satisfied all objectives!")
            print_section_header("Satisfaction details:")
            for i, (satisfied, detail) in enumerate(zip(inverse.get_satisfaction_status(), inverse.get_result_details())):
                print_satisfaction_status(i, satisfied, detail)
        else:
            print_info("Solution did not satisfy all objectives")
            print_section_header("Status per objective:")
            for i, (satisfied, detail) in enumerate(zip(inverse.get_satisfaction_status(), inverse.get_result_details())):
                print_satisfaction_status(i, satisfied, detail)

        print_section_header("Final solution:")
        print_values("Input values", inverse.input)
        print_values("Output values", next_output)
        print_values("Target values", objective.objectives)
        print_values("Error values", inverse.get_objective_errors(), precision=6)

    finally:
        # Clean up resources
        if 'client' in locals():
            client.http_client.close()
            print_info("Closed client connection")

if __name__ == "__main__":
    main()

Interactive Tutorial

Try globalMOO directly in your browser with our interactive Google Colab notebook:

This notebook walks through a complete example of using globalMOO to optimize a simple linear system.

Next Steps

  1. Learn about Authentication

  2. Explore our Core Concepts

  3. Check out the Quickstart Guide

Last updated