<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def run(edges, iterations=1000, force_strength=5.0, dampening=0.01, max_velocity=2.0, max_distance=50, is_3d=True):
 """Runs a force-directed-layout algorithm on the input graph. iterations - Number of FDL iterations to run in coordinate generation force_strength - Strength of Coulomb and Hooke forces (edit this to scale the distance between nodes) dampening - Multiplier to reduce force applied to nodes max_velocity - Maximum distance a node can move in one step max_distance - The maximum distance considered for interactions """


    # Get a list of node ids from the edge data
    nodes = set(e['source'] for e in edges) | set(e['target'] for e in edges)

    # Convert to a data-storing object and initialize some values
    d = 3 if is_3d else 2
    nodes = {n: {'velocity': [0.0] * d, 'force': [0.0] * d} for n in nodes}

    # Repeat n times (is there a more Pythonic way to do this?)
    for _ in repeat(None, iterations):

        # Add in Coulomb-esque node-node repulsive forces
        for node1, node2 in combinations(nodes.values(), 2):
            _coulomb(node1, node2, force_strength, max_distance)

        # And Hooke-esque edge spring forces
        for edge in edges:
            _hooke(nodes[edge['source']], nodes[edge['target']],
                   force_strength * edge.get('size', 1), max_distance)

        # Move by resultant force
        for node in nodes.values():
            # Constrain the force to the bounds specified by input parameter
            force = [_constrain(dampening * f, -max_velocity, max_velocity)
                     for f in node['force']]
            # Update velocities and reset force
            node['velocity'] = [v + dv
                                for v, dv in zip(node['velocity'], force)]
            node['force'] = [0] * d

    # Clean and return
    for node in nodes.values():
        del node['force']
        node['location'] = node['velocity']
        del node['velocity']
        # Even if it's 2D, let's specify three dimensions
        if not is_3d:
            node['location'] += [0.0]
    return nodes