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;
$begingroup$
The code consists of three functions:
Spans arbitrary vector (takes dimension as an argument)
Spans vector orthogonal to the one passed in the argument
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
$endgroup$
add a comment
|
$begingroup$
The code consists of three functions:
Spans arbitrary vector (takes dimension as an argument)
Spans vector orthogonal to the one passed in the argument
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
$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 namesspan_vector
andspan_orthogonal
are appropriate (sth. likegenerate_vector
should be fine); (2) if it is not required thatspan_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
add a comment
|
$begingroup$
The code consists of three functions:
Spans arbitrary vector (takes dimension as an argument)
Spans vector orthogonal to the one passed in the argument
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
$endgroup$
The code consists of three functions:
Spans arbitrary vector (takes dimension as an argument)
Spans vector orthogonal to the one passed in the argument
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
python coordinate-system
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 namesspan_vector
andspan_orthogonal
are appropriate (sth. likegenerate_vector
should be fine); (2) if it is not required thatspan_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
add a comment
|
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 namesspan_vector
andspan_orthogonal
are appropriate (sth. likegenerate_vector
should be fine); (2) if it is not required thatspan_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
add a comment
|
5 Answers
5
active
oldest
votes
$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
.
$endgroup$
add a comment
|
$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.
$endgroup$
$begingroup$
That's a very useful information. Thank you!
$endgroup$
– Nelver
Sep 18 at 14:54
add a comment
|
$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]
)
$endgroup$
add a comment
|
$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.
$endgroup$
add a comment
|
$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
$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
add a comment
|
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
$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
.
$endgroup$
add a comment
|
$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
.
$endgroup$
add a comment
|
$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
.
$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
.
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
add a comment
|
add a comment
|
$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.
$endgroup$
$begingroup$
That's a very useful information. Thank you!
$endgroup$
– Nelver
Sep 18 at 14:54
add a comment
|
$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.
$endgroup$
$begingroup$
That's a very useful information. Thank you!
$endgroup$
– Nelver
Sep 18 at 14:54
add a comment
|
$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.
$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.
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
add a comment
|
$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
add a comment
|
$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]
)
$endgroup$
add a comment
|
$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]
)
$endgroup$
add a comment
|
$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]
)
$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]
)
answered Sep 18 at 17:38
Jan KuikenJan Kuiken
1,0654 silver badges8 bronze badges
1,0654 silver badges8 bronze badges
add a comment
|
add a comment
|
$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.
$endgroup$
add a comment
|
$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.
$endgroup$
add a comment
|
$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.
$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.
answered Sep 18 at 20:41
AJNeufeldAJNeufeld
14.8k1 gold badge13 silver badges44 bronze badges
14.8k1 gold badge13 silver badges44 bronze badges
add a comment
|
add a comment
|
$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
$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
add a comment
|
$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
$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
add a comment
|
$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
$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
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
add a comment
|
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
add a comment
|
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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
andspan_orthogonal
are appropriate (sth. likegenerate_vector
should be fine); (2) if it is not required thatspan_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