def apply_same_chip_constraints(vertices_resources, nets, constraints):
    """Modify a set of vertices_resources, nets and constraints to account for
    all SameChipConstraints.

    To allow placement algorithms to handle SameChipConstraints without any
    special cases, Vertices identified in a SameChipConstraint are merged into
    a new vertex whose vertices_resources are the sum total of their parts
    which may be placed as if a single vertex. Once placed, the placement can
    be expanded into a full placement of all the original vertices using
    :py:func:`finalise_same_chip_constraints`.

    A typical use pattern might look like::

        def my_placer(vertices_resources, nets, machine, constraints):
            # Should be done first thing since this may redefine
            # vertices_resources, nets and constraints.
            vertices_resources, nets, constraints, substitutions = \\
                apply_same_chip_constraints(vertices_resources,
                                            nets, constraints)

            # ...deal with other types of constraint...

            # ...perform placement...

            finalise_same_chip_constraints(substitutions, placements)
            return placements

    Note that this function does not modify its arguments but rather returns
    new copies of the structures supplied.

    Parameters
    ----------
    vertices_resources : {vertex: {resource: quantity, ...}, ...}
    nets : [:py:class:`~rig.netlist.Net`, ...]
    constraints : [constraint, ...]

    Returns
    -------
    (vertices_resources, nets, constraints, substitutions)
        The vertices_resources, nets and constraints values contain modified
        copies of the supplied data structures modified to contain a single
        vertex in place of the individual constrained vertices.

        substitutions is a list of :py:class:`MergedVertex` objects which
        resulted from the combining of the constrained vertices. The order of
        the list is the order the substitutions were carried out. The
        :py:func:`finalise_same_chip_constraints` function can be used to
        expand a set of substitutions.
    """
    # Make a copy of the basic structures to be modified by this function
    vertices_resources = vertices_resources.copy()
    nets = nets[:]
    constraints = constraints[:]

    substitutions = []

    for same_chip_constraint in constraints:
        if not isinstance(same_chip_constraint, SameChipConstraint):
            continue

        # Skip constraints which don't actually merge anything...
        if len(same_chip_constraint.vertices) <= 1:
            continue

        # The new (merged) vertex with which to replace the constrained
        # vertices
        merged_vertex = MergedVertex(same_chip_constraint.vertices)
        substitutions.append(merged_vertex)

        # A set containing the set of vertices to be merged (to remove
        # duplicates)
        merged_vertices = set(same_chip_constraint.vertices)

        # Remove the merged vertices from the set of vertices resources and
        # accumulate the total resources consumed. Note add_resources is not
        # used since we don't know if the resources consumed by each vertex are
        # overlapping.
        total_resources = {}
        for vertex in merged_vertices:
            resources = vertices_resources.pop(vertex)
            for resource, value in iteritems(resources):
                total_resources[resource] = (total_resources.get(resource, 0) +
                                             value)
        vertices_resources[merged_vertex] = total_resources

        # Update any nets which pointed to a merged vertex
        for net_num, net in enumerate(nets):
            net_changed = False

            # Change net sources
            if net.source in merged_vertices:
                net_changed = True
                net = Net(merged_vertex, net.sinks, net.weight)

            # Change net sinks
            for sink_num, sink in enumerate(net.sinks):
                if sink in merged_vertices:
                    if not net_changed:
                        net = Net(net.source, net.sinks, net.weight)
                    net_changed = True
                    net.sinks[sink_num] = merged_vertex

            if net_changed:
                nets[net_num] = net

        # Update any constraints which refer to a merged vertex
        for constraint_num, constraint in enumerate(constraints):
            if isinstance(constraint, LocationConstraint):
                if constraint.vertex in merged_vertices:
                    constraints[constraint_num] = LocationConstraint(
                        merged_vertex, constraint.location)
            elif isinstance(constraint, SameChipConstraint):
                if not set(constraint.vertices).isdisjoint(merged_vertices):
                    constraints[constraint_num] = SameChipConstraint([
                        merged_vertex if v in merged_vertices else v
                        for v in constraint.vertices
                    ])
            elif isinstance(constraint, RouteEndpointConstraint):
                if constraint.vertex in merged_vertices:
                    constraints[constraint_num] = RouteEndpointConstraint(
                        merged_vertex, constraint.route)

    return (vertices_resources, nets, constraints, substitutions)
