예제 #1
0
    def __init__(self,
                 opt_prob: problem.OptimizationProblem,
                 logger: workspace.Logger,
                 optimizer: str = "L-BFGS",
                 monitor_lists: Optional[
                     optplan.ScipyOptimizerMonitorList] = None,
                 optimization_options: Optional[Dict] = None) -> None:
        """Initializes transformation for `PenaltyOptimizer`.

        This transformation solves an optimization problem using the
        `PenaltyOptimizer` which solves a constrained optimization problem
        by adding a L1 norm penalty function. For example, the problem

        minimize f(x)
        subject to h(x) = 0

        is solved by minimizing `f(x) + mu |h(x)|` for successively larger
        values of `mu`.

        Args:
            opt_prob: Optimization problem to solve.
            logger: Logger to use.
            optimizer: Name of scipy optimizer to use, e.g. 'L-BFGS'. Should be
                one of those defined for `scipy.optimize`.
            monitor_lists: List of monitors to log.
            optimization_options: Dictionary specifying additional optimizations
                as defined in the scipy documentation. For example, to specify
                maximum iterations for 'L-BFGS', `optimization_options` should
                be set to `{"maxiter": 10}`.
        """
        self._opt_prob = opt_prob
        self.optimizer = optimizer
        if optimization_options is None:
            optimization_options = {}
        else:
            for key, value in optimization_options.items():
                if not value:
                    del optimization_options[key]
        self.optimization_options = optimization_options
        self.monitor_lists = monitor_lists
        if not self.monitor_lists:
            self.monitor_lists = optplan.ScipyOptimizerMonitorList()
        self.logger = logger
예제 #2
0
    def __init__(self,
                 opt_prob: problem.OptimizationProblem,
                 logger: workspace.Logger,
                 optimizer: str = "L-BFGS",
                 monitor_lists: Optional[
                     optplan.ScipyOptimizerMonitorList] = None,
                 optimization_options: Optional[Dict] = None) -> None:
        """Initializes transformation for running optimization with scipy.

        This transformation solves an optimization problem using a scipy
        optimizer.

        Args:
            opt_prob: Optimization problem to solve.
            logger: Logger to use.
            optimizer: Name of scipy optimizer to use, e.g. 'L-BFGS'. Should be
                one of those defined for `scipy.optimize`.
            monitor_lists: List of monitors to log.
            optimization_options: Dictionary specifying additional optimizations
                as defined in the scipy documentation. For example, to specify
                maximum iterations for 'L-BFGS', `optimization_options` should
                be set to `{"maxiter": 10}`.
        """
        self._opt_prob = opt_prob
        self.optimizer = optimizer
        if optimization_options is None:
            optimization_options = {}
        else:
            for key, value in optimization_options.items():
                if not value:
                    del optimization_options[key]
        self.optimization_options = optimization_options
        self.monitor_lists = monitor_lists
        if not self.monitor_lists:
            self.monitor_lists = optplan.ScipyOptimizerMonitorList()
        self.logger = logger
