Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help to find a command
#1
Hi everyone,
I am new in coding and struggling to to find a way for the following.
Can someone help me with some commands (I will study it in details then) to help me if this case.

I have have a list like this
a = [[10, 20], [30, 60], [[50, 200]]

I will create a variable (b) which will increase from ZERO until the smallest value of a[x][1].. When this variable reaches it, then I will a.append(0) or if it increase 100 times and do not reach any number, then the program stops

For example
b = 1
is b > 20 i.e a[0][1] NO
is b > 40 NO
is b > 60 NO
then
b = 2
..
b = 21
is b > 20 YES
then
a = [[10, 20, 0], [30, 40], [[50, 60]]

I am trying this:
a = [[10, 20], [30, 40], [50, 60]]
z = 0
b = 0
while z < 100:
if b > a[z][1]:
a[z].append(0)
z = 0
z += 1
b += 1
print (a)

The real case is one sample with many defects, I will test it by increasing the stress until one defect fail, at the end I will now how many defect failed by looking which one has the ZERO at the end.

Thank you!
Reply
#2
Use a for loop instead of while:

a = [[10, 20], [30, 40], [50, 60]]
b = 0

for entry in a:
    if b > entry[1]:
        entry.append(0)

    b += 1
    
print (a)
However, I don't believe this accomplishes the objective. This (and the code you provided) can only iterate over "a" once. It appears that you want to iterate indefinitely until you find the list with the smallest value less than 101. To do that, you need a nested loop.

b = 0

while b < 101:
    for entry in a:
       pass
As I understand your objective, a loop is less than ideal. A function that finds the minimum value and another than indexes that value would likely be more effective. The reason being that the nested loop above with a list a = [[0, 102],[1, 512],[1, 200]] will loop 300 times before exiting. Whereas, the functions mentioned above would only loop twice.
Reply
#3
I am ready to try to help but I can't understand what is the desired output. There is solution presented but I couldn't find the description of the problem.
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#4
Hi there!
First of all. Sorry to don't use the forum writing rules.

Let me describe better the case.

This example bellow is the simplest way I found to explain. Otherwise will take so long.
I need to test in tension one chain, the chain will have a random number of links and each link will have a random strength property. I need to number (location) each link to know where it broke based on its strength. I will increase the stress step by step. Each increase I need to very if any broke, if so, add '0' at the link list. This was the easiest way to define where did it broke (any other suggestion?)
I am thinking to use list to do it.
a: chain; b: link; c: strength; d: location; e: broke?
a = [[c1, d1], [c2, d2, c2], [c3, d3], [c4, d4], [c5, d5, e5]
I this case the chain 'a' has 5 links 'b' and after the test the links 2 and 5 broke. This would be the result.

As I do not know many python commands, I am trying to do it with while command. However if anyone can tell me other good commands, I will search and learn to use it.

a = [[10, 20], [30, 40], [50, 60]]

z = 0
x = 0
while z < 100:
    if x > a[z][1]:
        a[z].append(0)
        z = 0
    z += 1
    x += 1
print (a)


This was my attempt. After 100 times incresing the stress without any break, the program stops. When the stress (x) reach one strength, this link will break and a "0" will be add at the end of this link list.

Hope it make my question more clear.

(Feb-02-2019, 04:15 PM)stullis Wrote: Use a for loop instead of while:

a = [[10, 20], [30, 40], [50, 60]]
b = 0

for entry in a:
    if b > entry[1]:
        entry.append(0)

    b += 1
    
print (a)
However, I don't believe this accomplishes the objective. This (and the code you provided) can only iterate over "a" once. It appears that you want to iterate indefinitely until you find the list with the smallest value less than 101. To do that, you need a nested loop.

b = 0

while b < 101:
    for entry in a:
       pass
As I understand your objective, a loop is less than ideal. A function that finds the minimum value and another than indexes that value would likely be more effective. The reason being that the nested loop above with a list a = [[0, 102],[1, 512],[1, 200]] will loop 300 times before exiting. Whereas, the functions mentioned above would only loop twice.

Thank you.
I am going to have a look in nested loop.

Which function do you mean below?
"A function that finds the minimum value and another than indexes that value would likely be more effective."
Reply
#5
I still feel that description of the problem and your idea how to solve it are mixed.

How I understand the problem: you have list which consists lists as elements. List represents chain and element lists represent links. Links are represented with integer pair where first number indicates strength and second location. It can be expressed something like that (this ain't code, this is visualisation of data with descriptive names):

chain = link_1: (strength, location), link_2: (strength, location)...

You apply tension (which is integer) to chain and need to know which links will break. Link will break only when tension is larger than strength i.e if they are equal chain stays in one piece.

Sidenote: it puzzles me that if first link of chain breaks then the chain is broken and it can't break in another link (but I don't know the whole picture)

I am wondering whether it makes point to find weakest link? There is no point to compare tension and strength if we know that tension is smaller. We can find strengths of all links (it assumes that strength is first integer, in you first post strength seemed to be second integer):

In [1]: chain = [[10, 20], [30, 40], [50, 60]]

In [2]: [link[0] for link in chain]        # give me first element of every link in chain
Out[2]: [10, 30, 50]

In [3]: min([link[0] for link in chain])   # find the smallest value i.e. strength of weakest link
Out[3]: 10
If I know this value (strength of weakest link) I know that it is kind of pointless to compare with tension values <= 10.

Now to the tension. What do you actually need to know? At which tension link will not hold anymore and chain will be broken? You can just min + 1 and have your answer. If you have fixed tension then one should compare strength to tension to find out whether it will break or not.

If you need the location of weakest link:

In [4]: min([(link[0], i) for i, link in enumerate(chain)])
Out[4]: (10, 0)
Weakest link in chain is at index 0 (first element) with value 10.

If you need compare all links to some arbitrary tension, let's say 35:

In [5]: tension = 35

In [6]: [(link[0], i) for i, link in enumerate(chain) if tension > link[0]]
Out[6]: [(10, 0), (30, 1)]
Links at index position 0 and 1 will break.

I personally think that appending some value to link is not good idea. If you know location of the 'broken' links you can access them by their location. However, if it is needed:

In [7]: [link +  [0] if tension > link[0] else link for link in chain]
Out[7]: [[10, 20, 0], [30, 40, 0], [50, 60]]
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#6
(Feb-03-2019, 12:51 PM)perfringo Wrote: I still feel that description of the problem and your idea how to solve it are mixed.

How I understand the problem: you have list which consists lists as elements. List represents chain and element lists represent links. Links are represented with integer pair where first number indicates strength and second location. It can be expressed something like that (this ain't code, this is visualisation of data with descriptive names):

chain = link_1: (strength, location), link_2: (strength, location)...

You apply tension (which is integer) to chain and need to know which links will break. Link will break only when tension is larger than strength i.e if they are equal chain stays in one piece.

Sidenote: it puzzles me that if first link of chain breaks then the chain is broken and it can't break in another link (but I don't know the whole picture)

I am wondering whether it makes point to find weakest link? There is no point to compare tension and strength if we know that tension is smaller. We can find strengths of all links (it assumes that strength is first integer, in you first post strength seemed to be second integer):

In [1]: chain = [[10, 20], [30, 40], [50, 60]]

In [2]: [link[0] for link in chain]        # give me first element of every link in chain
Out[2]: [10, 30, 50]

In [3]: min([link[0] for link in chain])   # find the smallest value i.e. strength of weakest link
Out[3]: 10
If I know this value (strength of weakest link) I know that it is kind of pointless to compare with tension values <= 10.

Now to the tension. What do you actually need to know? At which tension link will not hold anymore and chain will be broken? You can just min + 1 and have your answer. If you have fixed tension then one should compare strength to tension to find out whether it will break or not.

If you need the location of weakest link:

In [4]: min([(link[0], i) for i, link in enumerate(chain)])
Out[4]: (10, 0)
Weakest link in chain is at index 0 (first element) with value 10.

If you need compare all links to some arbitrary tension, let's say 35:

In [5]: tension = 35

In [6]: [(link[0], i) for i, link in enumerate(chain) if tension > link[0]]
Out[6]: [(10, 0), (30, 1)]
Links at index position 0 and 1 will break.

I personally think that appending some value to link is not good idea. If you know location of the 'broken' links you can access them by their location. However, if it is needed:

In [7]: [link +  [0] if tension > link[0] else link for link in chain]
Out[7]: [[10, 20, 0], [30, 40, 0], [50, 60]]

Thank you for your help. I am leaning a lot.

As I said, the situation is more complicated then the "chain" example. The real case is a fiber composite (one fiber embedded by polymer) with random flaws in it (with random strength at random position). Each flaw can be considered as a link, and while I am increasing the tensile, the fiber will break at that flaw strength and so one. However the area around the break need to be treated differently. For that reason I need to increase the tensile step by step, when one break occurs, I will need to modify the local property. But lets comeback to python hehe.

Now my problem is to increase the tensile one by one and as soon it reaches one link strength, this link shall append 1.

Feel free to suggest any python function that suits better. I go and check how to use it.

I am trying this with "while" but it is not working.

In the bellow example, the break will stop when the is a gap bigger than 10 between 2 link strength.
For example: [[77, 2], [16, 5], [36, 11], [7, 12], [93, 15], [42, 17], [82, 18], [33, 33], [79, 42], [94, 43]]
the result would be:
[[77, 2], [16, 5, 1], [36, 11], [7, 12, 1], [93, 15], [42, 17], [82, 18], [33, 33], [79, 42], [94, 43]]

import random
import operator

chain = []

for x in range (10):
    link = []
    s = random.randint (0, 100)
    link.append (s)
    l = random.randint (0, 50)
    link.append (l)
    chain.append (link)
print (chain)

print ([link[0] for link in chain])

print (max([link[0] for link in chain]))

chain.sort(key = operator.itemgetter(1))
print (chain) 

tension = 0
cont = 0
while (cont < 10):  
    for link in chain:
        if tension > link[0]:
            link.append(1)
            cont = 0
        else:   
            cont += 1
    tension += 1
print (chain)
Reply
#7
(Feb-04-2019, 08:01 AM)andre_fermart Wrote: In the bellow example, the break will stop when the is a gap bigger than 10 between 2 link strength.
For example: [[77, 2], [16, 5], [36, 11], [7, 12], [93, 15], [42, 17], [82, 18], [33, 33], [79, 42], [94, 43]]
the result would be:
[[77, 2], [16, 5, 1], [36, 11], [7, 12, 1], [93, 15], [42, 17], [82, 18], [33, 33], [79, 42], [94, 43]]

What constitutes a gap? If I look at two list in bold I don't see any corresponding values where gap is bigger than ten (16 - 7 = 9; 12 - 5 = 7).

I do see 36 - 16 > 10. Does it mean that 1 should be appended to next element after the element where gap is larger than 10?

I still don't get this tension stuff. Why should you iterate below min value of strength? Nothing happens while doing it.

I also noticed that you sorted list. Does it mean that order is not important?
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#8
(Feb-04-2019, 09:49 AM)perfringo Wrote:
(Feb-04-2019, 08:01 AM)andre_fermart Wrote: In the bellow example, the break will stop when the is a gap bigger than 10 between 2 link strength.
For example: [[77, 2], [16, 5], [36, 11], [7, 12], [93, 15], [42, 17], [82, 18], [33, 33], [79, 42], [94, 43]]
the result would be:
[[77, 2], [16, 5, 1], [36, 11], [7, 12, 1], [93, 15], [42, 17], [82, 18], [33, 33], [79, 42], [94, 43]]

What constitutes a gap? If I look at two list in bold I don't see any corresponding values where gap is bigger than ten (16 - 7 = 9; 12 - 5 = 7).

I do see 36 - 16 > 10. Does it mean that 1 should be appended to next element after the element where gap is larger than 10?

I still don't get this tension stuff. Why should you iterate below min value of strength? Nothing happens while doing it.

I also noticed that you sorted list. Does it mean that order is not important?

A gap in strength between two links.
The first number is the link strength the the second is its position. A gap comparing only link[0]. I sorted by position. Maybe the link example is becoming limited. Let´s use the fiber with flaw.
The fiber is 50 mm long and had 100 flaws in it(random strength and location along the 50 mm). As below.
The fiber strength is driven by the flaw strength at the position the flaw is. Where there is no flaw, the strength is so high that it will never fail and I do not take into consideration in my study.


for x in range (10):
    link = []
    s = random.randint (0, 100)
    link.append (s)
    l = random.randint (0, 50)
    link.append (l)
    chain.append (link)


I need to apply tensile stress in the fiber (it is embedded in a polymer matrix and for that reason it continue to break even after the first flaw failure). The matrix keep transferring stress to the fiber that keep failing as soon as the stress reach the flaw strength.

I need to make a loop of "increasing the stress" (MPa is the unit) and at each increment I need to check if any flaw failed. If so I will need to apply a stress function for the neighbors (imagine a situation that the neighbor will now require a higher stress to fail) but this is something I need to do consider in future, next thing to learn how to do. Not important now.

This loop, in order to do not go to infinite, I set to stop after a certain amount of increment without failure (I used 10 as example).

Does it make sense now?

Comming back to the links. There are 50 links (positions) but just some of them I will analyse (random location). I increment the stress 1 by 1.
Stress = 1 MPa, did any link break? No
Stress = 2...
Stress = 7, Yes (the link at position 12 with 7 strength broke, then [7, 12, 1]
At this stage count = stress = 7 but now cont = 0 and stress = 7
Stress = 8, cont = 1
Stress = 16, cont = 9..the link at position 5 broke; [16, 5, 1]
stress = 16 and cont = 0
Stress = 26 and cont = 10 program stops as count reached 10

I thought that my scrip below would run as the example above.

while (cont < 10):  
    for link in chain:
        if tension > link[0]:
            link.append(1)
            cont = 0
        else:   
            cont += 1
    tension += 1
Reply
#9
Sorry, but it doesn't click... You always append number 1, there is no way to determine in which order flaws occur. You can set tension to min value and find whether there are strengths which are some predefined range.

Something like that:

>>> fiber = [[77, 2], [16, 5], [36, 11], [7, 12], [93, 15], [42, 17], [82, 18], [33, 33], [79, 42], [94, 43]]
>>> tension = min(fiber, key=lambda x: x[0])[0]
>>> tension
7
>>> r = 10                # arbitrary range from breakpoint
>>> [strength + [1] if tension + r >= strength[0] else strength for strength in fiber]
[[77, 2],
 [16, 5, 1],
 [36, 11],
 [7, 12, 1],
 [93, 15],
 [42, 17],
 [82, 18],
 [33, 33],
 [79, 42],
 [94, 43]]
If r = 87 then 1 will be appended to all elements and nobody is any wiser.


Side observation:

- random.randint(0, 100) may include both 0 and 100:

>>> help(random.randint)
Help on method randint in module random:

randint(a, b) method of random.Random instance
    Return random integer in range [a, b], including both end points.
(END)
I believe that fiber cannot break at start and endpoint i.e. at length 0 and 100. In order to avoid surprises it's good to use range like (1, 99) or something.

EDIT: with subjectively better naming:

>>> [[strength, position, 1] if tension + r >= strength else [strength, position] for [strength, position] in fiber]
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#10
With every iteration find breakpoint (set tension to min value of strength) and add tension to start and iteration to end for links which will break. This results a list where first element indicates tension at which break occurs, second and third are strength and position respectively and fourth is 'batch no' in which breakage occurred:

from itertools import count

fiber = [[77, 2], [16, 5], [36, 11], [7, 12], [93, 15], [42, 17], [82, 18], [33, 33], [79, 42], [94, 43]]
r = 10


for i in count():
    try:
        tension = min([link for link in fiber if len(link) == 2],key=lambda x: x[0])[0]
        fiber = [[tension] + strength + [i+1] if tension + r > strength[0] and len(strength) == 2 else strength for strength in fiber ]
    except ValueError:
        break

sorted(fiber)

[[7, 7, 12, 1],
 [7, 16, 5, 1],
 [33, 33, 33, 2],
 [33, 36, 11, 2],
 [33, 42, 17, 2],
 [77, 77, 2, 3],
 [77, 79, 42, 3],
 [77, 82, 18, 3],
 [93, 93, 15, 4],
 [93, 94, 43, 4]] 
It's brute force but is it something along those lines you want to achieve?
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020