
    bi(                     z    d dl Zd dlmZ d dlZd dlmZ d dlm	Z	 d dl
mZmZ d dlZd dlZd Z G d de      Zd Zy)	    N)Module)Function)Paralleldelayedc                     | y | j                         dk(  rt        j                  g       S | j                         j	                         j                         S )Nr   )nelementnparraycpudetachnumpy)ts    H/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/osqp/nn/torch.pyto_numpyr      sB    y	
	xx|uuw~~%%''    c                   2     e Zd Z	 	 	 	 	 	 d fd	Zd Z xZS )OSQPc                     t         |           ||c| _        | _        ||c| _        | _        ||c| _        | _        || _        || _	        |	| _
        |
| _        y N)super__init__P_idxP_shapeA_idxA_shapeeps_releps_absverbosemax_iteralgebrasolver_type)selfr   r   r   r   r   r   r   r   r    r!   	__class__s              r   r   zOSQP.__init__   s]     	#(' 
DL#(' 
DL%,g"dl &r   c                     t        | j                  | j                  | j                  | j                  | j
                  | j                  | j                  | j                  | j                  | j                  
      |||||      S )N)
r   r   r   r   r   r   r   r   r    r!   )_OSQP_Fnr   r   r   r   r   r   r   r   r    r!   )r"   P_valq_valA_vall_valu_vals         r   forwardzOSQP.forward-   sm    
x**LL**LLLLLLLL]]LL((
 ue- 	-r   )h㈵>r,   Fi'  builtindirect)__name__
__module____qualname__r   r+   __classcell__)r#   s   @r   r   r      s!     ',-r   r   c
                 x    	 g \   G  	fddt               }
|
j                  S )Nc                   R    e Zd Ze 	
fd       Ze 
fd       Zy)_OSQP_Fn.<locals>._OSQP_FnFnc                    dt         dt        f#fd}#$fd|||g}|D ]  }|j                         dk  rJ d        t        j                  |D 	cg c]  }	|	j                         dkD   c}	      }
|
sd}n>|D 	cg c](  }	|	j                         dk(  r|	j                  d      nd* }}	t        |      }j                  }j                  }t        |      D ]L  \  }}|j                         dk(  s|j                  d      j                  ||j                  d            ||<   N |\  }}}j                  d      t        d         k(  sJ d	       j                  d      t        d         k(  sJ d
       t        |      D cg c]  }t        ||          c}t        |      D cg c]  }t        ||          c}t        |      D cg c]  }t        ||          c}t        j                   |!f||      } ||      t#        j$                         } t'        |d       "fdt        |      D              }t)        | \  }}t        |      D ]<  }r	||   #|<   n#j+                  ||          t        j,                  ||         ||<   > |
s|j/                  d      }|S c c}	w c c}	w c c}w c c}w c c}w )a  Solve a batch of QPs using OSQP.

            This function solves a batch of QPs, each optimizing over
            `n` variables and having `m` constraints.

            The optimization problem for each instance in the batch
            (dropping indexing from the notation) is of the form

                \hat x =   argmin_x 1/2 x' P x + q' x
                        subject to l <= Ax <= u

            where P \in S^{n,n},
                S^{n,n} is the set of all positive semi-definite matrices,
                q \in R^{n}
                A \in R^{m,n}
                l \in R^{m}
                u \in R^{m}

            These parameters should all be passed to this function as
            Variable- or Parameter-wrapped Tensors.
            (See torch.autograd.Variable and torch.nn.parameter.Parameter)

            If you want to solve a batch of QPs where `n` and `m`
            are the same, but some of the contents differ across the
            minibatch, you can pass in tensors in the standard way
            where the first dimension indicates the batch example.
            This can be done with some or all of the coefficients.

            You do not need to add an extra dimension to coefficients
            that will not change across all of the minibatch examples.
            This function is able to infer such cases.

            If you don't want to use any constraints, you can set the
            appropriate values to:

                e = Variable(torch.Tensor())

            n_batchreturnc                 T    t              }|d| fvrt        d|  d| d      || k(  S )z
                This is a helper function that returns a flag if we need to update the solvers
                or generate them. Raises an RuntimeError if the number of solvers is invalid.
                r   z)Invalid number of solvers: expected 0 or z
, but got .)lenRuntimeError)r7   num_solverssolverss     r   _get_update_flagz>_OSQP_Fn.<locals>._OSQP_FnFn.forward.<locals>._get_update_flagv   sF    
 "'lq'l2&)RSZR[[efqerrs'tuu"g--r   c                 J   |r?|    }|j                  ||    ||    ||    t        ||          |t        ||          |       nt        j                  t        ||          |f      }t        j                  t        ||          |f      }t	        j
                        }|j                  |||    |||    ||    |	|
|	       |j                         }|j                  j                  }|t        j                  j                  k7  rt        d|       ||j                  fS )z
                This inner function solves for each solver. update_flag has to be passed from
                outside to make sure it doesn't change during a parallel run.
                )qluPxPx_idxAxAx_idx)shape)r    )r!   r   r   r   zUnable to solve QP, status: )updater   spa
