Algorithm that spans orthogonal vectors: PythonAlgorithm that generates orthogonal vectors: C++ implementationOptimize Cython code with np.ndarray containedCreating 2D vectorsTapeEquilibrium Codility implementation not achieving 100%Python - basis of a parser library, followupFind the intervals which have a non-empty intersection with a given intervalOrthogonal samplingImplementation of a threshold detection function in PythonPython program to find the subarray with maximum sum

Scientific Illustration: Non-photorealistic rendering of sparse wireframe with dashed/dotted lines for backfacing areas - Blender 2.80

CORS error but only from AJAX and not from HTML form

Draw the Ionising Radiation Hazard Symbol

What is the rationale for single engine military aircraft?

How can an AI train itself if no one is telling it if its answer is correct or wrong?

Is there a way to extend the length of wires for I2C connection?

Puzzling is a Forte of Mine

Why did we never simplify key signatures?

Messed up my .bash_profile remotely, can't ssh back in

What is the difference between "cat < filename" and "cat filename"?

How to differentiate landing on top of an object from falling down the side?

If I wanted to reconstruct an entire Apollo mission's crewed spacecraft trajectories, what are the key sources of historical data I'd look for?

Present value heuristics problem

Why can't sonic booms be heard at air shows?

Did the Apollo missions fly "over the top" of the Van Allen radiation belts?

How should I handle cases like this where the documentation for Bitcoin Core states one thing, and the actual program does something else?

How to get the memory state of SRAM on power up?

Why would Earth be long-term unsuitable for an advanced alien species that's already colonized it?

Cheap and safe way to dim 100+ 60W Incandescent bulbs

Is there a theory challenging the "strict" distinction between Thai and Vietnamese?

How does Hilbert's 10th problem imply that the growth of solutions to Diophantine equations is uncomputable?

Translation of "Love makes it grow" in Latin for my tattoo

Can studying in a good place hurt your application?

Is there no way in Windows 10 to type the Euro symbol € on a US English keyboard that has neither numeric keypad nor "alt gr" key?



Algorithm that spans orthogonal vectors: Python


Algorithm that generates orthogonal vectors: C++ implementationOptimize Cython code with np.ndarray containedCreating 2D vectorsTapeEquilibrium Codility implementation not achieving 100%Python - basis of a parser library, followupFind the intervals which have a non-empty intersection with a given intervalOrthogonal samplingImplementation of a threshold detection function in PythonPython program to find the subarray with maximum sum






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;









12















$begingroup$


The code consists of three functions:



  1. Spans arbitrary vector (takes dimension as an argument)


  2. Spans vector orthogonal to the one passed in the argument


  3. Finds cross product between two vectors.


The code is following:



def span_vector(n):
'''n represents dimension of the vector.'''
return [random.randrange(-1000,1000) for x in range(n)]


def span_orthogonal(vec):
'''vec represents n-dimensional vector'''
'''Function spans an arbitrary vector that is orthogonal to vec'''

dimension = len(vec)
orthogonal_vec = []
for k in range(dimension-1):
orthogonal_vec.append(random.randrange(-1000,1000))
last_k = ((-1)*sum([vec[x]*orthogonal_vec[x] for x in range(dimension-1)]))/vec[-1]
orthogonal_vec.append(last_k)
return orthogonal_vec

def cross_product(v1,v2):
return sum(v1[x]*v2[x] for x in range(len(v1)))



What can be improved?




EDIT The last function must read dot_product, but not cross_product. I made a mistake.










share|improve this question











$endgroup$










  • 2




    $begingroup$
    Is there a reason that you aren't using Numpy?
    $endgroup$
    – Reinderien
    Sep 18 at 13:42










  • $begingroup$
    @Reinderien I've just tried to write something without using Numpy. But well, I concede that using Numpy would be a way better choice.
    $endgroup$
    – Nelver
    Sep 18 at 14:27






  • 8




    $begingroup$
    Two points: (1) "span" has a technical meaning in linear algebra so I do not think the names span_vector and span_orthogonal are appropriate (sth. like generate_vector should be fine); (2) if it is not required that span_orthogonal returns a random vector, one can directly construct a vector orthogonal to the input from the input's coordinates.
    $endgroup$
    – GZ0
    Sep 18 at 14:41


















12















$begingroup$


The code consists of three functions:



  1. Spans arbitrary vector (takes dimension as an argument)


  2. Spans vector orthogonal to the one passed in the argument


  3. Finds cross product between two vectors.


The code is following:



def span_vector(n):
'''n represents dimension of the vector.'''
return [random.randrange(-1000,1000) for x in range(n)]


def span_orthogonal(vec):
'''vec represents n-dimensional vector'''
'''Function spans an arbitrary vector that is orthogonal to vec'''

dimension = len(vec)
orthogonal_vec = []
for k in range(dimension-1):
orthogonal_vec.append(random.randrange(-1000,1000))
last_k = ((-1)*sum([vec[x]*orthogonal_vec[x] for x in range(dimension-1)]))/vec[-1]
orthogonal_vec.append(last_k)
return orthogonal_vec

def cross_product(v1,v2):
return sum(v1[x]*v2[x] for x in range(len(v1)))



What can be improved?




