def default_cost_function(segments, nodes,
                          turn_cost=3000, intersection_cost=500,
                          min_travel_lanes_for_deadend_uturn=1,
                          deadend_uturn_cost=0):
    """
    Return the default cost function for building the segment->segment nework.

    Doesn't allow vehicles to go across a street from one blockface to another.

    Parameters
    ----------
    turn_cost : int
        The cost pentalty for making a turn (Default 3000)
    intersection_cost : int
        The cost pentalty for crossing an intersection (Default 500)
    min_travel_lanes_for_deadend_uturn : int
        The number of lanes required for the vehicle to make a u-turn on a
        dead end.  For trucks it should be >= 2. (Default 1)
    deadend_uturn_cost : int
        The additional cost penalty for making a uturn. Used to disincentivize
        making a u-turn on a dead end, but not disallow it. (Default 0)

    Returns
    -------
    function(geocoder, segment_id_1, segment_id_2, node_id)
    """

    def cost_function(segment_id_1, segment_id_2, node_id):
        """
        A function that returns the cost of going from segment_id_1 to
        segment_id_2.

        If the transition isn't possible, return None.

        Parameters
        ----------
        geocoder : gomi.geocoder.Geocoder
            A reference to a Geocoder is passed so that the function can
            look up attributes of the segments and node.
        segment_id_1, segment_id_2 : str
            The segments
        node_id : str
            The node connecting the two segments
        """
        segment_id_1 = segment_id_1[:-1]
        segment_id_2 = segment_id_2[:-1]

        travel_lanes = segments[segment_id_1]['number_travel_lanes']

        if (
            # No transitions between the same segment
            (segment_id_1 != segment_id_2) or
            # Unless it's a dead end with enough travel lanes
            (
                (nodes[node_id]['dead_end']) and
                (travel_lanes >= min_travel_lanes_for_deadend_uturn)
            )
        ):
            cost = 0

            # If crossing physical IDs, it's an intersection
            if (segments[segment_id_1]['physical_id'] !=
                segments[segment_id_2]['physical_id']):
                cost = intersection_cost

            # If the street codes don't overlap it's a turn
            if len(segments[segment_id_1]['street_code'].intersection(
                segments[segment_id_2]['street_code']
            )) == 0:
                cost = turn_cost

            # Include half the length of each segment
            cost += segments[segment_id_1]['len']/2
            cost += segments[segment_id_2]['len']/2

            # If it's a dead end, add u-turn penalty
            if segment_id_1 == segment_id_2:
                cost += deadend_uturn_cost

            return cost

    return cost_function