csc_matrixosqpr   setupsolveinfo
status_valSolverStatusOSQP_SOLVEDr<   x)iupdate_flagrA   rB   rC   r&   r   r(   r   r!   r   r   solverPAresultstatusr   r   r    r>   r   s                    r   _inner_solvez:_OSQP_Fn.<locals>._OSQP_FnFn.forward.<locals>._inner_solve   s,    $QZFMMA$!A$!A$8E!H3EeX`afghaiXjsx "  q(:E'B'RAq(:E'B'RA!YYw7FLL!!!$/ ' ' ' ! 
  //T..::: ')EfX'NOOvxx''r      zUnexpected number of dimensions   r   zUnexpected size of AzUnexpected size of Pdtypedevicethreadsn_jobspreferc              3   X   K   | ]!  } t              |
	        # yw))rT   rU   rA   rB   rC   r&   r   r(   r   r!   r   r   Nr   ).0rT   r   r(   r   r&   r[   r   r   rB   rA   r!   rC   rU   s     r   	<genexpr>z7_OSQP_Fn.<locals>._OSQP_FnFn.forward.<locals>.<genexpr>   sP      <  &% + +## <s   '*)intbool
ndimensionr	   anysizemaxr_   r`   	enumerate	unsqueezeexpandr;   ranger   torchzerosmultiprocessing	cpu_countr   zipappend
from_numpysqueeze)%ctxr&   r'   r(   r)   r*   r?   paramspr   
batch_moder7   batch_sizesr_   r`   rT   x_torchrc   ressolvers_looprS   r[   rB   rA   rC   rU   r   r   r   r   r    r   r   nr!   r>   r   s%    ` `                 @@@@@r   r+   z$_OSQP_Fn.<locals>._OSQP_FnFn.forwardM   s   R.# .$ .$( $(L UE5%8F N||~*M,MM*N V D!!3 DEJPVW1ALLNa,?qvvayQFWWk*KKE\\F
 "&) J1<<>Q& !A 5 5gqvvay IF1IJ 39/UE5%::a=CaM1I3II1::a=CaM1I3II1-27^<%(#<A-27^<%(#<A-27^<%(#<A kk7A,eFKG*73K$..0F;(&; < < w< C" "3iOL!7^ 4!-aGAJNN<?3"--ad3
4 !//!,Nw !E X" =<<s   K
	-KK=K"Kc                    d |j                   }|j                  }|j                         dk(  }|s|j                  d      }|j	                  d      }|j                   }|j                  }t        |      t        d         }t        d         }t        j                  ||f||      }t        j                  |f||      }	t        j                  ||f||      }
t        j                  |f||      }t        j                  |f||      }t        j                         } t        |d      fdt        |      D              }t        | \  }}}}}t        |      D ]*  }||   |	|<   ||   ||<   ||   ||<   ||   ||<   ||   |
|<   , ||	|
||g}|s&t        |      D ]  \  }}|j                         ||<    t!        |      S )Nc                 T   | j                  |       | j                  dd      \  }}| j                         \  }}}|||fD cg c]  }t        j                  |       c}\  }}	}
||fD cg c]!  }t        j                  |j
                        # c}\  }}||	|
||fS c c}w c c}w )z
                This inner function calculates dp[i] dl[i], du[i], dP[i], dA[i]
                using solvers[i], dl_dx[i].
                )dxF)as_dense
dP_as_triu)adjoint_derivative_computeadjoint_derivative_get_matadjoint_derivative_get_vecrs   ry   rS   )rV   dl_dxdPi_npdAi_npdqi_npdli_npdui_npddqdldudPdAs                r   _loop_adjoint_derivativezG_OSQP_Fn.<locals>._OSQP_FnFn.backward.<locals>._loop_adjoint_derivative   s    
 11U1;!'!B!BE^c!B!d)/)J)J)L&<BFF;STae..q1T
B:@&9IJA%**133/JB2r2r)) UJs   B -&B%r\   r   r^   ra   rb   c              3   N   K   | ]  } t              |   |           y wr   rf   )rg   rT   r   r   r>   s     r   rh   z8_OSQP_Fn.<locals>._OSQP_FnFn.backward.<locals>.<genexpr>  s.      <LM101'!*eAhG<s   "%)r_   r`   rk   rp   rm   r   r;   rs   rt   ru   rv   r   rr   rw   ro   rz   tuple)r{   	dl_dx_valr_   r`   r~   r7   nnz_Pnnz_Ar   r   r   r   r   rc   r   dq_vecdl_vecdu_vecdP_vecdA_vecrT   gradsgr   r   r   r   mr   r>   s                          @@r   backwardz%_OSQP_Fn.<locals>._OSQP_FnFn.backward   s   
* OOE%%F"--/14J%//2	nnQ'GOOE%%F Y'E aMEaMEgu-U6JBgq\vFBgu-U6JBgq\vFBgq\vFB$..0F;(&; <QVW^Q_< C 69#Y2FFFFF7^ "q	1q	1q	1q	1q	1" RR(E%e, +DAq yy{E!H+ <r   N)r/   r0   r1   staticmethodr+   r   )r   r   r   r   r    r   r   r   r   r!   r>   r   s   r   
_OSQP_FnFnr5   L   s2    	X	 X	 
X	t 
7	  
7	 r   r   )r   apply)r   r   r   r   r   r   r   r   r    r!   r   r   r   r>   s   ``````` `` @@@r   r%   r%   <   s=     GDAqT  T  T X T l r   )r   r	   scipy.sparsesparserJ   rs   torch.nnr   torch.autogradr   joblibr   r   ru   rL   r   r   r%    r   r   <module>r      s5        # $  (#-6 #-Lfr   