Official .NET SDK for the globalMOO API, providing a clean and intuitive interface for mathematical optimization operations.
- .NET 6.0 or later
- A globalMOO account with valid API credentials
Create a new account on the globalMOO API dashboard to obtain your API credentials.
Add the SDK to your project using NuGet:
dotnet add package GMOO.SDK
Or via the Package Manager Console:
Install-Package GMOO.SDK
Set the GMOO_API_KEY
and GMOO_API_URI
environment variables or provide them directly when creating the client.
Initialize the Client
using GMOO.SDK;
// Load credentials from environment variables or provide directly
string apiKey = Environment.GetEnvironmentVariable("GMOO_API_KEY");
string baseUri = Environment.GetEnvironmentVariable("GMOO_API_URI");
using var client = new Client(apiKey, baseUri);
Console.WriteLine("Successfully initialized globalMOO client");
Step 1: Create a Model
// Create a model to represent your optimization problem
var model = await client.CreateModelAsync(
name: "Linear Function Example",
description: "Basic example demonstrating optimization with globalMOO"
);
Console.WriteLine($"Created model with ID: {model.Id}");
Step 2: Create a Project
// Configure the project parameters including input constraints
var project = await client.CreateProjectAsync(
modelId: model.Id,
name: "README Example Project",
inputCount: 2,
minimums: new List<double> { 0.0, 0.0 },
maximums: new List<double> { 10.0, 10.0 },
inputTypes: new List<string> { "float", "float" },
categories: new List<string>()
);
Console.WriteLine($"Created project with ID: {project.Id}");
Step 3: Get Input Cases
// Get the generated input cases for evaluation
var inputCases = project.InputCases;
Console.WriteLine($"Received {inputCases.Count} input cases");
Step 4: Compute Outputs
// Define the function that represents your system or process
/// <summary>
/// Simple 2-input, 3-output linear function for demonstration.
///
/// This function represents a "black box" system that we want to optimize.
/// In real applications, this could be a complex simulation, physical experiment,
/// or any process where we can control inputs and measure outputs.
/// </summary>
/// <param name="inputs">A list containing two float values [x, y]</param>
/// <returns>Three output values representing different linear combinations of inputs</returns>
private static List<double> LinearFunction(List<double> inputs)
{
double x = inputs[0];
double y = inputs[1];
return new List<double>
{
x + y, // Output 1: simple sum
2 * x + y, // Output 2: weighted sum
x + 2 * y // Output 3: different weighted sum
};
}
// Compute outputs for each input case
var outputCases = new List<List<double>>();
foreach (var singleCase in inputCases)
{
outputCases.Add(LinearFunction(singleCase));
}
Console.WriteLine($"Computed {outputCases.Count} output cases");
Step 5: Create a Trial
// Submit the output cases to create a trial
var trial = await client.LoadOutputCasesAsync(
projectId: project.Id,
outputCount: 3,
outputCases: outputCases
);
Console.WriteLine($"Successfully created trial with ID: {trial.Id}");
Step 6: Set Optimization Objectives
// Define the optimization objectives
var targetValues = new List<double> { 2.0, 3.0, 3.0 };
var objectiveTypes = Enumerable.Repeat(ObjectiveType.Percent, 3).ToList();
var minimumBounds = new List<double> { -1.0, -1.0, -1.0 };
var maximumBounds = new List<double> { 1.0, 1.0, 1.0 };
// Initialize the inverse optimization with objectives
var objective = await client.LoadObjectivesAsync(
trialId: trial.Id,
objectives: targetValues,
objectiveTypes: objectiveTypes,
initialInput: inputCases[0],
initialOutput: outputCases[0],
minimumBounds: minimumBounds,
maximumBounds: maximumBounds,
desiredL1Norm: 0.0
);
Console.WriteLine("Initialized inverse optimization");
Step 7: Run Inverse Optimization
// Run the optimization iteration loop
const int maxIterations = 10;
List<double> nextOutput = null;
Inverse inverse = null;
for (int iteration = 0; iteration < maxIterations; iteration++)
{
// Get a suggested input from the optimizer
inverse = await client.SuggestInverseAsync(objectiveId: objective.Id);
// Evaluate the suggested input with your function
nextOutput = LinearFunction(inverse.Input);
// Submit the results back to the optimizer
inverse = await client.LoadInverseOutputAsync(inverseId: inverse.Id, output: nextOutput);
// Check if optimization should stop
if (inverse.ShouldStop())
{
Console.WriteLine("Optimization stopped");
break;
}
}
┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│ Create │ │ Create │ │ Compute │ │ Set │
│ Model ├────►│ Project ├────►│ Outputs ├────►│ Objectives│
└────────────┘ └────────────┘ └────────────┘ └────────────┘
│
▼
┌────────────┐
│ Run │
│ Optimizer │
└────────────┘
Below is a complete, runnable example that demonstrates the full workflow:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using GMOO.SDK;
namespace GMOOExample
{
class Program
{
static async Task Main(string[] args)
{
try
{
// Initialize client
string apiKey = Environment.GetEnvironmentVariable("GMOO_API_KEY");
string baseUri = Environment.GetEnvironmentVariable("GMOO_API_URI");
using var client = new Client(apiKey, baseUri);
Console.WriteLine("Successfully initialized globalMOO client");
// Create a model
var model = await client.CreateModelAsync(
name: "Linear Function Example",
description: "Basic example demonstrating optimization with globalMOO"
);
Console.WriteLine($"Created model with ID: {model.Id}");
// Create a project
var project = await client.CreateProjectAsync(
modelId: model.Id,
name: "README Example Project",
inputCount: 2,
minimums: new List<double> { 0.0, 0.0 },
maximums: new List<double> { 10.0, 10.0 },
inputTypes: new List<string> { "float", "float" },
categories: new List<string>()
);
Console.WriteLine($"Created project with ID: {project.Id}");
// Get input cases
var inputCases = project.InputCases;
Console.WriteLine($"Received {inputCases.Count} input cases");
// Compute outputs
var outputCases = new List<List<double>>();
foreach (var singleCase in inputCases)
{
outputCases.Add(LinearFunction(singleCase));
}
Console.WriteLine($"Computed {outputCases.Count} output cases");
// Create a trial
var trial = await client.LoadOutputCasesAsync(
projectId: project.Id,
outputCount: 3,
outputCases: outputCases
);
Console.WriteLine($"Successfully created trial with ID: {trial.Id}");
// Set optimization objectives
var targetValues = new List<double> { 2.0, 3.0, 3.0 };
var objectiveTypes = Enumerable.Repeat(ObjectiveType.Percent, 3).ToList();
var minimumBounds = new List<double> { -1.0, -1.0, -1.0 };
var maximumBounds = new List<double> { 1.0, 1.0, 1.0 };
var objective = await client.LoadObjectivesAsync(
trialId: trial.Id,
objectives: targetValues,
objectiveTypes: objectiveTypes,
initialInput: inputCases[0],
initialOutput: outputCases[0],
minimumBounds: minimumBounds,
maximumBounds: maximumBounds,
desiredL1Norm: 0.0
);
Console.WriteLine("Initialized inverse optimization");
// Run inverse optimization
const int maxIterations = 10;
List<double> nextOutput = null;
Inverse inverse = null;
for (int iteration = 0; iteration < maxIterations; iteration++)
{
inverse = await client.SuggestInverseAsync(objectiveId: objective.Id);
nextOutput = LinearFunction(inverse.Input);
inverse = await client.LoadInverseOutputAsync(inverseId: inverse.Id, output: nextOutput);
Console.WriteLine($"Iteration {iteration + 1}: Input = [{string.Join(", ", inverse.Input)}], " +
$"Output = [{string.Join(", ", nextOutput)}]");
if (inverse.ShouldStop())
{
Console.WriteLine("Optimization converged successfully");
break;
}
}
Console.WriteLine("Optimization complete!");
Console.WriteLine($"Best input found: [{string.Join(", ", inverse.Input)}]");
Console.WriteLine($"Corresponding output: [{string.Join(", ", nextOutput)}]");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
/// <summary>
/// Simple 2-input, 3-output linear function for demonstration.
///
/// This function represents a "black box" system that we want to optimize.
/// In real applications, this could be a complex simulation, physical experiment,
/// or any process where we can control inputs and measure outputs.
/// </summary>
/// <param name="inputs">A list containing two float values [x, y]</param>
/// <returns>Three output values representing different linear combinations of inputs</returns>
private static List<double> LinearFunction(List<double> inputs)
{
double x = inputs[0];
double y = inputs[1];
return new List<double>
{
x + y, // Output 1: simple sum
2 * x + y, // Output 2: weighted sum
x + 2 * y // Output 3: different weighted sum
};
}
}
}
- Full support for the globalMOO API
- Strong typing for all API operations
- Automatic serialization/deserialization
- Robust error handling
- Configurable retry policies
- Comprehensive documentation
Set environment variables for simpler credential management:
GMOO_API_KEY=your-api-key
GMOO_API_URI=https://app.globalmoo.com/api/
Then initialize the client:
var client = new Client();
The SDK will automatically check for these environment variables if you don't provide them explicitly.
Use inverse optimization to find optimal parameter values for your system:
// Configure objectives for parameter tuning
var targetValues = new List<double> { desiredOutput1, desiredOutput2, desiredOutput3 };
var objectiveTypes = new List<ObjectiveType> {
ObjectiveType.Minimize,
ObjectiveType.Target,
ObjectiveType.Maximize
};
Balance multiple competing objectives without traditional weighting schemes:
// Configure multiple objectives with different target types
var targetValues = new List<double> { 10.0, 5.0, 3.0 };
var objectiveTypes = new List<ObjectiveType> {
ObjectiveType.Maximize,
ObjectiveType.Target,
ObjectiveType.Minimize
};
// Note: No weights required - our algorithm automatically balances objectives
var objective = await client.LoadObjectivesAsync(
trialId: trial.Id,
objectives: targetValues,
objectiveTypes: objectiveTypes,
initialInput: inputCases[0],
initialOutput: outputCases[0],
// Additional constraints for the optimization process
minimumBounds: minimumBounds,
maximumBounds: maximumBounds
);
The SDK provides specific exception types to help you diagnose issues:
try
{
var client = new Client();
var model = await client.CreateModelAsync("Test Model");
}
catch (InvalidArgumentException ex)
{
// Handle validation errors in your arguments
Console.WriteLine($"Invalid input: {ex.Message}");
}
catch (InvalidRequestException ex)
{
// Handle API response errors
Console.WriteLine($"API error: {ex.Message}");
foreach (var error in ex.GetErrors())
{
Console.WriteLine($" {error["property"]}: {error["message"]}");
}
}
catch (AuthenticationException ex)
{
// Handle authentication failures
Console.WriteLine($"Authentication failed: {ex.Message}");
Console.WriteLine("Check your API key and ensure it's still valid");
}
catch (RateLimitException ex)
{
// Handle rate limiting
Console.WriteLine($"Rate limit exceeded: {ex.Message}");
Console.WriteLine($"Retry after: {ex.RetryAfter} seconds");
}
catch (Exception ex)
{
// Catch-all for unexpected errors
Console.WriteLine($"Error: {ex.Message}");
}
SDK Version | globalMOO API Version | .NET Version |
---|---|---|
1.0.x | v1 | 6.0+ |
For detailed documentation, see:
- Issues and Bugs: Report issues on our GitHub repository
- Community Support: Join our Discord community
- Email Support: Contact support@globalmoo.com for direct assistance
Additional examples can be found in the gmoo-sdk-suite.
This project is licensed under the MIT License.
Contributions are welcome! Please see our Contributing Guidelines for details.