EDIT The last function must read dot_product, but not cross_product. I made a mistake.










share|improve this question











$endgroup$










  • 2




    $begingroup$
    Is there a reason that you aren't using Numpy?
    $endgroup$
    – Reinderien
    Sep 18 at 13:42










  • $begingroup$
    @Reinderien I've just tried to write something without using Numpy. But well, I concede that using Numpy would be a way better choice.
    $endgroup$
    – Nelver
    Sep 18 at 14:27






  • 8




    $begingroup$
    Two points: (1) "span" has a technical meaning in linear algebra so I do not think the names span_vector and span_orthogonal are appropriate (sth. like generate_vector should be fine); (2) if it is not required that span_orthogonal returns a random vector, one can directly construct a vector orthogonal to the input from the input's coordinates.
    $endgroup$
    – GZ0
    Sep 18 at 14:41














12













12









12


1



$begingroup$


The code consists of three functions:



  1. Spans arbitrary vector (takes dimension as an argument)


  2. Spans vector orthogonal to the one passed in the argument


  3. Finds cross product between two vectors.


The code is following:



def span_vector(n):
'''n represents dimension of the vector.'''
return [random.randrange(-1000,1000) for x in range(n)]


def span_orthogonal(vec):
'''vec represents n-dimensional vector'''
'''Function spans an arbitrary vector that is orthogonal to vec'''

dimension = len(vec)
orthogonal_vec = []
for k in range(dimension-1):
orthogonal_vec.append(random.randrange(-1000,1000))
last_k = ((-1)*sum([vec[x]*orthogonal_vec[x] for x in range(dimension-1)]))/vec[-1]
orthogonal_vec.append(last_k)
return orthogonal_vec

def cross_product(v1,v2):
return sum(v1[x]*v2[x] for x in range(len(v1)))



What can be improved?




EDIT The last function must read dot_product, but not cross_product. I made a mistake.










share|improve this question











$endgroup$




The code consists of three functions:



  1. Spans arbitrary vector (takes dimension as an argument)


  2. Spans vector orthogonal to the one passed in the argument


  3. Finds cross product between two vectors.


The code is following:



def span_vector(n):
'''n represents dimension of the vector.'''
return [random.randrange(-1000,1000) for x in range(n)]


def span_orthogonal(vec):
'''vec represents n-dimensional vector'''
'''Function spans an arbitrary vector that is orthogonal to vec'''

dimension = len(vec)
orthogonal_vec = []
for k in range(dimension-1):
orthogonal_vec.append(random.randrange(-1000,1000))
last_k = ((-1)*sum([vec[x]*orthogonal_vec[x] for x in range(dimension-1)]))/vec[-1]
orthogonal_vec.append(last_k)
return orthogonal_vec

def cross_product(v1,v2):
return sum(v1[x]*v2[x] for x in range(len(v1)))



What can be improved?




EDIT The last function must read dot_product, but not cross_product. I made a mistake.







python coordinate-system






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Sep 18 at 15:02









dfhwze

13.3k3 gold badges26 silver badges95 bronze badges




13.3k3 gold badges26 silver badges95 bronze badges










asked Sep 18 at 13:34









NelverNelver

63512 bronze badges




63512 bronze badges










  • 2




    $begingroup$
    Is there a reason that you aren't using Numpy?
    $endgroup$
    – Reinderien
    Sep 18 at 13:42










  • $begingroup$
    @Reinderien I've just tried to write something without using Numpy. But well, I concede that using Numpy would be a way better choice.
    $endgroup$
    – Nelver
    Sep 18 at 14:27






  • 8




    $begingroup$
    Two points: (1) "span" has a technical meaning in linear algebra so I do not think the names span_vector and span_orthogonal are appropriate (sth. like generate_vector should be fine); (2) if it is not required that span_orthogonal returns a random vector, one can directly construct a vector orthogonal to the input from the input's coordinates.
    $endgroup$
    – GZ0
    Sep 18 at 14:41













  • 2




    $begingroup$
    Is there a reason that you aren't using Numpy?
    $endgroup$
    – Reinderien
    Sep 18 at 13:42










  • $begingroup$
    @Reinderien I've just tried to write something without using Numpy. But well, I concede that using Numpy would be a way better choice.
    $endgroup$
    – Nelver
    Sep 18 at 14:27






  • 8




    $begingroup$
    Two points: (1) "span" has a technical meaning in linear algebra so I do not think the names span_vector and span_orthogonal are appropriate (sth. like generate_vector should be fine); (2) if it is not required that span_orthogonal returns a random vector, one can directly construct a vector orthogonal to the input from the input's coordinates.
    $endgroup$
    – GZ0
    Sep 18 at 14:41








2




2




$begingroup$
Is there a reason that you aren't using Numpy?
$endgroup$
– Reinderien
Sep 18 at 13:42




$begingroup$
Is there a reason that you aren't using Numpy?
$endgroup$
– Reinderien
Sep 18 at 13:42












$begingroup$
@Reinderien I've just tried to write something without using Numpy. But well, I concede that using Numpy would be a way better choice.
$endgroup$
– Nelver
Sep 18 at 14:27




$begingroup$
@Reinderien I've just tried to write something without using Numpy. But well, I concede that using Numpy would be a way better choice.
$endgroup$
– Nelver
Sep 18 at 14:27