예제 #3
0
파일: grating.py 프로젝트: shanham/spins-b
def create_transformations(
        obj: optplan.Function,
        monitors: List[optplan.Monitor],
        cont_iters: int,
        disc_iters: int,
        sim_space: optplan.SimulationSpaceBase,
        min_feature: float = 100,
        cont_to_disc_factor: float = 1.1,
) -> List[optplan.Transformation]:
    """Creates a list of transformations for the optimization.

    The grating coupler optimization proceeds as follows:
    1) Continuous optimization whereby each pixel can vary between device and
       background permittivity.
    2) Discretization whereby the continuous pixel parametrization is
       transformed into a discrete grating (Note that L2D is implemented here).
    3) Further optimization of the discrete grating by moving the grating
       edges.

    Args:
        opt: The objective function to minimize.
        monitors: List of monitors to keep track of.
        cont_iters: Number of iterations to run in continuous optimization.
        disc_iters: Number of iterations to run in discrete optimization.
        sim_space: Simulation space ot use.
        min_feature: Minimum feature size in nanometers.
        cont_to_disc_factor: Discretize the continuous grating with feature size
            constraint of `min_feature * cont_to_disc_factor`.
            `cont_to_disc_factor > 1` gives discrete optimization more wiggle
            room.

    Returns:
        A list of transformations.
    """
    # Setup empty transformation list.
    trans_list = []

    # First do continuous relaxation optimization.
    cont_param = optplan.PixelParametrization(
        simulation_space=sim_space,
        init_method=optplan.UniformInitializer(min_val=0, max_val=1))
    trans_list.append(
        optplan.Transformation(
            name="opt_cont",
            parametrization=cont_param,
            transformation=optplan.ScipyOptimizerTransformation(
                optimizer="L-BFGS-B",
                objective=obj,
                monitor_lists=optplan.ScipyOptimizerMonitorList(
                    callback_monitors=monitors,
                    start_monitors=monitors,
                    end_monitors=monitors),
                optimization_options=optplan.ScipyOptimizerOptions(
                    maxiter=cont_iters),
            ),
        ))

    # Discretize. Note we add a little bit of wiggle room by discretizing with
    # a slightly larger feature size that what our target is (by factor of
    # `cont_to_disc_factor`). This is to give the optimization a bit more wiggle
    # room later on.
    disc_param = optplan.GratingParametrization(
        simulation_space=sim_space, inverted=True)
    trans_list.append(
        optplan.Transformation(
            name="cont_to_disc",
            parametrization=disc_param,
            transformation=optplan.GratingEdgeFitTransformation(
                parametrization=cont_param,
                min_feature=cont_to_disc_factor * min_feature)))

    # Discrete optimization.
    trans_list.append(
        optplan.Transformation(
            name="opt_disc",
            parametrization=disc_param,
            transformation=optplan.ScipyOptimizerTransformation(
                optimizer="SLSQP",
                objective=obj,
                constraints_ineq=[
                    optplan.GratingFeatureConstraint(
                        min_feature_size=min_feature,
                        simulation_space=sim_space,
                        boundary_constraint_scale=1.0,
                    )
                ],
                monitor_lists=optplan.ScipyOptimizerMonitorList(
                    callback_monitors=monitors,
                    start_monitors=monitors,
                    end_monitors=monitors),
                optimization_options=optplan.ScipyOptimizerOptions(
                    maxiter=disc_iters),
            ),
        ))
    return trans_list
