# Cryptographic Utilities Exercise || I.BA_MOVK_MM, Semesterweek 04
*Please write down to solution of the exercises in a consise but comprehensible way. Numerical results
should be accurate to 4 digits.*

## 1 Exercise 1: MD5, SHA1, SHA256, SHA512

Generate the previsously mentioned hash values of the string $Hello World!$. Do You get the same
result as Your neighbour? Check the size of each hash value! What are the corresponding block sizes?
Make a table! How many hash values would You have to generate in order to find a collision with a
probability of at least 50% (90%)?

---

We will use some good ol' Python for that

```python
import hashlib

plaintext = b'HelloWorld!'

md5hash = hashlib.md5(plaintext)
print("md5: ",md5hash.hexdigest())
print("md5-size: ",md5hash.digest_size)
print("md5-lenght: ",str(md5hash.digest_size * 8))
print("md5-block-size: ",md5hash.block_size)
print()

sha1hash = hashlib.sha1(plaintext)
print("sha1: ",sha1hash.hexdigest())
print("sha1-size: ",sha1hash.digest_size)
print("sha1-lenght: ",str(sha1hash.digest_size * 8))
print("sha1-block-size: ",sha1hash.block_size)
print()

sha256hash = hashlib.sha256(plaintext)
print("sha256: ",sha256hash.hexdigest())
print("sha256-size: ",sha256hash.digest_size)
print("sha256-lenght: ",str(sha256hash.digest_size * 8))
print("sha256-block-size: ",sha256hash.block_size)
print()

sha512hash = hashlib.sha512(plaintext)
print("sha512: ",sha512hash.hexdigest())
print("sha512-size: ",sha512hash.digest_size)
print("sha512-lenght: ",str(sha512hash.digest_size * 8))
print("sha512-block-size: ",sha512hash.block_size)

```

### Probability of a Collission

The values are obviously the same as my neighbours, because it is a hash and not an encryption with different keys!

The Probability of a Collission is best shown here:

