Ask Your Question
1

Trying to plot a function with three variables

asked 2016-11-28 23:56:32 +0100

thwee gravatar image

I'm trying to plot a function with three variables, attraction, repulsion, and epsilon, but the plot function doesn't seem to be doing what I want it to.

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

        return self.position

    def _distance(self, p1, p2):
        return sqrt((p1[0] + p2[0])^2 + (p1[0] + p2[0])^2 + (p1[0] + p2[0])^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)
plot(distance(repulsion, attraction, epsilon), 
     (repulsion, -1, 1), 
     (attraction, -1, 1),
     (epsilon, -1, 1)
    )

I'll post the code below, could someone share with me what I'm doing wrong, please? To be specific, my code doesn't produce any output whatsoever.

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
2

answered 2016-11-29 04:41:02 +0100

updated 2016-11-29 05:21:43 +0100

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, plotting a function of three independent variables needs four-dimensional plotting capabilities. 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.

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2016-11-28 23:56:32 +0100

Seen: 376 times

Last updated: Nov 29 '16