/*******************************************************************************
* Copyright 2014 Analog Devices, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
********************************************************************************/
/**
* Extended Statically typed hierarchical option support for Dimple.
* <p>
* This package extends the core option functionality provided by the {@link com.analog.lyric.options} package
* for use with Dimple.
*
* <h2>Option definitions</h2>
* <p>
* Most Dimple option keys are declared in classes specifically created for that purpose and that are
* descended from the base class {@linkplain com.analog.lyric.dimple.options.DimpleOptions DimpleOptions}.
* This allows developers to browse most options by exploring the class hierarchy rooted at the class
* using their IDE. For instance, in Eclipse pressing Ctrl+Shift+H and typing "DimpleOptions" in the dialog
* box will display the Type Hierarchy view. Some options are defined directly in the class that uses them.
* This is the case with options that configure {@linkplain com.analog.lyric.dimple.solvers.core.proposalKernels
* proposal kernels} and {@linkplain com.analog.lyric.dimple.solvers.gibbs.samplers.generic generic samplers}
* for the Gibbs solver. You can see an enumeration of the classes that define options in the documentation
* for the {@link com.analog.lyric.dimple.options.DimpleOptionRegistry DimpleOptionRegistry}.
* <p>
* Most options are solver specific and can be found in the corresponding options declaration class for that solver.
* For instance, most options affecting the configuration of the Gibbs solver can be found in
* {@link com.analog.lyric.dimple.solvers.gibbs.GibbsOptions GibbsOptions}.
*
* <h2>Option lookup</h2>
* <p>
* The {@linkplain com.analog.lyric.dimple.options.DimpleOptionHolder DimpleOptionHolder} class extends
* the core {@linkplain com.analog.lyric.options.LocalOptionHolder LocalOptionHolder} implementation to use a more
* complex option lookup strategy than
* the default one, which simply iterates over the
* {@linkplain com.analog.lyric.options.IOptionHolder#getOptionParent option parent} chain.
* Instead Dimple solver objects will look for options set on the corresponding model object before recursing
* to look at the option parent. This allows users to set options on model factors and variables that will
* take effect on their corresponding solver variables and have those options take priority over those set
* on the solver graph or model graph. Users may set solver options directly on solver variables or factors that will
* take precedence over those set on the model, but that will rarely be needed.
* <p>
* {@linkplain com.analog.lyric.dimple.model.core.FactorGraph FactorGraph} objects that are not subgraphs of
* another graph will return their {@linkplain com.analog.lyric.dimple.environment.DimpleEnvironment DimpleEnvironment}
* as their {@linkplain com.analog.lyric.options.IOptionHolder#getOptionParent option parent}, consequently the
* environment object will serve as the root object in the option hierarchy and can be used to set default values
* for options to be shared across all graphs in the environment.
* <p>
* The exact lookup iteration algorithm is described in more detail in
* {@linkplain com.analog.lyric.dimple.events.EventSourceIterator EventSourceIterator}, but can
* be summarized succinctly considering how an option value for a solver variable is found. In that case, the following
* objects are examined in order until one is found that contains a local setting for that option:
* <ol>
* <li>The solver variable itself
* <li>The corresponding model variable
* <li>The solver factor graph that immediately contains the solver variable
* <li>The corresponding model factor graph that contains the model variable
* <li>If the graph has a parent graph, the solver parent graph will be looked at followed by the model parent
* graph and so on recursively until there are no more parent graphs
* <li>Finally, the environment object of the root model graph will be examined.
* </ol>
* If the option is not set anywhere in the hierarchy, then most code that depends on options will use
* the {@linkplain com.analog.lyric.options.IOptionKey#defaultValue default value} defined by the key, but
* there are some exceptions
* (e.g. {@linkplain com.analog.lyric.dimple.options.DimpleOptions#randomSeed DimpleOptions.randomSeed}).
*
* <h2>Examples</h2>
* <p>
* Here is a toy example that illustrates several common usage patterns for options in Dimple.
* <p>
* Start with the following simple model consisting of a square of discrete variables connected by some
* arbitrary factors:
* <p>
* <blockquote>
* <pre>
* //
* // (d1)---[f12]---(d2)
* // | |
* // [f13] [f24]
* // | |
* // (d3)---[f34]---(d4)
* //
* FactorGraph fg = FactorGraph();
* DiscreteDomain digit = DiscreteDomain.range(0,9);
* Discrete d1 = new Discrete(digit), d2 = new Discrete(digit);
* Discrete d3 = new Discrete(digit), d4 = new Discrete(digit);
* Factor f12 = fg.addFactor(new HorizontalFactor(<em>horizontalArgs</em>), d1, d2);
* Factor f34 = fg.addFactor(new HorizontalFactor(<em>horizontalArgs</em>), d3, d4);
* Factor f13 = fg.addFactor(new VerticalFactor(<em>verticalArgs</em>), d1, d3);
* Factor f24 = fg.addFactor(new VerticalFactor(<em>verticalArgs</em>), d2, d4);
* </pre>
* </blockquote>
* <p>
* If we were to use the min-sum solver on this model, we might want to enable damping
* and specify the number of iterations to run. This can be done by setting options on the
* model graph object:
* <blockquote>
* <pre>
* fg.setOption(BPOptions.damping, .9);
* fg.setOption(SolverOptions.iterations, 20);
* </pre>
* </blockquote>
* Later, when a solver is created for the graph, it and its component objects will inherit these settings:
* <blockquote>
* <pre>
* MinSumSolverGraph minSumGraph = fg.setSolverFactory(new MinSumSolver());
* assert(minSumGraph.getOption(SolverOptions.iterations) == 20);
* ISolverVariable sd1 = minSumGraph.getSolverVariable(d1);
* assert(sd1.getOption(BPOptions.damping) == .9);
* </pre>
* </blockquote>
* If you find you need to override the damping value for a particular variable or factor, you
* can set it on the model object:
* <blockquote>
* <pre>
* d1.setOption(BPOptions.damping, .7);
* </pre>
* </blockquote>
* You may also set options directly on solver objects as well, but that is usually less convenient
* and should rarely be necessary:
* <blockquote>
* <pre>
* sd1.setOption(BPOptions.damping, .7);
* </pre>
* </blockquote>
* The {@linkplain com.analog.lyric.options.IOptionHolder#setOption setOption} method only accepts a single
* value of the appropriate type for the option. For some types of options, it can be slightly easier to set
* the option using methods on the option key object itself. For instance, when setting options that have
* list values, the key usually has a {@code set} method that takes multiple values:
* <blockquote>
* <pre>
* // These two statements are equivalent:
* d1.setOption(BPOptions.nodeSpecificDamping, new OptionDoubleList(.7, .8));
* BPOptions.nodeSpecificDamping.set(d1, .7, .8);
* </pre>
* </blockquote>
* <p>
* @since 0.07
* @author Christopher Barber
*/
@org.eclipse.jdt.annotation.NonNullByDefault
package com.analog.lyric.dimple.options;