**The Formula is:** $n = 2^{(m+1)/2} \cdot \sqrt{(\ln{(\frac{1}{1-p})}}$

Angenähert $2^{\frac{m}{2}}$

```python
import numpy as np

def number_hashes_for_collision(message_digest_length, probability_threshold):
    n = 2 ** ((message_digest_length+1)/2) * np.sqrt(np.log(1/(1-probability_threshold)))
    return n #n = hashes die es braucht für eine kollision mit w'keit p

print('MD5, p = 0.5:  ' + str(number_hashes_for_collision(128,0.5)))
print('MD5, p = 0.9:  ' + str(number_hashes_for_collision(128,0.9)))
print('SHA1, p = 0.5:  ' + str(number_hashes_for_collision(160,0.5)))
print('SHA1, p = 0.9:  ' + str(number_hashes_for_collision(160,0.9)))
print('SHA256, p = 0.5:  ' + str(number_hashes_for_collision(256,0.5)))
print('SHA256, p = 0.9:  ' + str(number_hashes_for_collision(256,0.9)))
print('SHA512, p = 0.5:  ' + str(number_hashes_for_collision(512,0.5)))
print('SHA512, p = 0.9:  ' + str(number_hashes_for_collision(512,0.9)))
print('SHA3, p = 0.5:  ' + str(number_hashes_for_collision(512,0.5)))
print('SHA3, p = 0.9:  ' + str(number_hashes_for_collision(512,0.9)))
```

    MD5, p = 0.5:  2.171938135516356e+19
    MD5, p = 0.9:  3.958608607783506e+19
    SHA1, p = 0.5:  1.4234013764919992e+24
    SHA1, p = 0.9:  2.5943137371969984e+24
    SHA256, p = 0.5:  4.006518692980012e+38
    SHA256, p = 0.9:  7.3023439875766e+38
    SHA512, p = 0.5:  1.3633476639602231e+77
    SHA512, p = 0.9:  2.4848588961634497e+77
    SHA3, p = 0.5:  1.3633476639602231e+77
    SHA3, p = 0.9:  2.4848588961634497e+77

## Exercise 2: True random number generator

Check if Your computer can generate true random numbers, possibly through some special device? Find
out the underlying physical principle (thermal noise, etc.). How can You use the random number generator
in the power shell (Windows) or some shell (bash, sh, etc.) on Linux or MAC OS X?
How are true random numbers generated on smart cards? Do some research on the internet!

---

**Windows:** https://en.wikipedia.org/wiki/CryptGenRandom
**True-Randomness**: Pseudorandom

PowerShell

    Get-Random sets a default seed for each session based on the system time clock when the session starts.

---

**Linux**: /dev/random
**True-Randomness**: Verwendet den "Noise" von Systemtreibern (CPU clock, GPU clock, Voltage Level...)
**Example**: cat /dev/urandom > ~/urandom_test2

---

**Smartcard:** Almost all - if not all - smart cards have a true random number generator (TRNG) on it. Most often the TRNG depends on thermal noise or clock drift, but other entropy sources are possible. A more technical evaluation of this can be found e.g. here
[https://csrc.nist.gov/csrc/media/events/random-bit-generation-workshop-2016/documents/presentations/sessionvi-2-viktor-fischer-presentation.pdf])
**True Randomness**: Allgemein werden "Hardware Random Number Generators" (hrng) verwendet bei smartcards
https://en.wikipedia.org/wiki/Hardware_random_number_generator.
Diese messen "Noise" wie Thermisches Rauschen oder den Photoelektrischen Effekt.

## Exercise 3: Linear congruential random number generator

Compute the period of a linear congruential number generator if $m$ = 11, $b$ = 5, $a$ = 3 and $x_{0}$ = 7 is
used. Write down the sequence of random number! What is the maximal size of the period? Adapt the paramters, such that the period is maximal!

---

Formel gemäss Folie Nr 37 :

$x_{0} = s_{0} = 7$

$s_{i} = (a \cdot s_{i-1} + b) \mod m$

**Example**

$s_{1} = (3 \cdot s_{0} + 5) \mod 11 = (3 \cdot 7 + 5) \mod 11 = 4$

Das Maximum können wir mittels Python berechnen:

```python
def lcrn(a, sx, b, m):
    res = ((a * sx + b) % m)
    print(res)
    return res

sx = lcrn(3,7,5,11)
x = 1
while x<22:
    sx = lcrn(3,sx,5,11)
    x=x+1
```

    4
    6
    1
    8
    7
    4
    6
    1
    8
    7
    4
    6
    1
    8
    7
    4
    6
    1
    8
    7
    4
    6

Die momentane Period ist bei **5** (nach 5 wiederholt sich das Muster.)

---

Um die Period maximal zu machen muss folgendes gelten:
- gcd(b,m) = 1 (erfüllt)
- jeder primfaktor von m dividiert a-1 (nicht erfüllt)
- falls eine Zahl m teilt, teilt diese Zahl auch a-1 (nicht erfüllt)

Um diese Bedingungen zu erfüllen müssten wir also lediglich **a** anpassen, z.B. auf 12

```python
sx = lcrn(12,7,5,11)
x = 1
while x<22:
    sx = lcrn(12,sx,5,11)
    x=x+1
```

    1
    6
    0
    5
    10
    4
    9
    3
    8
    2
    7
    1
    6
    0
    5
    10
    4
    9
    3
    8
    2
    7

Mit unserer angepassten Formel erhalten wir nun eine Maximale Periode von **11**!

## Aufgabe 4: LFSR

Construct an LFSR of length 5 which produces the sequence of bits (1, 0, 1, 1, 0, 0, 1, 0, 1, 0,...). What
is the period of this LFSR? What is the maximal period? Try to improve this LFSR such that it has maximum period!

**Python Way**:

```python
def lfsr5(seed, taps):
    sr, xor = seed, 0
    while 1:
        for t in taps:
            xor += int(sr[t-1])
        xor %= 2
        sr, xor = str(xor) + sr[:-1], 0
        yield sr
        if sr == seed:
            break

a = lfsr5('10110', (5,3,2,1)) #IV
[next(a) for j in range(31)]
```

    ['01011',
     '00101',
     '00010',
     '00001',
     '10000',
     '11000',
     '01100',
     '00110',
     '10011',
     '01001',
     '00100',
     '10010',
     '11001',
     '11100',
     '11110',
     '11111',
     '01111',
     '10111',
     '11011',
     '11101',
     '01110',
     '00111',
     '00011',
     '10001',
     '01000',
     '10100',
     '01010',
     '10101',
     '11010',
     '01101',
     '10110']

Period is 15 which can be improved to 31 by adding c2 = 1 as an example! To make computations easy,
use the following python code

### Paper Way (raten und zeichnen):
**Gegeben**:
- LFSR Länge: 5
- Output: 1011001010

**Gegeben**: LFSR Länge & Output
- LFSR Länge: 4
- Output: 00011110

### Paper Way 2 (mathematischer):

Dieser Weg sollte besser verständlich sein und beinhaltet alle wesentlichen Schritte.

## Exercise 4:Is random really random (optional)

Nope

## Exercise 5:Probability for a collision

There are 40 people in a room. You bet, that there are at least 2 people with the same birthday. What is the probability, that You win? Use the exact formula as well as the approximation

```python
from sympy import *
i = symbols('i',integer=True)
p = 1 - product((365-i)/365,(i,1,39))
p.evalf()
```

$\displaystyle 0.891231809817949$

**Formel:**

$ 1 - \frac{365!}{(365 - n)! \cdot 365^{n}} =  1 - \frac{365!}{(365 - 40)! \cdot 365^{40}} = 0.891$

**Mathematischer Hintergrund**: Im **Urnenmodell** entspricht diese Annahme einer Ziehung von $n$ Kugeln mit Zurücklegen aus einer Urne, die 365 Kugeln mit der Beschriftung „1. Januar“, „2. Januar“ usw. bis „31. Dezember“ enthält.

---

**Allgemein Formel für W'Keit (p) von Kollision berechnen.**

$p = 1 - e^{\frac{-n(n-1)}{(2*m)}} = 1 - e^{\frac{-40(40-1)}{(2*365)}} = 0.882$

n = Anzahl effektiver Werte (z.B. Personen)
m = Anzahl möglicher Werte (z.B. Tage im Jahr)

## Exercise 6:Probability of a collision

Suppose You use a hash function of length 128 bits. How many hash values would You have to compute in order to find a collision with probability at least 90%?   Use the approximate forumula from Slide 14/58.

$n = 2^{(m+1)/2} \cdot \sqrt{(\ln{(\frac{1}{1-p})}}$

where m=128 and p=0.9.

```python
import math
import numpy as np
m = 128
p = 0.9

n = 2**((m+1)/2) * ( math.sqrt(np.log(1/(1-p)) ) )
print (n)
```

    3.958608607783506e+19

How much storage would You need, if You need 16 bytes for each hash?

```python
byte = n * 16
kilobyte = byte/1024
megabyte = kilobyte/1024
gigabyte = megabyte/1024
terabyte = gigabyte/1024
petabyte = terabyte/1024
exabyte = petabyte/1024

print("byte: ",byte)
print("kilobyte: ",kilobyte)
print("megabyte: ",megabyte)
print("gigabyte: ",gigabyte)
print("terabyte: ",terabyte)
print("petabyte: ",petabyte)
print("exabyte: ",exabyte)
```

    byte:  6.33377377245361e+20
    kilobyte:  6.185325949661728e+17
    megabyte:  604035737271653.1
    gigabyte:  589878649679.3488
    terabyte:  576053368.827489
    petabyte:  562552.1179955947
    exabyte:  549.367302730073

Conclusion: It's not worth it :)

```python

```


# 4. Integrating ODEs using `odeint`

First, import some stuff we'll need. We give some of them nicknames to save typing later

```python
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from scipy.integrate import odeint
```

The function `odeint`, which is found in the `integrate` submodule of the `scipy` package, integrates ordinary differential equations of the form
$$
\newcommand{\yy}{\mathbf{y}}
\newcommand{\ff}{\mathbf{f}}
\frac{\mathrm{d} \yy}{\mathrm{d}t} = \ff(\yy, t),
$$where $\yy$ is a vector in $\mathbb{R}^n$, or
$$
\dot{\yy} =  \ff(\yy, t).
$$
That is, it provides a numerical solution of the *initial value problem* given by this differential equation, together with an initial condition
$$
\yy(t = t_0) = \yy_0,
$$
returning the solution curve (or trajectory) $\yy(t)$ as a function of time $t$, within a certain (finite!) range of values of $t$.

Writing $\yy = (y_1, \ldots, y_n)$, we have a system of the form
\begin{align}
\dot{y_1} &= f_1(y_1, \ldots, y_n, t) \\
\dot{y_2} &= f_2(y_1, \ldots, y_n, t) \\
&\ldots \\
\dot{y_n} &= f_n(y_1, \ldots, y_n, t)
\end{align}

Note that in fact, *any* ordinary (system of) ordinary differential equation(s) can be written in this form by defining new variables to represent higher-order derivatives,
and incorporating them into the vector $\yy$ of variables.

To use `odeint`, we must define at least the Python function `f` which implements the mathematical function $\ff$. It must take a vector `y` and a time `t`,
and return the new vector `f(y,t)`.

## 1D equations

The simplest case is when the spatial dimension is $n=1$. For example, we could wish to solve the ODE
$
\dot{y} = ay,
$
whose exact solution is, of course, $y(t) = y_0 \exp(a t)$.

```python
a = 2.0
def f(y, t):
    return a*y
times = np.linspace(0,6)
y0 = 1.0
y_output = odeint(f, y0, times)
y_exact = y0*np.exp(a*times)
plt.plot(times, y_output, 'r.', label='integrated')
plt.plot(times, y_exact, label='analytical')
plt.legend()
plt.show()
```

# Example E5-6, Calculating X in a reactor with pressure drop
See page [183-188 in the textbook "Essentials of Chemical Reaction Engineering" by Fogler](.

This time we have two variables to integrate (conversion $X$ and pressure ratio $y$), so our function must accept and return a vector. We integrate over weight of catalyst $W$, not time $t$.
The differential equations are:

$$\frac{\mathrm{d} X}{\mathrm{d} W} = \frac{-r_A'}{F_{A0}}$$
$$\frac{\mathrm{d} y}{\mathrm{d} W} = -\alpha \frac{(1+\epsilon X)}{2y}$$

```python
def dYvecdW(Yvec,W):
    """
    Returns the right hand side of the differential equation dY/dW
    where Y is a vector containing two variables, (X, y).
    It thus returns a vector of two variables (dX/dW, dy/dW).

    X is conversion (what fraction of the limiting reactant has reacted)
    y is pressure ratio. (P/P_0)

    The "vector" Yvec could be an array, list, or tuple. Anything "array-like".
    """
    X, y = Yvec # unpack values from Y vector into two variables
    # Explicit equations
    epsilon = -0.15
    kprime = 0.0074
    Fa0 = 0.1362
    alpha = 0.0367
    raprime = -1*kprime*(1-X)/(1+epsilon*X) * y
    f = (1+epsilon*X)/y # ratio of v / v0
    # Differential equations
    dXdW = -raprime / Fa0
    dydW = -1*alpha * (1 + epsilon * X)/ (2*y)
    return (dXdW, dydW)  # pack up three differential equations into the dYvecdV vector
```

Set up the steps you want to integrate over. In this case it's Weight not Time

```python
W_output = np.linspace(0, 27., num=50) # Range for the weight of catalyst of the reactor
```

Set up the initial conditions, as a vector of the two values

```python
Y0 = [0., 1.] # Initial values for the dependent variables i.e X and y
```

Perform the integration, and extract the results

```python
Y_result = odeint(dYvecdW, Y0, W_output) # perform the integration
X, y = Y_result.T # extract columns by transposing matrix and splitting into two variables
```

Now we can plot the results

```python
epsilon = -0.15
f = (1+epsilon*X)/y # volumetric flow rate ratio

plt.plot(W_output, X, label='X (conversion)')
plt.plot(W_output, y, label='y ($P/P_0$)')
plt.plot(W_output, f, label='f ($v/v_0$)')
plt.legend(loc='upper left')
plt.xlabel('Weight of catalyst (kg)')

plt.show()
```

# Integrating other variables
Sometimes it's convenient to integrate things like $N_{tot}$ or Volume as well as the variables that you think you care most about. Just add them to your vector.

```python

```


#  Inaugural project: Getting an Insurance

##  Introduction to Programming and Numerical Analysis
*Oluf Kelkjær*

### **Today's Plan**
1. Objectives
2. Remember to...
3. Important formal requirement
4. Question hints

## Objectives
* Apply simple numerical solution and simulation methods
    * Solve the problem using SciPy and numpy
* Structure a code project
    * Notebook, .py-files, readme etc.
* Document code
    * Document and explain your code using what you learned in **lecture 5**
* Present results in text form and in figures
    * Create nice tables and figures + create nice markdown cells

## Remember (general hint) (1/4)
Create a python-file for your functions
**Remember** autoreload

```python
import pythonfile as py

%load_ext autoreload
%autoreload 2

```

## Remember (general hint) (2/4)
Document your code - at the exam you might have forgotten what you did and why

```python
import numpy as np

# 1. Initiliaze vectors of goods and container for utilities
psis = np.linspace(-10, -5, 5)
utility = np.empty((psis.shape)) # empty array with same shape as psi's

# 2. Calculate utility for all psis (relative risk aversion parameter
for i, psi in enumerate(psis):
    # i. Calculate utility using functions module
    u_psi = py.utility(1,psi)

    # ii. store the utility at the respective place (i)
    utility[i] = u_psi

    # iii. print result
    print(f'u(1,psi={psi:.2f})={u_psi:.2f}')

```

    u(1,psi=-10.00)=-0.11
    u(1,psi=-8.75)=-0.13
    u(1,psi=-7.50)=-0.15
    u(1,psi=-6.25)=-0.19
    u(1,psi=-5.00)=-0.25

## Remember (general hint) (3/4)

Incoporate markdown cells in your project that describes the model, intuition, etc.
Remember you do can do equation in markdown using either LaTeX syntax, `$$ math $$`:
$$ y_i = \beta_0 + \beta_1 x_i + \epsilon_i $$
or `\begin{equation} math \end{equation}`
\begin{align} y_i = \beta_0 + \beta_1 x_i + \epsilon_i \end{align}

Other formatting?
* An indent followed by `*` or `1.` creates list
    1. list item 1
    2. list item 2
    * list item 3
* `** text **` produces **text**
* `*text*` produces *text*
* `#` creates a large header, `##` smaller header and so on
* Google it!

## Remember (general hint) (4/4)
**Always** add docstrings to your functions.
The function name in itself isn't always as informal as you'd want

```python
def utility(z,psi):
    """ Calculates utility of given some assets, z, and relative risk aversion, psi.

    Args:
    z (float): the agents assets
    psi (float): the agents relative risk aversion

    Returns:
    (float): utility of assets
    """
    return (z**(1+psi))/(1+psi)

```

## Important requirement!

**ALLWAYS** restart your *kernel* and *run all cells* **before** handing in! This goes for the mandatory assignments along with the exam. It is crucial!

If you have crucual old variables in memory that makes your notebook run, then i cannot run your notebook!!

**Red flag** if the notebook can't be run from start to end!!

## Getting an insurance

Uninsured agents expected utility:

$V_0 = pu(y-x)+(1-p)u(y)$

Insured agent expected utility:

$V(q;\pi)=pu(y-x+q-\pi(p,q))+(1-p)u(y-\pi(p,q))$

Insurance company requires premium (in order to not go broke):

$\pi(p,q) = pq$

Agents utility given by:

$u(z) = \frac{z^{1+\psi}}{1+\psi}$

Parameters are:

$y=1, p = 0.2, \psi = -2$

## Hints for question 1
Once the *utility function*, *insurance premium* and the *insured agents expected utility* has been defined, we're ready to solve **question 1**.

Find optimal coverage, $q^*$, for $x$ in range $[0.01,0.9]$:

$q^\ast = \underset{q\in[0,x]}{\operatorname{argmax}} V(q;\pi)$

1.  create `x` array in range `[0.01,0.9]` and an empty array for optimal `q's` to be stored.
2.  Loop over `x's` where you define an ojective function for each `x`.
      * You can solve the objective function using the `minimize_scalar` funtion and store $q^*(x)$
      * Remember that $q\in[0,x]$ which means your solver should be **bounded**
      * Remember remember that we're maximizing (-minimize)

Plot the `x` and `q` arrays and comment!

## Hints for question 2:
Find $\tilde{\pi}$ such that $V(q;\tilde{\pi})=V_0$ at each point in $q$-array.
1. Construct $q$ and (empty) $\pi$-array
2. Create new objective function $V(q;\tilde{\pi})=V_0\rightarrow V(q;\tilde{\pi})-V_0=0$
3. Loop through the $q$'s
    * Can use `optimize.root` (solves objective function = 0) **seen in lecture 3**
    * store results in $\pi$-array
4. plot $q$ and $\pi$-array and comment!

## Hints for question 3:
Create a function for Monte Carlo integration - **seen in lecture 4**.
You can advantageously use two different `SimpleNamespace()`
One for model parameters and the other for different policy parameters

## Hints for question 4:
Define new objective function (MC under no coverage - MC under coverage)
Solve the objective function using `optimize.root` with `method='broyden1'`


# *Circuitos Elétricos I - Primeiro Estágio 2020.1e*

## Gabarito da avaliação

```python
m = [9,1,6] # últimos dígitos da matrícula
```

```python
import numpy as np
import sympy as sp
```

### Problema 1

a. $R_{eq}=?$

```python
# define valores das resistências
R1 = (m[0]+1)*1e3
R2 = (m[1]+1)*1e3
R3 = (m[2]+1)*1e3
```

```python
Req = ((R1+R3)*2*R3)/(R1+3*R3)
Req = Req + 3*R2
Req = (Req*R2)/(Req+R2)

print('Req = %.2f kΩ' %(Req/1000))
```

    Req = 1.69 kΩ

b. Leitura do voltímetro ideal

```python
# divisor de tensão
Vs  = 100

Req = ((R1+R3)*2*R3)/(R1+3*R3)

Vmed1 = Vs*Req/(Req+3*R2)

print('Vmed = %.2f V' %(Vmed1))
```

    Vmed = 45.45 V

c. Leitura do voltímetro de resistência interna $R_i = 20R_3$

```python
# divisor de tensão
Vs  = 100

Req = ((R1+R3)*2*R3)/(R1+3*R3)

Req = (Req*20*R3)/(Req+20*R3)

Vmed2 = Vs*Req/(Req+3*R2)

Erro = (Vmed1-Vmed2)/Vmed1

print('Vmed = %.2f V' %(Vmed2))
print('Erro absoluto = %.2f V' %(Vmed1-Vmed2))
print('Erro percentual = %.2f %%' %(Erro*100))
```

    Vmed = 44.25 V
    Erro absoluto = 1.21 V
    Erro percentual = 2.65 %

### Problema 2

```python
# define valores das resistências
R1 = m[1]+1
R2 = m[2]+1
print('R1 = ', R1, 'Ω', ' R2 = ', R2, 'Ω',)
```

    R1 =  2 Ω  R2 =  5 Ω

a. Correntes de malha

```python
# define as variáveis
i1, i2, i3, ix = sp.symbols('i1, i2, i3, ix')

# define os sistema de equações
eq1 = sp.Eq(i1+2*ix,0)
eq2 = sp.Eq(i2+ix,0)
eq3 = sp.Eq(i3-0.5,0)
eq4 = sp.Eq(-R2*(i1-i2)-10+2*R1*(i2-i3)+3*R1*i2,0)

# resolve o sistema
soluc = sp.solve((eq1, eq2, eq3, eq4), dict=True)
print('Equações: \n\n', eq1,'\n', eq2,'\n', eq3,'\n', eq4,'\n')

i1 = np.array([sol[i1] for sol in soluc])
i2 = np.array([sol[i2] for sol in soluc])
i3 = np.array([sol[i3] for sol in soluc])
ix = np.array([sol[ix] for sol in soluc])

print('Correntes de malha:\n\n i1 = %.2f A,\n i2 = %.2f A,\n i3 = %.2f A,\n ix = %.2f A.' %(i1, i2, i3, ix))
```

    Equações:

     Eq(i1 + 2*ix, 0)
     Eq(i2 + ix, 0)
     Eq(i3 - 0.5, 0)
     Eq(-5*i1 + 15*i2 - 4*i3 - 10, 0)

    Correntes de malha:

     i1 = 4.80 A,
     i2 = 2.40 A,
     i3 = 0.50 A,
     ix = -2.40 A.

b. $v_a=?$,  $v_b=?$

```python
va = R2*(i1-i2)
vb = 2*R1*(i2-i3)

print('va = %.2f V' %(va))
print('vb = %.2f V' %(vb))
```

    va = 12.00 V
    vb = 7.60 V

c. Potências

```python
# tensões desconhecidas
v_cI = R1*i1 + va
v_I  = vb - 7*R2*i3

# potências
p_cI = 2*ix*v_cI
p_V  = -10*i2
p_I  = v_I*i3
p_R  = R1*i1**2 + R2*(i1-i2)**2 + 3*R1*i2**2 + 2*R1*(i2-i3)**2 + 7*R2*i3**2

print('Potências:\n\n p_CI = %.2f W,\n p_V = %.2f W,\n p_I = %.2f W,\n p_R = %.2f W.\n' %(p_cI, p_V, p_I, p_R))
print('Soma das potências: %.2f W.'%(p_cI+p_V+p_I+p_R))
```

    Potências:

     p_CI = -103.68 W,
     p_V = -24.00 W,
     p_I = -4.95 W,
     p_R = 132.63 W.

    Soma das potências: 0.00 W.

### Problema 3

a. $v_{th}=?$ utilizando o princípio da superposição

```python
# define valores das resistências
R1 = m[0]+1
R2 = m[1]+1
R3 = m[2]+1
```

```python
# define variáveis auxiliares x, y, z
x = 12
y = 2
z = 10

vth = 0
for ind in range(0,3):
    # define as variáveis
    v1, v2, v3 = sp.symbols('v1, v2, v3')
    if ind == 0: # fonte de corrente 1A
        x = 12
        y = 0
        z = 0
    elif ind == 1:# fonte de tensão 2V
        x = 0
        y = 2
        z = 0
    elif ind == 2:# fonte de tensão 10V
        x = 0
        y = 0
        z = 10

    # define os sistema de equações
    eq1 = sp.Eq(-v1/(R1+12) -v1/2 - (v2-v3)/3 - (v2-v3)/(R3+2), -x/(R1+12)+y/(R3+2))
    eq2 = sp.Eq(v2-v1, z)
    eq3 = sp.Eq(-v3/R2 + (v2-v3)/3 + (v2-v3)/(R3+2), -y/(R3+2))

    # resolve o sistema
    soluc = sp.solve((eq1, eq2, eq3), dict=True)

    v1 = np.array([sol[v1] for sol in soluc])
    v2 = np.array([sol[v2] for sol in soluc])
    v3 = np.array([sol[v3] for sol in soluc])

    vth = vth + (-v3)

    print('vth %d = %.2f V' %(ind+1, -v3))

print('vth(superposição) = %.2f V' %(vth))
```

    vth 1 = -0.43 V
    vth 2 = -0.20 V
    vth 3 = -3.40 V
    vth(superposição) = -4.03 V

b. $R_{th}=?$

```python
# Rth via resistência equivalente
Req1 = ((R1+12)*2)/(R1+14)
Req2 = ((R3+2)*3)/(R3+5)

Req = ((Req1+Req2)*R2)/(Req1+Req2+R2)
print('Via resistência equivalente:')
print('Rth = %.2f Ω\n' %(Req))

# Rth via Icc

# define variáveis auxiliares x, y, z
x = 12  # fonte de corrente 1A (transformada para fonte de tensão)
y = 2   # fonte de tensão 2V
z = 10  # fonte de tensão 10V

# define as variáveis
v1, v2 = sp.symbols('v1, v2')

# define os sistema de equações
eq1 = sp.Eq(-v1/(R1+12) -v1/2 - v2/3 - v2/(R3+2), -x/(R1+12)+y/(R3+2))
eq2 = sp.Eq(v2-v1, z)

# resolve o sistema
soluc = sp.solve((eq1, eq2), dict=True)

v1 = np.array([sol[v1] for sol in soluc])
v2 = np.array([sol[v2] for sol in soluc])

icc = -v2/3 - (v2+2)/(R3+2)

# calcula vth/icc
Rth = vth/icc

print('Via corrente de curto circuito:')
print('Rth = %.2f Ω' %(Rth))
```

    Via resistência equivalente:
    Rth = 1.32 Ω

    Via corrente de curto circuito:
    Rth = 1.32 Ω

c. $R_L=?$ tal que $\eta = 0.9$, onde $\eta = \frac{v_{th}i}{R_Li^2}$.

```python
print('RL = %.2f Ω' %(9*Rth))
```

    RL = 11.89 Ω

Jupyter notebooks/.ipynb_checkpoints/Circuitos Eletricos I - Primeiro Estagio 2020.1e-checkpoint.ipynb