Documentation

This page hosts the documentation of the SmartCGMS software architecture and all of its components.

The documentation is being updated to acommodate the recent improvements. Please, be patient, we are working on it...


Optimizing the parameters

Once you have the configuration saved in a file, you can use either the console or GUI application to optimize it. The console application is intended for batch processing, to execute the experimental setups with no user input while conserving system resources.

With the GUI application, you will have to load, optimize and possibly save the configuration (with the optimized parameters) manually for each configuration. Hence, it is useful when you experiment with different optimizing solvers and their settings.

Optimizer calls

The SmartCGMS SDK offers a wrapper functions around the scgms library exports, allowing you to perform parameter optimalization in a single function call. There are two functions (exported and wrapped), which you can call to optimize the parameters:

  • scgms::Optimize_Parameters - this function optimizes parameters of a single filter (and its encapsulated model) and stores the result in the given configuration (modifies the contents)
  • scgms::Optimize_Multiple_Parameters - same as above, but for multiple filters (and their encapsulated models); this is convenient if a coupled optimalization is desired (e.g. the parameters of one model depends on parameters of another model)
The function parameters for scgms::Optimize_Parameters are as follows:
  1. configuration (scgms::SFilter_Chain_Configuration)
  2. optimized filter index (size_t)
  3. optimized parameters configuration name (wchar_t*)
  4. filter creation callback (scgms::TOn_Filter_Created)
  5. data-type-agnostic pointer (void*) to a data, passed as a parameter to the filter creation callback function
  6. GUID of a solver to be used for optimalization
  7. population size (size_t)
  8. maximum generations count (size_t)
  9. array of parameter hints (double**) - if there are none, pass the nullptr value and set the following parameter to zero
  10. size of hints array (size_t)
  11. progress container reference (solver::TSolver_Progress), see below for details
  12. error list (refcnt::Swstr_list)
The scgms::Optimize_Multiple_Parameters changes the parameters 2 and 3 to arrays, and adds an additional parameter for filter count:
  1. an array of filter indices (size_t*)
  2. an array of parameters configuration names (wchar_t**)
  3. optimized filter count (size_t), i.e. a size of these arrays

Eventually, both optimizing functions call a generic function with C-interface. Hence, SmartCGMS can act as a general-purpose solver. Depending on library configuration, SmartCGMS can use the NLOpt and PaGMO optimization libraries. Note the scgms::TGeneric_Solver function prototype to explore this functionality.

The call itself is blocking, and therefore, you may want to start it in another thread. To monitor the solver progress, the interface introduces the solver::TSolver_Progress container. The contents of this container are further described in the solver API page.

Example

In the execution chapter, you've learned how to load and execute SmartCGMS configuration. If you would like to optimize the parameters, let us refer to the following example.

refcnt::Swstr_list errors;
solver::TSolver_Progress progress = solver::Null_Solver_Progress;
    
HRESULT rc = E_FAIL;
std::atomic<bool> optimizing_flag{ true };
std::thread optimitizing_thread([&] {
    //use thread, not async because that could live-lock on a uniprocessor

    rc = scgms::Optimize_Parameters(configuration,
        optimize_filter_index,
        parameters_name.c_str(),
        nullptr,
        nullptr,

        solver_id, population_size, generation_count,

        hints_ptr.data(), hints_ptr.size(),
        progress,
        errors);

    optimizing_flag = false;
});
  
while (optimizing_flag) {
    report_progress(progress);
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
}

if (optimitizing_thread.joinable())
    optimitizing_thread.join();

errors.for_each([](auto str) {
    std::wcerr << str << std::endl;
});

if (rc == S_OK) {
    //all went ok
} else {
    //something went wrong or did not succeed/improve (S_FALSE then)
}

Please, also note that the filter creation callback rules, mentioned in the execution page applies to the optimizer calls as well. Therefore, if database access is desired, pass the Setup_Filter_DB_Access as a third parameter.