8




8




$begingroup$
Two points: (1) "span" has a technical meaning in linear algebra so I do not think the names span_vector and span_orthogonal are appropriate (sth. like generate_vector should be fine); (2) if it is not required that span_orthogonal returns a random vector, one can directly construct a vector orthogonal to the input from the input's coordinates.
$endgroup$
– GZ0
Sep 18 at 14:41





$begingroup$
Two points: (1) "span" has a technical meaning in linear algebra so I do not think the names span_vector and span_orthogonal are appropriate (sth. like generate_vector should be fine); (2) if it is not required that span_orthogonal returns a random vector, one can directly construct a vector orthogonal to the input from the input's coordinates.
$endgroup$
– GZ0
Sep 18 at 14:41











5 Answers
5






active

oldest

votes


















11

















$begingroup$

You should probably be using Numpy, although I don't know enough about your situation to comment any further.



Assuming that you need to retain "pure Python", the following improvements can be made:



Negation



Replace (-1)* with -



Generators



Replace your for k in range(dimension-1): loop with



orthogonal_vec = [
random.randrange(-1000,1000)
for _ in range(dimension-1)
]


Type hints



n: int, vec: typing.Sequence[float] (probably) . And the first two functions return -> typing.List[float]. cross_product both accepts and returns float.



Inner list



sum([ ... ])


shouldn't use an inner list. Just pass the generator directly to sum.






share|improve this answer












