```python
import sympy as sp
import pandas as pd
from operator import mul
from functools import reduce
```


```python
def print_derivatives(nodes, *args):
    index = nodes
    cols = ['f' + i * '\'' for i in range(len(derivatives_per_node[0]))]
    return pd.DataFrame(derivatives_per_node, index=index, columns=cols)
```


```python
def calculate_div_diffs(nodes, *args, max_order=None):
    derivatives_per_node = list(zip(*args))
    max_order_per_node = [len([j for j in i if j != None]) for i in derivatives_per_node]
    if max_order == None:
        max_order = sum(max_order_per_node)
        
    nodes_with_order = [nodes[i] for i in range(len(nodes)) for j in range(max_order_per_node[i])]
    values_with_order = [args[0][i] for i in range(len(nodes)) for j in range(max_order_per_node[i])]
    node_to_pos = {n: p for p, n in enumerate(nodes)}
    nwo_to_pos = {i: node_to_pos[nodes_with_order[i]] for i in range(len(nodes_with_order))}
    
    diffs = [values_with_order]
    for order in range(max_order - 1):
        current_diffs = []
        for i in range(1, len(nodes_with_order) - order):
            if nodes_with_order[i + order] == nodes_with_order[i - 1]:
                current_diffs.append(
                    (derivatives_per_node[nwo_to_pos[i]][order + 1]) / 
                    (reduce(mul, [1] + [j for j in range(1, order + 1)]))
                )
            else:
                p = diffs[-1][i] - diffs[-1][i-1]
                current_diffs.append((diffs[-1][i] - diffs[-1][i-1]) / (nodes_with_order[i + order] - nodes_with_order[i-1]))
        if len(current_diffs) == 0:
            break
        diffs.append(current_diffs)
    return diffs
```


```python
def print_diffs(diffs):
    rows = 2 * len(diffs[0]) - 1
    for r in range(rows):
        row = '\t' if r % 2 == 1 else ''
        for i in range(r % 2, min(rows - r, min(r + 1, len(diffs))), 2):
            row += f'{float(diffs[i][(r - i) // 2]):.3f}\t\t'
        print(row[:-2])
```


```python
nodes = [-1, 1, 2, 3]
fvals = [7, -11, -5, 43]
dfvals = [None, 5, 1, None]
ddfvals = [None, -22, None, None]
```


```python
derivatives_per_node = list(zip(fvals, dfvals, ddfvals))
max_order_per_node = [len([j for j in i if j != None]) for i in derivatives_per_node]
nodes_with_order = [nodes[i] for i in range(len(nodes)) for j in range(max_order_per_node[i])]
```


```python
print_derivatives(nodes, fvals, dfvals, ddfvals)
```




<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>f</th>
      <th>f'</th>
      <th>f''</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>-1</th>
      <td>7</td>
      <td>NaN</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>1</th>
      <td>-11</td>
      <td>5.0</td>
      <td>-22.0</td>
    </tr>
    <tr>
      <th>2</th>
      <td>-5</td>
      <td>1.0</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>3</th>
      <td>43</td>
      <td>NaN</td>
      <td>NaN</td>
    </tr>
  </tbody>
</table>
</div>




```python
dds = calculate_div_diffs(nodes, fvals, dfvals, ddfvals)
```


```python
print_diffs(dds)
```

    7.000
    	-9.000
    -11.000		7.000
    	5.000		-14.500
    -11.000		-22.000		12.500
    	5.000		23.000		-13.833
    -11.000		1.000		-29.000		9.083
    	6.000		-6.000		22.500
    -5.000		-5.000		16.000
    	1.000		26.000
    -5.000		47.000
    	48.000
    43.000



```python
x = sp.symbols('x')
polynom = 0
mult = 1
for i in range(len(dds)):
    polynom += dds[i][0] * mult
    mult *= x - nodes_with_order[i]
```


```python
sp.expand(polynom)
```




$\displaystyle 9.08333333333333 x^{6} - 68.3333333333333 x^{5} + 176.833333333333 x^{4} - 149.333333333333 x^{3} - 87.9166666666667 x^{2} + 208.666666666667 x - 100.0$




```python
polynom_test = []
dp = polynom
for i in range(len(derivatives_per_node[0])):
    f_i = []
    for j in range(len(nodes)):
        if derivatives_per_node[j][i] != None:
            f_i.append(dp.evalf(subs={x: nodes[i]}))
        else:
            f_i.append(None)
    dp = sp.diff(dp)
    polynom_test.append(f_i)
```


```python
print_derivatives(nodes, *polynom_test)
```




<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>f</th>
      <th>f'</th>
      <th>f''</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>-1</th>
      <td>7</td>
      <td>NaN</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>1</th>
      <td>-11</td>
      <td>5.0</td>
      <td>-22.0</td>
    </tr>
    <tr>
      <th>2</th>
      <td>-5</td>
      <td>1.0</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>3</th>
      <td>43</td>
      <td>NaN</td>
      <td>NaN</td>
    </tr>
  </tbody>
</table>
</div>



d40caecb44148f0a8b5f8dd21c5569caee743c02
ipynb
Jupyter Notebook
year-2/computational-workshop/task-4.ipynb
Sergobot/university
7cd8c07fc660f1e19127c6488991ddd59d99643c
MIT
2019-09-05T08:43:47.000Z
2019-09-05T08:43:52.000Z
year-2/computational-workshop/task-4.ipynb
Sergobot/university
7cd8c07fc660f1e19127c6488991ddd59d99643c
MIT
year-2/computational-workshop/task-4.ipynb
Sergobot/university
7cd8c07fc660f1e19127c6488991ddd59d99643c
MIT
2020-10-04T07:40:20.000Z
2021-09-18T07:12:08.000Z
Qwen/Qwen-72B
1. YES
2. YES