Ask Your Question

Revision history [back]

Some things jump out for me:

1) Vertex.distance calls itself. Presumably it should call Vertex._distance.

2) Vertex._distance has issues: it needs negative signs inside the squares and the vector indices are currently identical.

3) Most critically, you're trying to plot a function of three independent variables, which would need four-dimensional plotting capabilities. The best you can do in three dimensions is an implicit_plot3d for when the four-dimensional surface equals some value. In the following code, that's when distance(repulsion, attraction, epsilon) is one:

class Vertex:
    def __init__(self):
        self.acceleration = vector((0, 0, 0))
        self.velocity = vector((0, 0, 0))
        self.position = self._random_vector()

    def _rand(self):
        return RR.random_element(-1, 1)

    def _random_vector(self):
        return vector((self._rand(), self._rand(), self._rand()))

    def _repulsion(self, x1, x2, c_repulsion=0, c_epsilon=0.1):
        return (c_repulsion / c_epsilon + abs(x1-x2)^2)*((x1-x2)/abs(x1-x2))    

    def _attraction(self, x1, x2, c_attraction):
        return (x1-x2)*-1*c_attraction

    def iterate(self, vertices, c_repulsion=0, c_attraction=0, c_epsilon=0, c_friction=0.60):
        for v in vertices:
            if v is not self:
                self.acceleration += self._attraction(self.position, v.position, c_attraction)
                self.acceleration -= self._repulsion(self.position, v.position, c_repulsion, c_epsilon)
        self.acceleration -= (self.acceleration * c_friction)
        self.velocity += self.acceleration
        self.position += self.velocity


    def _distance(self, p1, p2):
        return sqrt((p1[0] - p2[0])^2 + (p1[1] - p2[1])^2 + (p1[2] - p2[2])^2)

    def distance(self, v):
        return self._distance(self.position, v.position)

    def reset(self):
        self.acceleration = vector((0, 0, 0))
        self.velocity = vector((0, 0, 0))
        self.position = random_vector()

v1 = Vertex()
v2 = Vertex()

repulsion, attraction, epsilon = var('repulsion, attraction, epsilon')
def distance(repulsion, attraction, epsilon):
    #for i in range(100):
    v1.iterate(
            [v1, v2], 
            c_repulsion=repulsion, 
            c_attraction=attraction, 
            c_epsilon=epsilon
        )
    return v1.distance(v2)

implicit_plot3d(distance(repulsion, attraction, epsilon)==1, 
     (repulsion, -1, 1), 
     (attraction, -1, 1),
     (epsilon, -1, 1)
    )

Here's a live link for the code. You can change the value on the right-hand side of == to see other three-dimensional slices of the four-surface.

Some things jump out for me:

1) Vertex.distance calls itself. Presumably it should call Vertex._distance.

2) Vertex._distance has issues: it needs negative signs inside the squares and the vector indices are currently identical.

3) Most critically, you're trying to plot plotting a function of three independent variables, which would need variables needs four-dimensional plotting capabilities. The best One thing you can do in three dimensions is an implicit_plot3d for when the four-dimensional surface equals some value. In the following code, that's when distance(repulsion, attraction, epsilon) is one:

class Vertex:
    def __init__(self):
        self.acceleration = vector((0, 0, 0))
        self.velocity = vector((0, 0, 0))
        self.position = self._random_vector()

    def _rand(self):
        return RR.random_element(-1, 1)

    def _random_vector(self):
        return vector((self._rand(), self._rand(), self._rand()))

    def _repulsion(self, x1, x2, c_repulsion=0, c_epsilon=0.1):
        return (c_repulsion / c_epsilon + abs(x1-x2)^2)*((x1-x2)/abs(x1-x2))    

    def _attraction(self, x1, x2, c_attraction):
        return (x1-x2)*-1*c_attraction

    def iterate(self, vertices, c_repulsion=0, c_attraction=0, c_epsilon=0, c_friction=0.60):
        for v in vertices:
            if v is not self:
                self.acceleration += self._attraction(self.position, v.position, c_attraction)
                self.acceleration -= self._repulsion(self.position, v.position, c_repulsion, c_epsilon)
        self.acceleration -= (self.acceleration * c_friction)
        self.velocity += self.acceleration
        self.position += self.velocity


    def _distance(self, p1, p2):
        return sqrt((p1[0] - p2[0])^2 + (p1[1] - p2[1])^2 + (p1[2] - p2[2])^2)

    def distance(self, v):
        return self._distance(self.position, v.position)

    def reset(self):
        self.acceleration = vector((0, 0, 0))
        self.velocity = vector((0, 0, 0))
        self.position = random_vector()

v1 = Vertex()
v2 = Vertex()

repulsion, attraction, epsilon = var('repulsion, attraction, epsilon')
def distance(repulsion, attraction, epsilon):
    #for i in range(100):
    v1.iterate(
            [v1, v2], 
            c_repulsion=repulsion, 
            c_attraction=attraction, 
            c_epsilon=epsilon
        )
    return v1.distance(v2)

implicit_plot3d(distance(repulsion, attraction, epsilon)==1, 
     (repulsion, -1, 1), 
     (attraction, -1, 1),
     (epsilon, -1, 1)
    )

Here's a live link for the code. You can change the value on the right-hand side of == to see other three-dimensional slices of the four-surface.