
    RiePo                         d Z ddlmZ ddlmZ ddlmZ ddlmZ ddl	m
Z
 ddlmZmZ ddlmZ dd	lmZ dd
lmZmZ  G d d          ZdS )zB
This module can be used to solve problems related
to 2D Trusses.
    )inf)Add)Mul)Symbol)sympify)Matrixpi)sqrt)zeros)sincosc                       e Zd ZdZd Zed             Zed             Zed             Zed             Z	ed             Z
ed             Zed	             Zed
             Zed             Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd ZdS )Trussa  
    A Truss is an assembly of members such as beams,
    connected by nodes, that create a rigid structure.
    In engineering, a truss is a structure that
    consists of two-force members only.

    Trusses are extremely important in engineering applications
    and can be seen in numerous real-world applications like bridges.

    Examples
    ========

    There is a Truss consisting of four nodes and five
    members connecting the nodes. A force P acts
    downward on the node D and there also exist pinned
    and roller joints on the nodes A and B respectively.

    .. image:: truss_example.png

    >>> from sympy.physics.continuum_mechanics.truss import Truss
    >>> t = Truss()
    >>> t.add_node("node_1", 0, 0)
    >>> t.add_node("node_2", 6, 0)
    >>> t.add_node("node_3", 2, 2)
    >>> t.add_node("node_4", 2, 0)
    >>> t.add_member("member_1", "node_1", "node_4")
    >>> t.add_member("member_2", "node_2", "node_4")
    >>> t.add_member("member_3", "node_1", "node_3")
    >>> t.add_member("member_4", "node_2", "node_3")
    >>> t.add_member("member_5", "node_3", "node_4")
    >>> t.apply_load("node_4", magnitude=10, direction=270)
    >>> t.apply_support("node_1", type="fixed")
    >>> t.apply_support("node_2", type="roller")
    c                     g | _         i | _        i | _        i | _        g | _        g | _        g | _        g | _        i | _        i | _	        i | _
        i | _        dS )z'
        Initializes the class
        N)_nodes_members_loads	_supports_node_labels_node_positions_node_position_x_node_position_y_nodes_occupied_reaction_loads_internal_forces_node_coordinatesselfs    Glib/python3.11/site-packages/sympy/physics/continuum_mechanics/truss.py__init__zTruss.__init__6   sf     ! " "!! "!#    c                     | j         S )zL
        Returns the nodes of the truss along with their positions.
        )r   r   s    r   nodeszTruss.nodesG       
 {r!   c                     | j         S )z7
        Returns the node labels of the truss.
        )r   r   s    r   node_labelszTruss.node_labelsN   s    
   r!   c                     | j         S )zB
        Returns the positions of the nodes of the truss.
        )r   r   s    r   node_positionszTruss.node_positionsU       
 ##r!   c                     | j         S zW
        Returns the members of the truss along with the start and end points.
        )r   r   s    r   memberszTruss.members\   s    
 }r!   c                     | j         S r+   )_member_labelsr   s    r   member_labelszTruss.member_labelsc   s    
 ""r!   c                     | j         S )z
        Returns the nodes with provided supports along with the kind of support provided i.e.
        pinned or roller.
        )r   r   s    r   supportszTruss.supportsj   s     ~r!   c                     | j         S )z8
        Returns the loads acting on the truss.
        )r   r   s    r   loadszTruss.loadsr   r$   r!   c                     | j         S )z^
        Returns the reaction forces for all supports which are all initialized to 0.
        )r   r   s    r   reaction_loadszTruss.reaction_loadsy   r)   r!   c                     | j         S )z]
        Returns the internal forces for all members which are all initialized to 0.
        )r   r   s    r   internal_forceszTruss.internal_forces   s    
 $$r!   c                 F   t          |          }t          |          }|| j        v rt          d          || j        v rN|| j        v rE| j                            |          | j                            |          k    rt          d          | j                            |||f           | j                            |           | j                            ||f           | j                            |           | j                            |           ||g| j	        |<   dS )a  
        This method adds a node to the truss along with its name/label and its location.

        Parameters
        ==========
        label:  String or a Symbol
            The label for a node. It is the only way to identify a particular node.

        x: Sympifyable
            The x-coordinate of the position of the node.

        y: Sympifyable
            The y-coordinate of the position of the node.

        Examples
        ========

        >>> from sympy.physics.continuum_mechanics.truss import Truss
        >>> t = Truss()
        >>> t.add_node('A', 0, 0)
        >>> t.nodes
        [('A', 0, 0)]
        >>> t.add_node('B', 3, 0)
        >>> t.nodes
        [('A', 0, 0), ('B', 3, 0)]
        z!Node needs to have a unique labelz+A node already exists at the given positionN)