def apply_same_chip_constraints ( vertices_resources , nets , constraints ) : vertices_resources = vertices_resources . copy ( ) nets = nets [ : ] constraints = constraints [ : ] substitutions = [ ] for same_chip_constraint in constraints : if not isinstance ( same_chip_constraint , SameChipConstraint ) : continue if len ( same_chip_constraint . vertices ) <= 1 : continue merged_vertex = MergedVertex ( same_chip_constraint . vertices ) substitutions . append ( merged_vertex ) merged_vertices = set ( same_chip_constraint . vertices ) total_resources = { } for vertex in merged_vertices : resources = vertices_resources . pop ( vertex ) for resource , value in iteritems ( resources ) : total_resources [ resource ] = ( total_resources . get ( resource , 0 ) + value ) vertices_resources [ merged_vertex ] = total_resources for net_num , net in enumerate ( nets ) : net_changed = False if net . source in merged_vertices : net_changed = True net = Net ( merged_vertex , net . sinks , net . weight ) for sink_num , sink in enumerate ( net . sinks ) : if sink in merged_vertices : if not net_changed : net = Net ( net . source , net . sinks , net . weight ) net_changed = True net . sinks [ sink_num ] = merged_vertex if net_changed : nets [ net_num ] = net for constraint_num , constraint in enumerate ( constraints ) : if isinstance ( constraint , LocationConstraint ) : if constraint . vertex in merged_vertices : constraints [ constraint_num ] = LocationConstraint ( merged_vertex , constraint . location ) elif isinstance ( constraint , SameChipConstraint ) : if not set ( constraint . vertices ) . isdisjoint ( merged_vertices ) : constraints [ constraint_num ] = SameChipConstraint ( [ merged_vertex if v in merged_vertices else v for v in constraint . vertices ] ) elif isinstance ( constraint , RouteEndpointConstraint ) : if constraint . vertex in merged_vertices : constraints [ constraint_num ] = RouteEndpointConstraint ( merged_vertex , constraint . route ) return ( vertices_resources , nets , constraints , substitutions )
Modify a set of vertices_resources, nets and constraints to account for
    all SameChipConstraints.

    To allow placement algorithms to handle SameChipConstraints without any
    special cases, Vertices identified in a SameChipConstraint are merged into
    a new vertex whose vertices_resources are the sum total of their parts
    which may be placed as if a single vertex. Once placed, the placement can
    be expanded into a full placement of all the original vertices using
    :py:func:`finalise_same_chip_constraints`.

    A typical use pattern might look like::

        def my_placer(vertices_resources, nets, machine, constraints):
            # Should be done first thing since this may redefine
            # vertices_resources, nets and constraints.
            vertices_resources, nets, constraints, substitutions = \\
                apply_same_chip_constraints(vertices_resources,
                                            nets, constraints)

            # ...deal with other types of constraint...

            # ...perform placement...

            finalise_same_chip_constraints(substitutions, placements)
            return placements

    Note that this function does not modify its arguments but rather returns
    new copies of the structures supplied.

    Parameters
    ----------
    vertices_resources : {vertex: {resource: quantity, ...}, ...}
    nets : [:py:class:`~rig.netlist.Net`, ...]
    constraints : [constraint, ...]

    Returns
    -------
    (vertices_resources, nets, constraints, substitutions)
        The vertices_resources, nets and constraints values contain modified
        copies of the supplied data structures modified to contain a single
        vertex in place of the individual constrained vertices.

        substitutions is a list of :py:class:`MergedVertex` objects which
        resulted from the combining of the constrained vertices. The order of
        the list is the order the substitutions were carried out. The
        :py:func:`finalise_same_chip_constraints` function can be used to
        expand a set of substitutions.