예제 #4
0
def create_transformations(
    obj: optplan.Function,
    monitors: List[optplan.Monitor],
    sim_space: optplan.SimulationSpaceBase,
    cont_iters: int,  # require more to optimise power better
    num_stages: int = 3,
    min_feature: float = 100,
) -> List[optplan.Transformation]:
    """Creates a list of transformations for the device optimization.

    The transformations dictate the sequence of steps used to optimize the
    device. The optimization uses `num_stages` of continuous optimization. For
    each stage, the "discreteness" of the structure is increased (through
    controlling a parameter of a sigmoid function).

    Args:
        opt: The objective function to minimize.
        monitors: List of monitors to keep track of.
        sim_space: Simulation space ot use.
        cont_iters: Number of iterations to run in continuous optimization
            total across all stages.
        num_stages: Number of continuous stages to run. The more stages that
            are run, the more discrete the structure will become.
        min_feature: Minimum feature size in nanometers.

    Returns:
        A list of transformations.
    """
    # Setup empty transformation list.
    trans_list = []

    # First do continuous relaxation optimization.
    # This is done through cubic interpolation and then applying a sigmoid
    # function.
    param = optplan.CubicParametrization(
        # Specify the coarseness of the cubic interpolation points in terms
        # of number of Yee cells. Feature size is approximated by having
        # control points on the order of `min_feature / GRID_SPACING`.
        undersample=3.5 * min_feature / GRID_SPACING,
        simulation_space=sim_space,
        init_method=optplan.UniformInitializer(min_val=0.6, max_val=0.9),
    )

    iters = max(cont_iters // num_stages, 1)
    for stage in range(num_stages):
        trans_list.append(
            optplan.Transformation(
                name="opt_cont{}".format(stage),
                parametrization=param,
                transformation=optplan.ScipyOptimizerTransformation(
                    optimizer="L-BFGS-B",
                    objective=obj,
                    monitor_lists=optplan.ScipyOptimizerMonitorList(
                        callback_monitors=monitors,
                        start_monitors=monitors,
                        end_monitors=monitors),
                    optimization_options=optplan.ScipyOptimizerOptions(
                        maxiter=iters),
                ),
            ))

        if stage < num_stages - 1:
            # Make the structure more discrete.
            trans_list.append(
                optplan.Transformation(
                    name="sigmoid_change{}".format(stage),
                    parametrization=param,
                    # The larger the sigmoid strength value, the more "discrete"
                    # structure will be.
                    transformation=optplan.CubicParamSigmoidStrength(
                        value=4 * (stage + 1)),
                ))
    return trans_list
예제 #5
0
def create_transformations(
    obj: optplan.Function,
    monitors: List[optplan.Monitor],
    sim_space: optplan.SimulationSpaceBase,
    cont_iters: int,
    num_stages: int = 3,
    min_feature: float = 100,
) -> List[optplan.Transformation]:
    """Creates a list of transformations for the device optimization.

    The transformations dictate the sequence of steps used to optimize the
    device. The optimization uses `num_stages` of continuous optimization. For
    each stage, the "discreteness" of the structure is increased (through
    controlling a parameter of a sigmoid function).

    Args:
        obj: The objective function to minimize.
        monitors: List of monitors to keep track of.
        sim_space: Simulation space ot use.
        cont_iters: Number of iterations to run in continuous optimization
            total across all stages.
        num_stages: Number of continuous stages to run. The more stages that
            are run, the more discrete the structure will become.
        min_feature: Minimum feature size in nanometers.
        fab_obj: Objective including fabrication penalties to be used in the
            second half of the optimization

    Returns:
        A list of transformations.
    """
    # Setup empty transformation list.
    trans_list = []

    # First do continuous relaxation optimization.
    # This is done through cubic interpolation and then applying a sigmoid
    # function.
    param = optplan.CubicParametrization(
        # Specify the coarseness of the cubic interpolation points in terms
        # of number of Yee cells. Feature size is approximated by having
        # control points on the order of `min_feature / GRID_SPACING`.
        undersample=3.5 * min_feature / GRID_SPACING,
        simulation_space=sim_space,
        init_method=optplan.WaveguideInitializer3(lower_min=0,
                                                  lower_max=.2,
                                                  upper_min=.7,
                                                  upper_max=1,
                                                  extent_frac_x=1,
                                                  extent_frac_y=1 / 2,
                                                  center_frac_x=1 / 2,
                                                  center_frac_y=1 / 2),
        # init_method=optplan.GradientInitializer(min=0, max=1, random=0.3, extent_frac_x=1, extent_frac_y=0.4,
        #                                         center_frac_x=0.5, center_frac_y=0.55)
        # init_method=optplan.UniformInitializer(min_val=0, max_val=0)
        # init_method=optplan.PeriodicInitializer(random=0.2, min=0, max=1, period=400, sim_width=6000,
        #                                         center_frac_y=0.5, extent_frac_y=0.4)
    )

    trans_list.append(
        optplan.Transformation(
            name="sigmoid_change_init",
            parametrization=param,
            # The larger the sigmoid strength value, the more "discrete"
            # structure will be.
            transformation=optplan.CubicParamSigmoidStrength(value=4, )))

    iters = max(cont_iters // num_stages, 1)
    for stage in range(num_stages):
        trans_list.append(
            optplan.Transformation(
                name="opt_cont{}".format(stage),
                parametrization=param,
                transformation=optplan.ScipyOptimizerTransformation(
                    optimizer="L-BFGS-B",
                    objective=obj,
                    monitor_lists=optplan.ScipyOptimizerMonitorList(
                        callback_monitors=monitors,
                        start_monitors=monitors,
                        end_monitors=monitors),
                    optimization_options=optplan.ScipyOptimizerOptions(
                        maxiter=iters),
                ),
            ))

        if stage < num_stages - 1:
            # Make the structure more discrete.
            trans_list.append(
                optplan.Transformation(
                    name="sigmoid_change{}".format(stage),
                    parametrization=param,
                    # The larger the sigmoid strength value, the more "discrete"
                    # structure will be.
                    transformation=optplan.CubicParamSigmoidStrength(
                        value=2 * (stage + 3)),
                ))
    return trans_list