r   r   
ValueErrorr   r   indexr   appendr   r   )r   labelxys       r   add_nodezTruss.add_node   sE   6 AJJAJJD%%%@AAA$'''A1F,F,F4K`KfKfghKiKiko  lA  lG  lG  HI  lJ  lJ  LJ  LJJKKK Kq!}---$$U+++ ''A///!((+++!((+++-.FD"5)))r!   c                    t          t          | j                            D ]-}| j        |         |k    r| j        |         }| j        |         }.|| j        vrt          d          | j                                        }|D ]?}|| j        |         d         k    s|| j        |         d         k    rt          d          @| j	        
                    |||f           | j        
                    |           | j        
                    ||f           | j        
                    |           | j        
                    |           |t          | j                  v r| j                            |           |t          | j                  v r| j                            |           | j                            |           dS )a%  
        This method removes a node from the truss.

        Parameters
        ==========
        label:  String or Symbol
            The label of the node to be removed.

        Examples
        ========

        >>> from sympy.physics.continuum_mechanics.truss import Truss
        >>> t = Truss()
        >>> t.add_node('A', 0, 0)
        >>> t.nodes
        [('A', 0, 0)]
        >>> t.add_node('B', 3, 0)
        >>> t.nodes
        [('A', 0, 0), ('B', 3, 0)]
        >>> t.remove_node('A')
        >>> t.nodes
        [('B', 3, 0)]
        z No such node exists in the trussr      z1The node given has members already attached to itN)rangelenr#   r   r   r   r9   r   copyr   remover   listr   popr   r   )r   r<   ir=   r>   members_duplicatemembers          r   remove_nodezTruss.remove_node   s   0 s4:'' 	- 	-A #u,,)!,)!,)))?@@@ !% 2 2 4 4+ Z ZDM&1!444vAVWXAY8Y8Y$%XYYY 9ZKq!}---$$U+++ ''A///!((+++!((+++T[))))&&&T^,,,,""5)))"&&u-----r!   c                 P   || j         vs|| j         vs||k    rt          d          |t          | j                  v rt          d          | j                            ||f          rt          d          ||g| j        |<   d| j        ||f<   d| j        ||f<   d| j        |<   dS )a  
        This method adds a member between any two nodes in the given truss.

        Parameters
        ==========
        label: String or Symbol
            The label for a member. It is the only way to identify a particular member.

        start: String or Symbol
            The label of the starting point/node of the member.

        end: String or Symbol
            The label of the ending point/node of the member.

        Examples
        ========

        >>> from sympy.physics.continuum_mechanics.truss import Truss
        >>> t = Truss()
        >>> t.add_node('A', 0, 0)
        >>> t.add_node('B', 3, 0)
        >>> t.add_node('C', 2, 2)
        >>> t.add_member('AB', 'A', 'B')
        >>> t.members
        {'AB': ['A', 'B']}
        z;The start and end points of the member must be unique nodesz9A member with the same label already exists for the trussz-A member already exists between the two nodesTr   N)r   r9   rF   r   r   getr   )r   r<   startends       r   
add_memberzTruss.add_member   s    8 )))S8I-I-IUTWZZZ[[[d4=))))XYYY!%%ucl33 	-LMMM %*3<DM% /3D ,/3D e,+,D!%(((r!   c                    |t          | j                  vrt          d          | j                            | j        |         d         | j        |         d         f           | j                            | j        |         d         | j        |         d         f           | j                            |           | j                            |           dS )a  
        This method removes a member from the given truss.

        Parameters
        ==========
        label: String or Symbol
            The label for the member to be removed.

        Examples
        ========

        >>> from sympy.physics.continuum_mechanics.truss import Truss
        >>> t = Truss()
        >>> t.add_node('A', 0, 0)
        >>> t.add_node('B', 3, 0)
        >>> t.add_node('C', 2, 2)
        >>> t.add_member('AB', 'A', 'B')
        >>> t.add_member('AC', 'A', 'C')
        >>> t.add_member('BC', 'B', 'C')
        >>> t.members
        {'AB': ['A', 'B'], 'AC': ['A', 'C'], 'BC': ['B', 'C']}
        >>> t.remove_member('AC')
        >>> t.members
        {'AB': ['A', 'B'], 'BC': ['B', 'C']}
        z"No such member exists in the Trussr   rA   N)rF   r   r9   r   rG   r   )r   r<   s     r   remove_memberzTruss.remove_member  s    4 T]++++ABBB  $$dmE&:1&=t}U?STU?V%WXXX $$dmE&:1&=t}U?STU?V%WXXXMe$$$!%%e,,,,,r!   c                    || j         vrt          d          || j         v rt          d          | j        D ]}|d         |k    r||d         |d         f| j        | j                            ||d         |d         f          <   || j         | j                             |d                   <   | j        |         | j        |<   | j                            |           |d         t          | j                  v r;| j        |d                  | j        |<   | j                            |d                    |t          | j                  v r| j        |         dk    rdt          |          z   dz   t          | j	                  v rdt          |          z   d	z   t          | j	                  v r| j	        dt          |          z   dz            | j	        dt          |          z   dz   <   | j	        dt          |          z   d	z            | j	        dt          |          z   d	z   <   | j	                            dt          |          z   dz              | j	                            dt          |          z   d	z              | j
        |         | j
        |<   | j
        |         D ]l}|d         d
k    r^|dxx         t          dt          |          z   d	z             z  cc<   |d         dk    r | j
        |                             |            nm| j
        |         D ]l}|d         dk    r^|dxx         t          dt          |          z   dz             z  cc<   |d         dk    r | j
        |                             |            nm|                     |t          dt          |          z   dz             d           |                     |t          dt          |          z   d	z             d
           | j
                            |           n7| j        |         dk    r| j
        |         | j
        |<   | j
        |         D ]l}|d         d
k    r^|dxx         t          dt          |          z   d	z             z  cc<   |d         dk    r | j
        |                             |            nm|                     |t          dt          |          z   d	z             d
           | j
                            |           nE|t          | j
                  v r/| j
        |         | j
        |<   | j
                            |           t          | j                  D ]}| j        |         d         |d         k    r|| j        |         d<   d| j        || j        |         d         f<   d| j        | j        |         d         |f<   | j                            || j        |         d         f           | j                            | j        |         d         |f           | j        |         d         |d         k    r|| j        |         d<   d| j        | j        |         d         |f<   d| j        || j        |         d         f<   | j                            | j        |         d         |f           | j                            || j        |         d         f           dS )a  
        This method changes the label of a node.

        Parameters
        ==========
        label: String or Symbol
            The label of the node for which the label has
            to be changed.

        new_label: String or Symbol
            The new label of the node.

        Examples
        ========

        >>> from sympy.physics.continuum_mechanics.truss import Truss
        >>> t = Truss()
        >>> t.add_node('A', 0, 0)
        >>> t.add_node('B', 3, 0)
        >>> t.nodes
        [('A', 0, 0), ('B', 3, 0)]
        >>> t.change_node_label('A', 'C')
        >>> t.nodes
        [('C', 0, 0), ('B', 3, 0)]
        z!No such node exists for the Trussz*A node with the given label already existsr   rA      pinnedR__x_yZ   rollerTN)r   r9   r   r:   r   rG   rF   r   strr   r   r   rE   
apply_loadr   r   )r   r<   	new_labelnodeloadrJ   s         r   change_node_labelzTruss.change_node_label1  s   4 )))@AAA$+++IJJJ :X :X7e##QZ\`ab\ceijkelPmDK 1 15$q'472K L LMJSD%d&7&=&=d1g&F&FG8<8Nu8UD*95*..u555Aw$t~"6"66648N474Ky1**47333 D$8$888>)4@@#CJJt3tD<P7Q7QQQVZ[^_d[e[eVefjVjnrsw  tH  oI  oI  WI  WIQUQefjknotkukufuvzfzQ{ 4T#i..5H5M NQUQefjknotkukufuvzfzQ{ 4T#i..5H5M N $ 4 8 8c%jj9M N N N $ 4 8 8c%jj9M N N N59[5GDK	2(,I(> * *#'7b==$(GGGvd3u::od6J/K/K$KGGG'+Aw!||(,E(:(A(A$(G(G(G$)E	 $1
 )-I(> * *#'7a<<$(GGGvd3u::od6J/K/K$KGGG'+Aw!||(,E(:(A(A$(G(G(G$)E	 $0
 !OOIvd3y>>>QRV>V7W7WYZ[[[ OOIvd3y>>>QRV>V7W7WY[\\\ KOOE2222!^I6(BB59[5GDK	2(,E(: * *#'7b==$(GGGvd3u::od6J/K/K$KGGG'+Aw!||(,E(:(A(A$(G(G(G$)E	 $1
 !OOIvd3y>>>QRV>V7W7WY[\\\ KOOE222 D$5$55559[5GDK	2 KOOE222"&t}"5"5 X X=03tAw>>7@DM&1!4Z^D0)T]6=RST=U1VWZ^D0$-2G2JI1VW 044eT]6=RST=U5VWWW 044dmF6KA6NPU5VWWWW!]6215a@@7@DM&1!4Z^D0$-2G2JI1VWZ^D0)T]6=RST=U1VW 044dmF6KA6NPU5VWWW 044eT]6=RST=U5VWWWu:X :Xr!   c                    |t          | j                  vrt          d          t          | j                                                  }|D ]}||k    rw| j        |         d         | j        |         d         g| j        |<   | j                            |           | j        |         | j        |<   | j                            |           dS )aG  
        This method changes the label of a member.

        Parameters
        ==========
        label: String or Symbol
            The label of the member for which the label has
            to be changed.

        new_label: String or Symbol
            The new label of the member.

        Examples
        ========

        >>> from sympy.physics.continuum_mechanics.truss import Truss
        >>> t = Truss()
        >>> t.add_node('A', 0, 0)
        >>> t.add_node('B', 3, 0)
        >>> t.nodes
        [('A', 0, 0), ('B', 3, 0)]
        >>> t.change_node_label('A', 'C')
        >>> t.nodes
        [('C', 0, 0), ('B', 3, 0)]
        >>> t.add_member('BC', 'B', 'C')
        >>> t.members
        {'BC': ['B', 'C']}
        >>> t.change_member_label('BC', 'BC_new')
        >>> t.members
        {'BC_new': ['B', 'C']}
        z#No such member exists for the Trussr   rA   N)rF   r   r9   rD   rG   r   )r   r<   r]   rI   rJ   s        r   change_member_labelzTruss.change_member_label  s    @ T]++++BCCC !%T] 3 3 8 8 : :+ 5 5U??04f0Ea0H$-X^J_`aJb/cDM),M%%e,,,7;7LU7SD))4)--e4445 5r!   c                     t          |          }t          |          }|| j        vrt          d          |t          | j                  v r$| j        |                             ||g           dS ||gg| j        |<   dS )a  
        This method applies an external load at a particular node

        Parameters
        ==========
        location: String or Symbol
            Label of the Node at which load is applied.

        magnitude: Sympifyable
            Magnitude of the load applied. It must always be positive and any changes in
            the direction of the load are not reflected here.

        direction: Sympifyable
            The angle, in degrees, that the load vector makes with the horizontal
            in the counter-clockwise direction. It takes the values 0 to 360,
            inclusive.

        Examples
        ========

        >>> from sympy.physics.continuum_mechanics.truss import Truss
        >>> from sympy import symbols
        >>> t = Truss()
        >>> t.add_node('A', 0, 0)
        >>> t.add_node('B', 3, 0)
        >>> P = symbols('P')
        >>> t.apply_load('A', P, 90)
        >>> t.apply_load('A', P/2, 45)
        >>> t.apply_load('A', P/4, 90)
        >>> t.loads
        {'A': [[P, 90], [P/2, 45], [P/4, 90]]}
        z$Load must be applied at a known nodeN)r   r&   r9   rF   r   r;   r   location	magnitude	directions       r   r\   zTruss.apply_load  s    B I&&	I&&	4+++CDDD 4,,,,H%,,i-CDDDDD*3Y)?(@H%%%r!   c                 P   t          |          }t          |          }|| j        vrt          d          ||g| j        |         vrt          d          | j        |                             ||g           | j        |         g k    r| j                            |           dS dS )a;  
        This method removes an already
        present external load at a particular node

        Parameters
        ==========
        location: String or Symbol
            Label of the Node at which load is applied and is to be removed.

        magnitude: Sympifyable
            Magnitude of the load applied.

        direction: Sympifyable
            The angle, in degrees, that the load vector makes with the horizontal
            in the counter-clockwise direction. It takes the values 0 to 360,
            inclusive.

        Examples
        ========

        >>> from sympy.physics.continuum_mechanics.truss import Truss
        >>> from sympy import symbols
        >>> t = Truss()
        >>> t.add_node('A', 0, 0)
        >>> t.add_node('B', 3, 0)
        >>> P = symbols('P')
        >>> t.apply_load('A', P, 90)
        >>> t.apply_load('A', P/2, 45)
        >>> t.apply_load('A', P/4, 90)
        >>> t.loads
        {'A': [[P, 90], [P/2, 45], [P/4, 90]]}
        >>> t.remove_load('A', P/4, 90)
        >>> t.loads
        {'A': [[P, 90], [P/2, 45]]}
        z&Load must be removed from a known nodezENo load of this magnitude and direction has been applied at this nodeN)r   r&   r9   r   rE   rG   rd   s       r   remove_loadzTruss.remove_load  s    H I&&	I&&	4+++EFFF 9%T[-BBB !hiiiH%,,i-CDDD;x B&&KOOH%%%%% '&r!   c           	         || j         vrt          d          |t          | j                  vr|dk    ro|                     |t          dt          |          z   dz             d           |                     |t          dt          |          z   dz             d           n|dk    r7|                     |t          dt          |          z   dz             d           n| j        |         dk    r>|dk    r7|                     |t          dt          |          z   dz             d           nN| j        |         dk    r=|dk    r7|                     |t          dt          |          z   dz             d           || j        |<   d	S )
aH  
        This method adds a pinned or roller support at a particular node

        Parameters
        ==========

        location: String or Symbol
            Label of the Node at which support is added.

        type: String
            Type of the support being provided at the node.

        Examples
        ========

        >>> from sympy.physics.continuum_mechanics.truss import Truss
        >>> t = Truss()
        >>> t.add_node('A', 0, 0)
        >>> t.add_node('B', 3, 0)
        >>> t.apply_support('A', 'pinned')
        >>> t.supports
        {'A': 'pinned'}
        z%Support must be added on a known noderU   rV   rW   r   rX   rY   rZ   N)r   r9   rF   r   r\   r   r[   ri   )r   re   types      r   apply_supportzTruss.apply_support  s   0 4,,,DEEE tDN33338##OOHfT#h--5G5L.M.MqQQQOOHfT#h--5G5L.M.MrRRRRX%%OOHfT#h--5G5L.M.MrRRR)X558##$$Xvd3x==6H6M/N/NPQRRR)X558##OOHfT#h--5G5L.M.MqQQQ'+DN8$$$r!   c           	      D   || j         vrt          d          |t          | j                  vrt          d          | j        |         dk    ro|                     |t          dt          |          z   dz             d           |                     |t          dt          |          z   dz             d           nH| j        |         d	k    r7|                     |t          dt          |          z   dz             d           | j                            |           d
S )a4  
        This method removes support from a particular node

        Parameters
        ==========

        location: String or Symbol
            Label of the Node at which support is to be removed.

        Examples
        ========

        >>> from sympy.physics.continuum_mechanics.truss import Truss
        >>> t = Truss()
        >>> t.add_node('A', 0, 0)
        >>> t.add_node('B', 3, 0)
        >>> t.apply_support('A', 'pinned')
        >>> t.supports
        {'A': 'pinned'}
        >>> t.remove_support('A')
        >>> t.supports
        {}
        z No such node exists in the Trussz+No support has been added to the given noderU   rV   rW   r   rX   rY   rZ   N)r   r9   rF   r   ri   r   r[   rG   )r   re   s     r   remove_supportzTruss.remove_supportA  s   0 4,,,?@@@T$.1111JKKK ~h'833  6$s8}}2DT2I+J+JANNN  6$s8}}2DT2I+J+JBOOOO)X55  6$s8}}2DT2I+J+JBOOONx(((((r!   c                     d} j         D ]W}|d         t           j                  v r9 j        |d                  dk    r|dz  }; j        |d                  dk    r|dz  }Xdt           j                   z  t           j                  |z   k    rt          d           fdt          dt           j                   z            D             }t          dt           j                  z  d          }d} j         D ]}|d         t           j	                  v r j	        |d                  D ]}|d         t          dt          |d                   z   d	z             k    r|d         t          dt          |d                   z   d
z             k    rq||xx         |d         t          t          |d         z  dz            z  z  cc<   ||dz   xx         |d         t          t          |d         z  dz            z  z  cc<   |dz  }d}d} j         D ]}|d         t           j                  v r j        |d                  dk    r8||         |xx         dz  cc<   ||dz            |dz   xx         dz  cc<   |dz  }n5 j        |d                  dk    r||dz            |xx         dz  cc<   |dz  }|dz  }t           j                  D ]}	 j        |	         d         }
 j        |	         d         }t           j        |
         d          j        |         d         z
  dz   j        |
         d          j        |         d         z
  dz  z             } j                            |
          } j                            |          } j        |         d          j        |
         d         z
  |z  } j        |         d          j        |
         d         z
  |z  } j        |
         d          j        |         d         z
  |z  } j        |
         d          j        |         d         z
  |z  }||dz           |xx         |z  cc<   ||dz  dz            |xx         |z  cc<   ||dz           |xx         |z  cc<   ||dz  dz            |xx         |z  cc<   |dz  }t'          |          dz  |z  }i  _        d}t*          } j         D ]s}|d         t           j	                  v rU j	        |d                  D ]A}t-          |d                   t          t.          t0          fvrt3          ||d                   }Btt          t          |                    D ]L}t-          ||                   t          t.          t0          fvr!t5          ||         |z            dk     rd||<   M j         D ]}|d         t           j                  v r j        |d                  dk    r[||          j        dt          |d                   z   d	z   <   ||dz             j        dt          |d                   z   d
z   <   |dz  } j        |d                  dk    r.||          j        dt          |d                   z   d
z   <   |dz  }t           j                  D ]}	||          j        |	<   |dz  }dS )a	  
        This method solves for all reaction forces of all supports and all internal forces
        of all the members in the truss, provided the Truss is solvable.

        A Truss is solvable if the following condition is met,

        2n >= r + m

        Where n is the number of nodes, r is the number of reaction forces, where each pinned
        support has 2 reaction forces and each roller has 1, and m is the number of members.

        The given condition is derived from the fact that a system of equations is solvable
        only when the number of variables is lesser than or equal to the number of equations.
        Equilibrium Equations in x and y directions give two equations per node giving 2n number
        equations. However, the truss needs to be stable as well and may be unstable if 2n > r + m.
        The number of variables is simply the sum of the number of reaction forces and member
        forces.

        .. note::
           The sign convention for the internal forces present in a member revolves around whether each
           force is compressive or tensile. While forming equations for each node, internal force due
           to a member on the node is assumed to be away from the node i.e. each force is assumed to
           be compressive by default. Hence, a positive value for an internal force implies the
           presence of compressive force in the member and a negative value implies a tensile force.

        Examples
        ========

        >>> from sympy.physics.continuum_mechanics.truss import Truss
        >>> t = Truss()
        >>> t.add_node("node_1", 0, 0)
        >>> t.add_node("node_2", 6, 0)
        >>> t.add_node("node_3", 2, 2)
        >>> t.add_node("node_4", 2, 0)
        >>> t.add_member("member_1", "node_1", "node_4")
        >>> t.add_member("member_2", "node_2", "node_4")
        >>> t.add_member("member_3", "node_1", "node_3")
        >>> t.add_member("member_4", "node_2", "node_3")
        >>> t.add_member("member_5", "node_3", "node_4")
        >>> t.apply_load("node_4", magnitude=10, direction=270)
        >>> t.apply_support("node_1", type="pinned")
        >>> t.apply_support("node_2", type="roller")
        >>> t.solve()
        >>> t.reaction_loads
        {'R_node_1_x': 0, 'R_node_1_y': 20/3, 'R_node_2_y': 10/3}
        >>> t.internal_forces
        {'member_1': 20/3, 'member_2': 20/3, 'member_3': -20*sqrt(2)/3, 'member_4': -10*sqrt(5)/3, 'member_5': 10}
        r   rU   rT   rZ   rA   z The given truss cannot be solvedc           	      l    g | ]0}d  t          dt          j                  z            D             1S )c                     g | ]}d S )r    ).0rH   s     r   
<listcomp>z*Truss.solve.<locals>.<listcomp>.<listcomp>  s    EEEaEEEr!   rT   )rB   rC   r   )rs   jr   s     r   rt   zTruss.solve.<locals>.<listcomp>  s?    iii!EE53t{3C3C1C+D+DEEEiiir!   rV   rW   rX      g|=N)r   rF   r   rC   r   r9   rB   r   r#   r   r   r[   r   r	   r   r
   r   r   r:   r   r   r   rk   r   r   minabsr   )r   count_reaction_loadsr^   coefficients_matrixload_matrixload_matrix_rowr_   colsrowrJ   rN   rO   lengthstart_index	end_indexhorizontal_component_startvertical_component_starthorizontal_component_endvertical_component_endforces_matrixrH   min_loadru   s   `                      r   solvezTruss.solveg  s   b  !K 	. 	.DAw$t~....>$q'*H44(A-((^DG,h66(A-(ST]!3!36J!JJJ?@@@iiiiuUVWZ[_[fWgWgUgOhOhiiiAc$*oo-q11K 	! 	!DAw$t{++++ KQ0 X XDAwtCQLL'8'= > >>>47FSWX[\`ab\cXdXdSdeiSiLjLjCjCj#O444QBtAwJsN@S@S8SS444#Oa$7888DGC4PQ7
SVDWDW<WW888q OOK 		 		DAw$t~....>$q'*H44',T222a7222'A.tAv666!;666AIDD^DG,h66'A.t4449444AID1HCC4=)) 	 	FM&)!,E-'*C41%8;D<RSV<WXY<ZZ]^^bfbxy~b  AB  cC  DH  DZ  [^  D_  `a  Db  cb  ef  bf  f  g  gF+11%88K)//44I*.*@*Ea*HI_`eIfghIi*ikq)q&(,(>s(CA(FtG]^cGdefGg(gio'o$(,(>u(Ea(HI_`cIdefIg(gio'o$&*&<U&CA&FtG]^aGbcdGe&egm%m"A.t4448RR444Aa0666:RR666	!,T2226NN222	!A.t4448NN444AIDD 344b8+E!K 	: 	:DAw$t{++++ KQ0 : :DDG}}VS#,>>>#&xa#9#9s=))** 	) 	)AM!$%%fc3-???}Q'011588'(M!$K 	 	DAw$t~....>$q'*H44CPQRCSD(c$q'll):4)?@CPQRSTQTCUD(c$q'll):4)?@FAA^DG,h66CPQRCSD(c$q'll):4)?@FA4=)) 	 	F,9!,<D!&)FAAr!   N)__name__
__module____qualname____doc__r    propertyr#   r&   r(   r,   r/   r1   r3   r5   r7   r?   rK   rP   rR   r`   rb   r\   ri   rl   rn   r   rr   r!   r   r   r      s       ! !F$ $ $"   X ! ! X! $ $ X$   X # # X#   X   X $ $ X$ % % X%*3 *3 *3X.. .. ..`)- )- )-V!- !- !-FYX YX YXv*5 *5 *5X+A +A +AZ0& 0& 0&d(, (, (,T$) $) $)Lx x x x xr!   r   N)r   cmathr   sympy.core.addr   sympy.core.mulr   sympy.core.symbolr   sympy.core.sympifyr   sympyr   r	   (sympy.functions.elementary.miscellaneousr
   sympy.matrices.denser   r   r   r   rr   r!   r   <module>r      s    
                   $ $ $ $ $ $ & & & & & &         9 9 9 9 9 9 & & & & & &        M M M M M M M M M Mr!   