private static TRes CreateCore <TRes>(
            IHostEnvironment env,
            Type factoryType,
            Type signatureType,
            string settings,
            out string loadName,
            params object[] extraArgs)
            where TRes : class
        {
            Contracts.AssertValue(env);
            env.AssertValue(factoryType);
            env.AssertValue(signatureType);
            env.AssertValue(settings, "settings");

            var factory = CmdParser.CreateComponentFactory(factoryType, signatureType, settings);

            loadName = factory.Name;
            return(ComponentCatalog.CreateInstance <TRes>(env, factory.SignatureType, factory.Name, factory.GetSettingsString(), extraArgs));
        }
        public NelderMeadSweeper(IHostEnvironment env, Arguments args)
        {
            Contracts.CheckValue(env, nameof(env));
            env.CheckUserArg(-1 < args.DeltaInsideContraction, nameof(args.DeltaInsideContraction), "Must be greater than -1");
            env.CheckUserArg(args.DeltaInsideContraction < 0, nameof(args.DeltaInsideContraction), "Must be less than 0");
            env.CheckUserArg(0 < args.DeltaOutsideContraction, nameof(args.DeltaOutsideContraction), "Must be greater than 0");
            env.CheckUserArg(args.DeltaReflection > args.DeltaOutsideContraction, nameof(args.DeltaReflection), "Must be greater than " + nameof(args.DeltaOutsideContraction));
            env.CheckUserArg(args.DeltaExpansion > args.DeltaReflection, nameof(args.DeltaExpansion), "Must be greater than " + nameof(args.DeltaReflection));
            env.CheckUserArg(0 < args.GammaShrink && args.GammaShrink < 1, nameof(args.GammaShrink), "Must be between 0 and 1");

            _args = args;

            _sweepParameters = new List <IValueGenerator>();
            foreach (var sweptParameter in args.SweptParameters)
            {
                var parameter = ComponentCatalog.CreateInstance <IValueGenerator, SignatureSweeperParameter>(env, sweptParameter);
                // REVIEW: ideas about how to support discrete values:
                // 1. assign each discrete value a random number (1-n) to make mirroring possible
                // 2. each time we need to mirror a discrete value, sample from the remaining value
                // 2.1. make the sampling non-uniform by learning "weights" for the different discrete values based on
                // the metric values that we get when using them. (E.g. if, for a given discrete value, we get a bad result,
                // we lower its weight, but if we get a good result we increase its weight).
                var parameterNumeric = parameter as INumericValueGenerator;
                env.CheckUserArg(parameterNumeric != null, nameof(args.SweptParameters), "Nelder-Mead sweeper can only sweep over numeric parameters");
                _sweepParameters.Add(parameterNumeric);
            }

            _initSweeper = args.FirstBatchSweeper.CreateInstance(env, new object[] { _sweepParameters.ToArray() });
            _dim         = _sweepParameters.Count;
            env.CheckUserArg(_dim > 1, nameof(args.SweptParameters), "Nelder-Mead sweeper needs at least two parameters to sweep over.");

            _simplexVertices           = new SortedList <IRunResult, Float[]>(new SimplexVertexComparer());
            _stage                     = OptimizationStage.NeedReflectionPoint;
            _pendingSweeps             = new List <KeyValuePair <ParameterSet, Float[]> >();
            _pendingSweepsNotSubmitted = new Queue <KeyValuePair <ParameterSet, Float[]> >();
        }