$endgroup$






















    10

















    $begingroup$

    This is only a minor observation on top of what @Reinderien already wrote about your code.



    Writing function documentation like you did with



    def span_orthogonal(vec):
    '''vec represents n-dimensional vector'''
    '''Function spans an arbitrary vector that is orthogonal to vec'''


    does not work as expected.



    If you were to use help(span_orthogonal) you'd see



    Help on function span_orthogonal in module __main__:

    span_orthogonal(vec)
    vec represents n-dimensional vector


    The reason is that only the first block of text is interpreted as documentation. Also the usual convention is to write documentation "the other way round", by which I mean first give a short summary on what your function does, than go on to provide details such as the expected input. Both aspects can also be found in the infamous official Style Guide for Python Code (aka PEP 8) in the section on documentation strings.



    With



    def span_orthogonal(vec):
    '''Function spans an arbitrary vector that is orthogonal to vec

    vec represents n-dimensional vector
    '''


    calling help(...) gives you



    Help on function span_orthogonal in module __main__:

    span_orthogonal(vec)
    Function spans an arbitrary vector that is orthogonal to vec

    vec represents n-dimensional vector


    Also since @Reinderien also hinted you towards numpy, just let me tell you that there is also "special" documentation convention (aka numpydoc) often used in the scientific Python stack.



    An example:



    def span_orthogonal(vec):
    '''Function spans an arbitrary vector that is orthogonal to vec

    Parameters
    ----------
    vec : array_like
    represents n-dimensional vector
    '''


    This style is closer to what's possible with type hints in current versions of Python, as in that it's more structured. The idea behind numpydoc is to facilitate automated documentation generation using tools like Sphinx, but this goes a little bit beyond what I was trying to convey here.






    share|improve this answer










    $endgroup$














    • $begingroup$
      That's a very useful information. Thank you!
      $endgroup$
      – Nelver
      Sep 18 at 14:54


















    5

















    $begingroup$

    Besides what @Reinderein and @AlexV already mentioned, you could have added the following to your code to deliver a complete runnable example:



    at the top:



    import random


    at he bottom something like:



    def main():
    v1 = span_vector(3)
    v2 = span_orthogonal(v1)
    print(v1)
    print(v2)
    print(cross_product(v1,v2))

    if __name__ == '__main__':
    main()


    For the 1000's (and in -1000) you could use a 'constant':



    MAX_COOR_VAL = 1000


    The definition of (cross)dot_product(v1,v2) could be made a bit clearer and more consistent with span_orthogonal(vec):



    def dot_product(vec1, vec2):


    The method span_orthogonal(vec) is not bulletproof, it might result in a ZeroDivisionError exception when vec equals [1,0] and the random creation of orthogonal_vec happens to be [1] (or [2])






    share|improve this answer










    $endgroup$






















      5

















      $begingroup$

      It would be more Pythonic to use zip() in your cross_product(v1, v2) dot_product(v1, v2) function:



       return sum(a * b for a, b in zip(v1, v2))


      This iterates over both vectors simultaneously, extracting one component from each, and calling those components a and b respectively ... and multiplying them together and summing them as normal. No need for the "vulgar" for x in range(len(v1)) antipattern.






      share|improve this answer










      $endgroup$






















        2

















        $begingroup$

        Your span_orthogonal(vec) function is doing stuff from your other functions, so rather than rewriting the code, you can just use those functions:



        last_k = -dot_product(span_vector(dimension-1),vec[:-1])/vec[-1]


        However, your method of giving all but the last coordinate random values, and then calculating the last coordinate's value based on that, gives an error when the sum for the rest of the components. So you should find a nonzero coordinate, exit the function if none such exists, then find the dot product of the remaining coordinates, then check whether that's zero.



        try:
        nonzero_index, nonzero_value = next([(i,v) for (i,v) in enumerate(vec) if v)])
        except StopIteration:
        print("Vector must be nonzero.")
        return
        orthogonal_vec = span_vector(dimension-1)
        reduced_vec = vec.copy()
        reduced_vec.pop(nonzero_index)
        initial_product = -dot_product(orthogonal_vec,reduced_vector)
        if initial_product:
        orthogonal_vec.insert(nonzero_index,-initial_product/nonzero_value)
        else:
        orthogonal_vec.insert(non_zero_index,0)
        return orthogonal_vec





        share|improve this answer










        $endgroup$










        • 1




          $begingroup$
          My friends Gram and Schmidt also have a nice method to suggest for this task.
          $endgroup$
          – Federico Poloni
          Sep 23 at 16:37












        Your Answer






        StackExchange.ifUsing("editor", function ()
        StackExchange.using("externalEditor", function ()
        StackExchange.using("snippets", function ()
        StackExchange.snippets.init();
        );
        );
        , "code-snippets");

        StackExchange.ready(function()
        var channelOptions =
        tags: "".split(" "),
        id: "196"
        ;
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function()
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled)
        StackExchange.using("snippets", function()
        createEditor();
        );

        else
        createEditor();

        );

        function createEditor()
        StackExchange.prepareEditor(
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: false,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: null,
        bindNavPrevention: true,
        postfix: "",
        imageUploader:
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        ,
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        );



        );














        draft saved

        draft discarded
















        StackExchange.ready(
        function ()
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f229244%2falgorithm-that-spans-orthogonal-vectors-python%23new-answer', 'question_page');

        );

        Post as a guest















        Required, but never shown


























        5 Answers
        5






        active

        oldest

        votes








        5 Answers
        5






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        11

















        $begingroup$

        You should probably be using Numpy, although I don't know enough about your situation to comment any further.



        Assuming that you need to retain "pure Python", the following improvements can be made:



        Negation



        Replace (-1)* with -



        Generators



        Replace your for k in range(dimension-1): loop with



        orthogonal_vec = [
        random.randrange(-1000,1000)
        for _ in range(dimension-1)
        ]


        Type hints



        n: int, vec: typing.Sequence[float] (probably) . And the first two functions return -> typing.List[float]. cross_product both accepts and returns float.



        Inner list



        sum([ ... ])


        shouldn't use an inner list. Just pass the generator directly to sum.






        share|improve this answer












        $endgroup$



















          11

















          $begingroup$

          You should probably be using Numpy, although I don't know enough about your situation to comment any further.



          Assuming that you need to retain "pure Python", the following improvements can be made:



          Negation



          Replace (-1)* with -



          Generators



          Replace your for k in range(dimension-1): loop with



          orthogonal_vec = [
          random.randrange(-1000,1000)
          for _ in range(dimension-1)
          ]


          Type hints



          n: int, vec: typing.Sequence[float] (probably) . And the first two functions return -> typing.List[float]. cross_product both accepts and returns float.



          Inner list



          sum([ ... ])


          shouldn't use an inner list. Just pass the generator directly to sum.






          share|improve this answer












          $endgroup$

















            11















            11











            11







            $begingroup$

            You should probably be using Numpy, although I don't know enough about your situation to comment any further.



            Assuming that you need to retain "pure Python", the following improvements can be made:



            Negation



            Replace (-1)* with -



            Generators



            Replace your for k in range(dimension-1): loop with



            orthogonal_vec = [
            random.randrange(-1000,1000)
            for _ in range(dimension-1)
            ]


            Type hints



            n: int, vec: typing.Sequence[float] (probably) . And the first two functions return -> typing.List[float]. cross_product both accepts and returns float.



            Inner list



            sum([ ... ])


            shouldn't use an inner list. Just pass the generator directly to sum.






            share|improve this answer












            $endgroup$



            You should probably be using Numpy, although I don't know enough about your situation to comment any further.



            Assuming that you need to retain "pure Python", the following improvements can be made:



            Negation



            Replace (-1)* with -



            Generators



            Replace your for k in range(dimension-1): loop with



            orthogonal_vec = [
            random.randrange(-1000,1000)
            for _ in range(dimension-1)
            ]


            Type hints



            n: int, vec: typing.Sequence[float] (probably) . And the first two functions return -> typing.List[float]. cross_product both accepts and returns float.



            Inner list



            sum([ ... ])


            shouldn't use an inner list. Just pass the generator directly to sum.







            share|improve this answer















            share|improve this answer




            share|improve this answer








            edited Sep 18 at 13:56

























            answered Sep 18 at 13:49









            ReinderienReinderien

            12.7k22 silver badges50 bronze badges




            12.7k22 silver badges50 bronze badges


























                10

















                $begingroup$

                This is only a minor observation on top of what @Reinderien already wrote about your code.



                Writing function documentation like you did with



                def span_orthogonal(vec):
                '''vec represents n-dimensional vector'''
                '''Function spans an arbitrary vector that is orthogonal to vec'''


                does not work as expected.



                If you were to use help(span_orthogonal) you'd see



                Help on function span_orthogonal in module __main__:

                span_orthogonal(vec)
                vec represents n-dimensional vector


                The reason is that only the first block of text is interpreted as documentation. Also the usual convention is to write documentation "the other way round", by which I mean first give a short summary on what your function does, than go on to provide details such as the expected input. Both aspects can also be found in the infamous official Style Guide for Python Code (aka PEP 8) in the section on documentation strings.



                With



                def span_orthogonal(vec):
                '''Function spans an arbitrary vector that is orthogonal to vec

                vec represents n-dimensional vector
                '''


                calling help(...) gives you



                Help on function span_orthogonal in module __main__:

                span_orthogonal(vec)
                Function spans an arbitrary vector that is orthogonal to vec

                vec represents n-dimensional vector


                Also since @Reinderien also hinted you towards numpy, just let me tell you that there is also "special" documentation convention (aka numpydoc) often used in the scientific Python stack.



                An example:



                def span_orthogonal(vec):
                '''Function spans an arbitrary vector that is orthogonal to vec

                Parameters
                ----------
                vec : array_like
                represents n-dimensional vector
                '''


                This style is closer to what's possible with type hints in current versions of Python, as in that it's more structured. The idea behind numpydoc is to facilitate automated documentation generation using tools like Sphinx, but this goes a little bit beyond what I was trying to convey here.






                share|improve this answer










                $endgroup$














                • $begingroup$
                  That's a very useful information. Thank you!
                  $endgroup$
                  – Nelver
                  Sep 18 at 14:54















                10

















                $begingroup$

                This is only a minor observation on top of what @Reinderien already wrote about your code.



                Writing function documentation like you did with



                def span_orthogonal(vec):
                '''vec represents n-dimensional vector'''
                '''Function spans an arbitrary vector that is orthogonal to vec'''


                does not work as expected.



                If you were to use help(span_orthogonal) you'd see



                Help on function span_orthogonal in module __main__:

                span_orthogonal(vec)
                vec represents n-dimensional vector


                The reason is that only the first block of text is interpreted as documentation. Also the usual convention is to write documentation "the other way round", by which I mean first give a short summary on what your function does, than go on to provide details such as the expected input. Both aspects can also be found in the infamous official Style Guide for Python Code (aka PEP 8) in the section on documentation strings.



                With



                def span_orthogonal(vec):
                '''Function spans an arbitrary vector that is orthogonal to vec

                vec represents n-dimensional vector
                '''


                calling help(...) gives you



                Help on function span_orthogonal in module __main__:

                span_orthogonal(vec)
                Function spans an arbitrary vector that is orthogonal to vec

                vec represents n-dimensional vector


                Also since @Reinderien also hinted you towards numpy, just let me tell you that there is also "special" documentation convention (aka numpydoc) often used in the scientific Python stack.



                An example:



                def span_orthogonal(vec):
                '''Function spans an arbitrary vector that is orthogonal to vec

                Parameters
                ----------
                vec : array_like
                represents n-dimensional vector
                '''


                This style is closer to what's possible with type hints in current versions of Python, as in that it's more structured. The idea behind numpydoc is to facilitate automated documentation generation using tools like Sphinx, but this goes a little bit beyond what I was trying to convey here.






                share|improve this answer










                $endgroup$














                • $begingroup$
                  That's a very useful information. Thank you!
                  $endgroup$
                  – Nelver
                  Sep 18 at 14:54













                10















                10











                10







                $begingroup$

                This is only a minor observation on top of what @Reinderien already wrote about your code.



                Writing function documentation like you did with



                def span_orthogonal(vec):
                '''vec represents n-dimensional vector'''
                '''Function spans an arbitrary vector that is orthogonal to vec'''


                does not work as expected.



                If you were to use help(span_orthogonal) you'd see



                Help on function span_orthogonal in module __main__:

                span_orthogonal(vec)
                vec represents n-dimensional vector


                The reason is that only the first block of text is interpreted as documentation. Also the usual convention is to write documentation "the other way round", by which I mean first give a short summary on what your function does, than go on to provide details such as the expected input. Both aspects can also be found in the infamous official Style Guide for Python Code (aka PEP 8) in the section on documentation strings.



                With



                def span_orthogonal(vec):
                '''Function spans an arbitrary vector that is orthogonal to vec

                vec represents n-dimensional vector
                '''


                calling help(...) gives you



                Help on function span_orthogonal in module __main__:

                span_orthogonal(vec)
                Function spans an arbitrary vector that is orthogonal to vec

                vec represents n-dimensional vector


                Also since @Reinderien also hinted you towards numpy, just let me tell you that there is also "special" documentation convention (aka numpydoc) often used in the scientific Python stack.



                An example:



                def span_orthogonal(vec):
                '''Function spans an arbitrary vector that is orthogonal to vec

                Parameters
                ----------
                vec : array_like
                represents n-dimensional vector
                '''


                This style is closer to what's possible with type hints in current versions of Python, as in that it's more structured. The idea behind numpydoc is to facilitate automated documentation generation using tools like Sphinx, but this goes a little bit beyond what I was trying to convey here.






                share|improve this answer










                $endgroup$



                This is only a minor observation on top of what @Reinderien already wrote about your code.



                Writing function documentation like you did with



                def span_orthogonal(vec):
                '''vec represents n-dimensional vector'''
                '''Function spans an arbitrary vector that is orthogonal to vec'''


                does not work as expected.



                If you were to use help(span_orthogonal) you'd see



                Help on function span_orthogonal in module __main__:

                span_orthogonal(vec)
                vec represents n-dimensional vector


                The reason is that only the first block of text is interpreted as documentation. Also the usual convention is to write documentation "the other way round", by which I mean first give a short summary on what your function does, than go on to provide details such as the expected input. Both aspects can also be found in the infamous official Style Guide for Python Code (aka PEP 8) in the section on documentation strings.



                With



                def span_orthogonal(vec):
                '''Function spans an arbitrary vector that is orthogonal to vec

                vec represents n-dimensional vector
                '''


                calling help(...) gives you



                Help on function span_orthogonal in module __main__:

                span_orthogonal(vec)
                Function spans an arbitrary vector that is orthogonal to vec

                vec represents n-dimensional vector


                Also since @Reinderien also hinted you towards numpy, just let me tell you that there is also "special" documentation convention (aka numpydoc) often used in the scientific Python stack.



                An example:



                def span_orthogonal(vec):
                '''Function spans an arbitrary vector that is orthogonal to vec

                Parameters
                ----------
                vec : array_like
                represents n-dimensional vector
                '''


                This style is closer to what's possible with type hints in current versions of Python, as in that it's more structured. The idea behind numpydoc is to facilitate automated documentation generation using tools like Sphinx, but this goes a little bit beyond what I was trying to convey here.







                share|improve this answer













                share|improve this answer




                share|improve this answer










                answered Sep 18 at 14:48









                AlexVAlexV

                5,6002 gold badges15 silver badges39 bronze badges




                5,6002 gold badges15 silver badges39 bronze badges














                • $begingroup$
                  That's a very useful information. Thank you!
                  $endgroup$
                  – Nelver
                  Sep 18 at 14:54
















                • $begingroup$
                  That's a very useful information. Thank you!
                  $endgroup$
                  – Nelver
                  Sep 18 at 14:54















                $begingroup$
                That's a very useful information. Thank you!
                $endgroup$
                – Nelver
                Sep 18 at 14:54




                $begingroup$
                That's a very useful information. Thank you!
                $endgroup$
                – Nelver
                Sep 18 at 14:54











                5

















                $begingroup$

                Besides what @Reinderein and @AlexV already mentioned, you could have added the following to your code to deliver a complete runnable example:



                at the top:



                import random


                at he bottom something like:



                def main():
                v1 = span_vector(3)
                v2 = span_orthogonal(v1)
                print(v1)
                print(v2)
                print(cross_product(v1,v2))

                if __name__ == '__main__':
                main()


                For the 1000's (and in -1000) you could use a 'constant':



                MAX_COOR_VAL = 1000


                The definition of (cross)dot_product(v1,v2) could be made a bit clearer and more consistent with span_orthogonal(vec):



                def dot_product(vec1, vec2):


                The method span_orthogonal(vec) is not bulletproof, it might result in a ZeroDivisionError exception when vec equals [1,0] and the random creation of orthogonal_vec happens to be [1] (or [2])






                share|improve this answer










                $endgroup$



















                  5

















                  $begingroup$

                  Besides what @Reinderein and @AlexV already mentioned, you could have added the following to your code to deliver a complete runnable example:



                  at the top:



                  import random


                  at he bottom something like:



                  def main():
                  v1 = span_vector(3)
                  v2 = span_orthogonal(v1)
                  print(v1)
                  print(v2)
                  print(cross_product(v1,v2))

                  if __name__ == '__main__':
                  main()


                  For the 1000's (and in -1000) you could use a 'constant':



                  MAX_COOR_VAL = 1000


                  The definition of (cross)dot_product(v1,v2) could be made a bit clearer and more consistent with span_orthogonal(vec):



                  def dot_product(vec1, vec2):


                  The method span_orthogonal(vec) is not bulletproof, it might result in a ZeroDivisionError exception when vec equals [1,0] and the random creation of orthogonal_vec happens to be [1] (or [2])






                  share|improve this answer










                  $endgroup$

















                    5















                    5











                    5







                    $begingroup$

                    Besides what @Reinderein and @AlexV already mentioned, you could have added the following to your code to deliver a complete runnable example:



                    at the top:



                    import random


                    at he bottom something like:



                    def main():
                    v1 = span_vector(3)
                    v2 = span_orthogonal(v1)
                    print(v1)
                    print(v2)
                    print(cross_product(v1,v2))

                    if __name__ == '__main__':
                    main()


                    For the 1000's (and in -1000) you could use a 'constant':



                    MAX_COOR_VAL = 1000


                    The definition of (cross)dot_product(v1,v2) could be made a bit clearer and more consistent with span_orthogonal(vec):



                    def dot_product(vec1, vec2):


                    The method span_orthogonal(vec) is not bulletproof, it might result in a ZeroDivisionError exception when vec equals [1,0] and the random creation of orthogonal_vec happens to be [1] (or [2])






                    share|improve this answer










                    $endgroup$



                    Besides what @Reinderein and @AlexV already mentioned, you could have added the following to your code to deliver a complete runnable example:



                    at the top:



                    import random


                    at he bottom something like:



                    def main():
                    v1 = span_vector(3)
                    v2 = span_orthogonal(v1)
                    print(v1)
                    print(v2)
                    print(cross_product(v1,v2))

                    if __name__ == '__main__':
                    main()


                    For the 1000's (and in -1000) you could use a 'constant':



                    MAX_COOR_VAL = 1000


                    The definition of (cross)dot_product(v1,v2) could be made a bit clearer and more consistent with span_orthogonal(vec):



                    def dot_product(vec1, vec2):


                    The method span_orthogonal(vec) is not bulletproof, it might result in a ZeroDivisionError exception when vec equals [1,0] and the random creation of orthogonal_vec happens to be [1] (or [2])







                    share|improve this answer













                    share|improve this answer




                    share|improve this answer










                    answered Sep 18 at 17:38









                    Jan KuikenJan Kuiken

                    1,0654 silver badges8 bronze badges




                    1,0654 silver badges8 bronze badges
























                        5

















                        $begingroup$

                        It would be more Pythonic to use zip() in your cross_product(v1, v2) dot_product(v1, v2) function:



                         return sum(a * b for a, b in zip(v1, v2))


                        This iterates over both vectors simultaneously, extracting one component from each, and calling those components a and b respectively ... and multiplying them together and summing them as normal. No need for the "vulgar" for x in range(len(v1)) antipattern.






                        share|improve this answer










                        $endgroup$



















                          5

















                          $begingroup$

                          It would be more Pythonic to use zip() in your cross_product(v1, v2) dot_product(v1, v2) function:



                           return sum(a * b for a, b in zip(v1, v2))


                          This iterates over both vectors simultaneously, extracting one component from each, and calling those components a and b respectively ... and multiplying them together and summing them as normal. No need for the "vulgar" for x in range(len(v1)) antipattern.






                          share|improve this answer










                          $endgroup$

















                            5















                            5











                            5







                            $begingroup$

                            It would be more Pythonic to use zip() in your cross_product(v1, v2) dot_product(v1, v2) function:



                             return sum(a * b for a, b in zip(v1, v2))


                            This iterates over both vectors simultaneously, extracting one component from each, and calling those components a and b respectively ... and multiplying them together and summing them as normal. No need for the "vulgar" for x in range(len(v1)) antipattern.






                            share|improve this answer










                            $endgroup$



                            It would be more Pythonic to use zip() in your cross_product(v1, v2) dot_product(v1, v2) function:



                             return sum(a * b for a, b in zip(v1, v2))


                            This iterates over both vectors simultaneously, extracting one component from each, and calling those components a and b respectively ... and multiplying them together and summing them as normal. No need for the "vulgar" for x in range(len(v1)) antipattern.







                            share|improve this answer













                            share|improve this answer




                            share|improve this answer










                            answered Sep 18 at 20:41









                            AJNeufeldAJNeufeld

                            14.8k1 gold badge13 silver badges44 bronze badges




                            14.8k1 gold badge13 silver badges44 bronze badges
























                                2

















                                $begingroup$

                                Your span_orthogonal(vec) function is doing stuff from your other functions, so rather than rewriting the code, you can just use those functions:



                                last_k = -dot_product(span_vector(dimension-1),vec[:-1])/vec[-1]


                                However, your method of giving all but the last coordinate random values, and then calculating the last coordinate's value based on that, gives an error when the sum for the rest of the components. So you should find a nonzero coordinate, exit the function if none such exists, then find the dot product of the remaining coordinates, then check whether that's zero.



                                try:
                                nonzero_index, nonzero_value = next([(i,v) for (i,v) in enumerate(vec) if v)])
                                except StopIteration:
                                print("Vector must be nonzero.")
                                return
                                orthogonal_vec = span_vector(dimension-1)
                                reduced_vec = vec.copy()
                                reduced_vec.pop(nonzero_index)
                                initial_product = -dot_product(orthogonal_vec,reduced_vector)
                                if initial_product:
                                orthogonal_vec.insert(nonzero_index,-initial_product/nonzero_value)
                                else:
                                orthogonal_vec.insert(non_zero_index,0)
                                return orthogonal_vec





                                share|improve this answer










                                $endgroup$










                                • 1




                                  $begingroup$
                                  My friends Gram and Schmidt also have a nice method to suggest for this task.
                                  $endgroup$
                                  – Federico Poloni
                                  Sep 23 at 16:37















                                2

















                                $begingroup$

                                Your span_orthogonal(vec) function is doing stuff from your other functions, so rather than rewriting the code, you can just use those functions:



                                last_k = -dot_product(span_vector(dimension-1),vec[:-1])/vec[-1]


                                However, your method of giving all but the last coordinate random values, and then calculating the last coordinate's value based on that, gives an error when the sum for the rest of the components. So you should find a nonzero coordinate, exit the function if none such exists, then find the dot product of the remaining coordinates, then check whether that's zero.



                                try:
                                nonzero_index, nonzero_value = next([(i,v) for (i,v) in enumerate(vec) if v)])
                                except StopIteration:
                                print("Vector must be nonzero.")
                                return
                                orthogonal_vec = span_vector(dimension-1)
                                reduced_vec = vec.copy()
                                reduced_vec.pop(nonzero_index)
                                initial_product = -dot_product(orthogonal_vec,reduced_vector)
                                if initial_product:
                                orthogonal_vec.insert(nonzero_index,-initial_product/nonzero_value)
                                else:
                                orthogonal_vec.insert(non_zero_index,0)
                                return orthogonal_vec





                                share|improve this answer










                                $endgroup$










                                • 1




                                  $begingroup$
                                  My friends Gram and Schmidt also have a nice method to suggest for this task.
                                  $endgroup$
                                  – Federico Poloni
                                  Sep 23 at 16:37













                                2















                                2











                                2







                                $begingroup$

                                Your span_orthogonal(vec) function is doing stuff from your other functions, so rather than rewriting the code, you can just use those functions:



                                last_k = -dot_product(span_vector(dimension-1),vec[:-1])/vec[-1]


                                However, your method of giving all but the last coordinate random values, and then calculating the last coordinate's value based on that, gives an error when the sum for the rest of the components. So you should find a nonzero coordinate, exit the function if none such exists, then find the dot product of the remaining coordinates, then check whether that's zero.



                                try:
                                nonzero_index, nonzero_value = next([(i,v) for (i,v) in enumerate(vec) if v)])
                                except StopIteration:
                                print("Vector must be nonzero.")
                                return
                                orthogonal_vec = span_vector(dimension-1)
                                reduced_vec = vec.copy()
                                reduced_vec.pop(nonzero_index)
                                initial_product = -dot_product(orthogonal_vec,reduced_vector)
                                if initial_product:
                                orthogonal_vec.insert(nonzero_index,-initial_product/nonzero_value)
                                else:
                                orthogonal_vec.insert(non_zero_index,0)
                                return orthogonal_vec





                                share|improve this answer










                                $endgroup$



                                Your span_orthogonal(vec) function is doing stuff from your other functions, so rather than rewriting the code, you can just use those functions:



                                last_k = -dot_product(span_vector(dimension-1),vec[:-1])/vec[-1]


                                However, your method of giving all but the last coordinate random values, and then calculating the last coordinate's value based on that, gives an error when the sum for the rest of the components. So you should find a nonzero coordinate, exit the function if none such exists, then find the dot product of the remaining coordinates, then check whether that's zero.



                                try:
                                nonzero_index, nonzero_value = next([(i,v) for (i,v) in enumerate(vec) if v)])
                                except StopIteration:
                                print("Vector must be nonzero.")
                                return
                                orthogonal_vec = span_vector(dimension-1)
                                reduced_vec = vec.copy()
                                reduced_vec.pop(nonzero_index)
                                initial_product = -dot_product(orthogonal_vec,reduced_vector)
                                if initial_product:
                                orthogonal_vec.insert(nonzero_index,-initial_product/nonzero_value)
                                else:
                                orthogonal_vec.insert(non_zero_index,0)
                                return orthogonal_vec






                                share|improve this answer













                                share|improve this answer




                                share|improve this answer










                                answered Sep 19 at 18:34









                                AcccumulationAcccumulation

                                1,1552 silver badges5 bronze badges




                                1,1552 silver badges5 bronze badges










                                • 1




                                  $begingroup$
                                  My friends Gram and Schmidt also have a nice method to suggest for this task.
                                  $endgroup$
                                  – Federico Poloni
                                  Sep 23 at 16:37












                                • 1




                                  $begingroup$
                                  My friends Gram and Schmidt also have a nice method to suggest for this task.
                                  $endgroup$
                                  – Federico Poloni
                                  Sep 23 at 16:37







                                1




                                1




                                $begingroup$
                                My friends Gram and Schmidt also have a nice method to suggest for this task.
                                $endgroup$
                                – Federico Poloni
                                Sep 23 at 16:37




                                $begingroup$
                                My friends Gram and Schmidt also have a nice method to suggest for this task.
                                $endgroup$
                                – Federico Poloni
                                Sep 23 at 16:37


















                                draft saved

                                draft discarded















































                                Thanks for contributing an answer to Code Review Stack Exchange!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid


                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.

                                Use MathJax to format equations. MathJax reference.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function ()
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f229244%2falgorithm-that-spans-orthogonal-vectors-python%23new-answer', 'question_page');

                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown









                                Popular posts from this blog

                                Tamil (spriik) Luke uk diar | Nawigatjuun

                                Align equal signs while including text over equalitiesAMS align: left aligned text/math plus multicolumn alignmentMultiple alignmentsAligning equations in multiple placesNumbering and aligning an equation with multiple columnsHow to align one equation with another multline equationUsing \ in environments inside the begintabularxNumber equations and preserving alignment of equal signsHow can I align equations to the left and to the right?Double equation alignment problem within align enviromentAligned within align: Why are they right-aligned?

                                Where does the image of a data connector as a sharp metal spike originate from?Where does the concept of infected people turning into zombies only after death originate from?Where does the motif of a reanimated human head originate?Where did the notion that Dragons could speak originate?Where does the archetypal image of the 'Grey' alien come from?Where did the suffix '-Man' originate?Where does the notion of being injured or killed by an illusion originate?Where did the term “sophont” originate?Where does the trope of magic spells being driven by advanced technology originate from?Where did the term “the living impaired” originate?