<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
Step5:  Oregon Curriculum Network <br />
Discovering Math with Python
Chapter 7
Step6:  The polyhedrons we've talked about will be instances of our Polyhedron class.  Once instantiated, they each keep their vertex labels and pass them on to their progeny.  To transform a polyhedron, as we will do in the next chapter, is to create a new one, not to change an existing one in place.  Once defined, a polyhedron should be considered immutable.
Quadrays are just like XYZ vectors except they're described by 4-tuples indicating how much of three of the four directions are needed to reach a point.  The basis vectors point to the corners of a regular tetrahedron from its center, dividing space intor four quadrants.  The basis vector pointing away from the quadrant where our point is, will have a coefficient of 0.
Lets look at some examples
Step7:  Qvector A is in the all-positive XYZ octant (+,+,+), whereas Qvector B is still above the XY plane but kitty-corner in octant (-,-,+). The other two points form a segment below the XY plane and perpendicular to the first, in (-,+,-) and (+,-,-) respectively.  
Placing your forearms perpendicular to one another, but some distance apart, gives the same idea.  Your wrists and elbows will be the four vertexes in question.  Opposite edges of the regular tetrahedron are at 90 degrees to one another.
We're now ready to define our polyhedron faces accordingly and feed them into the class, along with the dict of needed vectors (or Qvectors in this case).
<ASSISTANT_TASK:>
Python Code:
from qrays import Vector # see Chapter 6
class Polyhedron:
    
    def __init__(self, name, volume, faces : set, 
                 vertexes : dict, center = Vector((0,0,0))):        
        self.name = name
        self.vertexes = vertexes
        self.volume = volume
        self.faces = faces
        self.edges = self._distill() # derive unique edges from faces
        self.center = center
        
    def _distill(self):
        
        get all edge pairs from faces
        
        edges = set()
        for face in self.faces:
            new_pairs = {tuple(sorted([a, b])) # sorting pairs keeps them unique
                         for a,b in zip(face, face[1:] + (face[0],))}
             # ('B','A') won't sneak in as another ('A','B')
            edges = edges.union(new_pairs) 
        return edges
    
    def translate(self, slider : Vector):
        
        slide to a new position, keep track of the center
        
        pass
    
    def rotate(self, degrees, axis):
        
        We will use a matrix to rotate around x, y or z axis
                    
        pass
    
    def scale(self, scale_factor):
        
        resize by scale_factor and emit a new polyhedron
        Volume changes as a 3rd power of scale_factor.
        
        pass
    
    def render(self, color, filename = "output.pov"):
        
        build a povray file in Scene Description Language
        
        pass
    
    def __repr__(self):
        return "Polyhedron({})".format(self.name)
Explanation: Oregon Curriculum Network <br />
Discovering Math with Python
Chapter 7: POLYHEDRONS
The ray-tracing program POV-Ray, free and open source, understands XYZ coordinates, so at the end of the day we'll need those for rendering our polyhedrons as ray tracings.  
However, building our small vocabulary of 26 vertexes will make use of a more congenial set of 4-tuples known as Quadray coordinates.  
We will compute and then store our polyhedron vertexes using Quadray Coordinates (see Chapter 6) and then convert to XYZ on the fly, when it's time to actually write scene description language for POV-Ray to process.
Do not confuse Quadrays with Quaternions, the subject of Chapter 11.
<a data-flickr-embed="true"  href="https://www.flickr.com/photos/kirbyurner/4073009388/in/photolist-dXVxsM-JotMo-8cn39x-7cVeMN-kreNGK-jjQKR2-8P2cs1-jjQPyH-jjRh9s-dj1wJw-jjPxdF-jjTYJ3-jjPNN8-bhjf7P-dq3Pno-jjTX9Q-jnjYkJ-jKwah8-jpfFXG-7rwtU1-4ZEr4-4ZEr3" title="Quadray Coordinates"><img src="https://farm3.staticflickr.com/2693/4073009388_e1da93dbd4.jpg" width="400" height="350" alt="Quadray Coordinates"></a><script async src="//embedr.flickr.com/assets/client-code.js" charset="utf-8"></script>
Polyhedrons as a Data Structure
Consider the Tetrahedron, the simplest of all polyhedrons, also known as a Simplex for that reason.  Its vertexes, labeled 'A', 'B', 'C', 'D' give us a way to represent the faces as a tuple of tuples: (('A', 'B', 'C'), ('A', 'B', 'D'), ('A', 'C', 'D'), ('B', 'C', 'D')).  
'A' through 'D' may be considered the names of point vectors.
The dual Tetrahedron (-A, -B, -C, -D) intersects our first at its mid-edges and together these define the eight vertexes of a cube.  The cube's dual, an octahedron, has vertexes we might define as vector sums of those already given.
The combination of the cube and octahedron define the twelve diamond faced rhombic dodecahedron, a favorite of Kepler's, and a space-filler.  Its dual, the cuboctahedron, will be the final shape we include.  All 26 vertexes labeled 'A' through 'Z' may be developed as vector sums of the initial A, B, C, D.
However, before we get to our actual dict of vectors, lets take a look at the Polyhedron that's shaping up, based on the transformations we'll be needing.
End of explanation
from qrays import Qvector, Vector
tet1 = {}
tet1['A'] = Qvector((1,0,0,0))
tet1['B'] = Qvector((0,1,0,0))
tet1['C'] = Qvector((0,0,1,0))
tet1['D'] = Qvector((0,0,0,1))
for v in tet1:
    print(tet1[v].xyz())
Explanation: The polyhedrons we've talked about will be instances of our Polyhedron class.  Once instantiated, they each keep their vertex labels and pass them on to their progeny.  To transform a polyhedron, as we will do in the next chapter, is to create a new one, not to change an existing one in place.  Once defined, a polyhedron should be considered immutable.
Quadrays are just like XYZ vectors except they're described by 4-tuples indicating how much of three of the four directions are needed to reach a point.  The basis vectors point to the corners of a regular tetrahedron from its center, dividing space intor four quadrants.  The basis vector pointing away from the quadrant where our point is, will have a coefficient of 0.
Lets look at some examples:
End of explanation
Tet1 = Polyhedron("Tetrahedron", volume = 1, 
                  faces = {('A', 'B', 'C'), ('A', 'B', 'D'), 
                           ('A', 'C', 'D'), ('B', 'C', 'D')},
                  vertexes = tet1)
Tet1.edges  # lets make sure _distill() did its job
tet2 = {}  # now for the dual tetrahedron
tet2['E'] = -tet1['A']
tet2['F'] = -tet1['B']
tet2['G'] = -Qvector((0,0,1,0)) # same as -tet1['C']
tet2['H'] = -Qvector((0,0,0,1)) # same as -tet1['D']
Tet2 = Polyhedron("Dual Tetrahedron", volume = 1, 
                  faces = {('E', 'F', 'G'), ('E', 'F', 'H'), 
                           ('E', 'F', 'G'), ('F', 'G', 'H')},
                  vertexes = tet2)
Tet2.edges
Explanation: Qvector A is in the all-positive XYZ octant (+,+,+), whereas Qvector B is still above the XY plane but kitty-corner in octant (-,-,+). The other two points form a segment below the XY plane and perpendicular to the first, in (-,+,-) and (+,-,-) respectively.  
Placing your forearms perpendicular to one another, but some distance apart, gives the same idea.  Your wrists and elbows will be the four vertexes in question.  Opposite edges of the regular tetrahedron are at 90 degrees to one another.
We're now ready to define our polyhedron faces accordingly and feed them into the class, along with the dict of needed vectors (or Qvectors in this case).
End of explanation
<END_TASK>