Numerično integriranje#
Uvod#
V okviru tega poglavja bomo za dano funkcijo \(f(x)\) izračunali določen integral:
kjer sta \(a\) in \(b\) meji integriranja, \(f(x)\) pa so vrednosti funkcije, ki jih pridobimo iz tabele vrednosti ali s pomočjo analitične funkcije.
Pri numeričnem integriranju integral ocenimo z \(I\) in velja
kjer je \(E\) napaka ocene integrala.
Numerični integral bomo računali na podlagi diskretne vsote:
kjer so \(A_i\) uteži, \(x_i\) pa vozlišča na intervalu \([a, b]\) in je \(m+1\) število vozlišč.
Ogledali si bomo dva različna pristopa k numerični integraciji:
Newton-Cotesov pristop, ki temelji na ekvidistantnih vozliščih (konstanten korak integracije) in
Gaussov integracijski pristop, kjer so vozlišča postavljena tako, da se doseže natančnost za polinome.
Motivacijski primer#
Pri numeričnem integriranju si bomo pomagali s konkretnim primerom:
Pripravimo si vozlišča. Osnovni korak naj bo \(h=0.25\), v tem primeru imamo štiri podintervale in pet vozlišč, pri koraku \(2h\) so tri vozliščne točke in pri koraku \(4h\) samo dve (skrajni):
import numpy as np
xg, hg = np.linspace(1, 2, 100, retstep=True) # goste točke (za prikaz)
x2v, h2v = np.linspace(1, 2, 2, retstep=True) # korak h2v = 1 (2 vozlišči)
x3v, h3v = np.linspace(1, 2, 3, retstep=True) # korak h3v = 0.5 (3 vozlišča)
x4v, h4v = np.linspace(1, 2, 4, retstep=True) # korak h4v = 0.33.. (4 vozlišča)
x5v, h5v = np.linspace(1, 2, 5, retstep=True) # korak h5v = 0.25 (5 vozlišč)
Pripravimo še funkcijske vrednosti:
yg = xg * np.sin(xg)
y2v = x2v * np.sin(x2v)
y3v = x3v * np.sin(x3v)
y4v = x4v * np.sin(x4v)
y5v = x5v * np.sin(x5v)
Pripravimo prikaz podatkov:
import matplotlib.pyplot as plt
from matplotlib import rc # to uvozimo, da so fonti na sliki latex ustrezni
#rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']})
rc('text', usetex=True)
%matplotlib inline
def fig_motivacija():
plt.fill_between(xg, yg, alpha=0.25, facecolor='r')
plt.annotate(r'$\int_1^2\,x\,\sin(x)\,\textrm{d}x$', (1.3, 0.5), fontsize=22)
plt.plot(xg, yg, lw=3, alpha=0.5, label=r'$x\,\sin(x)$')
plt.plot(x2v, y2v, 's', alpha=0.5, label=f'$h={h2v}$', markersize=14)
plt.plot(x3v, y3v, 'o', alpha=0.5, label=f'$h={h3v}$', markersize=10)
plt.legend(loc=(1.01, 0))
plt.ylim(0, 2)
plt.show()
Prikažimo podatke:
fig_motivacija()
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:250, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
249 try:
--> 250 report = subprocess.check_output(
251 command, cwd=cwd if cwd is not None else cls._texcache,
252 stderr=subprocess.STDOUT)
253 except FileNotFoundError as exc:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:466, in check_output(timeout, *popenargs, **kwargs)
464 kwargs['input'] = empty
--> 466 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
467 **kwargs).stdout
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:548, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
546 kwargs['stderr'] = PIPE
--> 548 with Popen(*popenargs, **kwargs) as process:
549 try:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:1026, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize, process_group)
1023 self.stderr = io.TextIOWrapper(self.stderr,
1024 encoding=encoding, errors=errors)
-> 1026 self._execute_child(args, executable, preexec_fn, close_fds,
1027 pass_fds, cwd, env,
1028 startupinfo, creationflags, shell,
1029 p2cread, p2cwrite,
1030 c2pread, c2pwrite,
1031 errread, errwrite,
1032 restore_signals,
1033 gid, gids, uid, umask,
1034 start_new_session, process_group)
1035 except:
1036 # Cleanup if the child failed starting.
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:1955, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group)
1954 if err_filename is not None:
-> 1955 raise child_exception_type(errno_num, err_msg, err_filename)
1956 else:
FileNotFoundError: [Errno 2] No such file or directory: 'latex'
The above exception was the direct cause of the following exception:
RuntimeError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backend_bases.py:2157, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
2154 # we do this instead of `self.figure.draw_without_rendering`
2155 # so that we can inject the orientation
2156 with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2157 self.figure.draw(renderer)
2158 if bbox_inches:
2159 if bbox_inches == "tight":
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:94, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
92 @wraps(draw)
93 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 94 result = draw(artist, renderer, *args, **kwargs)
95 if renderer._rasterizing:
96 renderer.stop_rasterizing()
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/figure.py:3264, in Figure.draw(self, renderer)
3261 # ValueError can occur when resizing a window.
3263 self.patch.draw(renderer)
-> 3264 mimage._draw_list_compositing_images(
3265 renderer, self, artists, self.suppressComposite)
3267 renderer.close_group('figure')
3268 finally:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/image.py:134, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
132 if not_composite or not has_images:
133 for a in artists:
--> 134 a.draw(renderer)
135 else:
136 # Composite any adjacent images together
137 image_group = []
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axes/_base.py:3226, in _AxesBase.draw(self, renderer)
3223 if artists_rasterized:
3224 _draw_rasterized(self.get_figure(root=True), artists_rasterized, renderer)
-> 3226 mimage._draw_list_compositing_images(
3227 renderer, self, artists, self.get_figure(root=True).suppressComposite)
3229 renderer.close_group('axes')
3230 self.stale = False
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/image.py:134, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
132 if not_composite or not has_images:
133 for a in artists:
--> 134 a.draw(renderer)
135 else:
136 # Composite any adjacent images together
137 image_group = []
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1405, in Axis.draw(self, renderer)
1402 renderer.open_group(__name__, gid=self.get_gid())
1404 ticks_to_draw = self._update_ticks()
-> 1405 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
1407 for tick in ticks_to_draw:
1408 tick.draw(renderer)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1332, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
1330 if renderer is None:
1331 renderer = self.get_figure(root=True)._get_renderer()
-> 1332 return ([tick.label1.get_window_extent(renderer)
1333 for tick in ticks if tick.label1.get_visible()],
1334 [tick.label2.get_window_extent(renderer)
1335 for tick in ticks if tick.label2.get_visible()])
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1332, in <listcomp>(.0)
1330 if renderer is None:
1331 renderer = self.get_figure(root=True)._get_renderer()
-> 1332 return ([tick.label1.get_window_extent(renderer)
1333 for tick in ticks if tick.label1.get_visible()],
1334 [tick.label2.get_window_extent(renderer)
1335 for tick in ticks if tick.label2.get_visible()])
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:969, in Text.get_window_extent(self, renderer, dpi)
964 raise RuntimeError(
965 "Cannot get window extent of text w/o renderer. You likely "
966 "want to call 'figure.draw_without_rendering()' first.")
968 with cbook._setattr_cm(fig, dpi=dpi):
--> 969 bbox, info, descent = self._get_layout(self._renderer)
970 x, y = self.get_unitless_position()
971 x, y = self.get_transform().transform((x, y))
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:373, in Text._get_layout(self, renderer)
370 ys = []
372 # Full vertical extent of font, including ascenders and descenders:
--> 373 _, lp_h, lp_d = _get_text_metrics_with_cache(
374 renderer, "lp", self._fontproperties,
375 ismath="TeX" if self.get_usetex() else False,
376 dpi=self.get_figure(root=True).dpi)
377 min_dy = (lp_h - lp_d) * self._linespacing
379 for i, line in enumerate(lines):
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:69, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
66 """Call ``renderer.get_text_width_height_descent``, caching the results."""
67 # Cached based on a copy of fontprop so that later in-place mutations of
68 # the passed-in argument do not mess up the cache.
---> 69 return _get_text_metrics_with_cache_impl(
70 weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:77, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
73 @functools.lru_cache(4096)
74 def _get_text_metrics_with_cache_impl(
75 renderer_ref, text, fontprop, ismath, dpi):
76 # dpi is unused, but participates in cache invalidation (via the renderer).
---> 77 return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backends/backend_agg.py:211, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
209 _api.check_in_list(["TeX", True, False], ismath=ismath)
210 if ismath == "TeX":
--> 211 return super().get_text_width_height_descent(s, prop, ismath)
213 if ismath:
214 ox, oy, width, height, descent, font_image = \
215 self.mathtext_parser.parse(s, self.dpi, prop)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backend_bases.py:566, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
562 fontsize = prop.get_size_in_points()
564 if ismath == 'TeX':
565 # todo: handle properties
--> 566 return self.get_texmanager().get_text_width_height_descent(
567 s, fontsize, renderer=self)
569 dpi = self.points_to_pixels(72)
570 if ismath:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:364, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
362 if tex.strip() == '':
363 return 0, 0, 0
--> 364 dvifile = cls.make_dvi(tex, fontsize)
365 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
366 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:293, in TexManager.make_dvi(cls, tex, fontsize)
290 with TemporaryDirectory(dir=dvifile.parent) as tmpdir:
291 Path(tmpdir, "file.tex").write_text(
292 cls._get_tex_source(tex, fontsize), encoding='utf-8')
--> 293 cls._run_checked_subprocess(
294 ["latex", "-interaction=nonstopmode", "-halt-on-error",
295 "-no-shell-escape", "file.tex"], tex, cwd=tmpdir)
296 Path(tmpdir, "file.dvi").replace(dvifile)
297 # Also move the tex source to the main cache directory, but
298 # only for backcompat.
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:254, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
250 report = subprocess.check_output(
251 command, cwd=cwd if cwd is not None else cls._texcache,
252 stderr=subprocess.STDOUT)
253 except FileNotFoundError as exc:
--> 254 raise RuntimeError(
255 f'Failed to process string with tex because {command[0]} '
256 'could not be found') from exc
257 except subprocess.CalledProcessError as exc:
258 raise RuntimeError(
259 '{prog} was not able to process the following string:\n'
260 '{tex!r}\n\n'
(...) 267 exc=exc.output.decode('utf-8', 'backslashreplace'))
268 ) from None
RuntimeError: Failed to process string with tex because latex could not be found
<Figure size 640x480 with 1 Axes>
Analitično izračunajmo točen rezultat:
import sympy as sym
sym.init_printing()
x = sym.symbols('x')
I_točno = float(sym.integrate(x*sym.sin(x), (x, 1, 2)).evalf())
I_točno
Newton-Cotesov pristop#
Na sliki je prikazan splošen primer, kjer je razdalja med vozlišči \(x_i\) enaka \(h\) (gre za ekvidistantno delitev).

V okviru tega poglavja si bomo najprej pogledali trapezno ter sestavljeno trapezno pravilo, pozneje pa bosta sledili še Simpsonova ter Rombergova metoda.
Trapezno pravilo#
Trapezno pravilo vrednosti podintegralske funkcije \(f(x)\) na (pod)intervalu \([x_0, x_1]\) interpolira z linearno funkcijo. Za dve vozliščni točki to pomeni, da površino pod grafom funkcije približno izračunamo kot:
In so uteži:
Numerična implementacija#
Numerična implementacija je:
def trapezno(y, h):
"""
Trapezno pravilo integriranja.
:param y: funkcijske vrednosti
:param h: korak integriranja
"""
return (y[0] + y[-1])*h/2
Numerični zgled#
V konkretnem primeru to pomeni, da prvo in zadnjo funkcijsko vrednost utežimo s \(h/2\). V našem primeru je \(h=1\):
I_trapezno = trapezno(y2v, h=h2v)
I_trapezno
Pripravimo sliko:
def fig_trapezno():
plt.fill_between(x2v, y2v, alpha=0.25, facecolor='r')
plt.vlines(x2v, 0, y2v, color='r', linestyles='dashed', lw=1)
plt.annotate('$I_{\\textrm{trapezno}}$', (1.4, 0.5), fontsize=22)
plt.annotate('Napaka', fontsize=20, xy=(1.5, 1.4), xytext=(1.6, 1.8),
arrowprops=dict(facecolor='gray', shrink=0.05))
plt.plot(xg, yg, lw=3, alpha=0.5, label='$x\\,\\sin(x)$')
plt.plot(x2v, y2v, 'o', alpha=0.5, label=f'$h={h2v}$')
plt.legend(loc=(1.01, 0))
plt.ylim(0, 2)
plt.show()
Prikažemo:
fig_trapezno()
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:250, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
249 try:
--> 250 report = subprocess.check_output(
251 command, cwd=cwd if cwd is not None else cls._texcache,
252 stderr=subprocess.STDOUT)
253 except FileNotFoundError as exc:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:466, in check_output(timeout, *popenargs, **kwargs)
464 kwargs['input'] = empty
--> 466 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
467 **kwargs).stdout
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:548, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
546 kwargs['stderr'] = PIPE
--> 548 with Popen(*popenargs, **kwargs) as process:
549 try:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:1026, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize, process_group)
1023 self.stderr = io.TextIOWrapper(self.stderr,
1024 encoding=encoding, errors=errors)
-> 1026 self._execute_child(args, executable, preexec_fn, close_fds,
1027 pass_fds, cwd, env,
1028 startupinfo, creationflags, shell,
1029 p2cread, p2cwrite,
1030 c2pread, c2pwrite,
1031 errread, errwrite,
1032 restore_signals,
1033 gid, gids, uid, umask,
1034 start_new_session, process_group)
1035 except:
1036 # Cleanup if the child failed starting.
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:1955, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group)
1954 if err_filename is not None:
-> 1955 raise child_exception_type(errno_num, err_msg, err_filename)
1956 else:
FileNotFoundError: [Errno 2] No such file or directory: 'latex'
The above exception was the direct cause of the following exception:
RuntimeError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backend_bases.py:2157, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
2154 # we do this instead of `self.figure.draw_without_rendering`
2155 # so that we can inject the orientation
2156 with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2157 self.figure.draw(renderer)
2158 if bbox_inches:
2159 if bbox_inches == "tight":
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:94, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
92 @wraps(draw)
93 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 94 result = draw(artist, renderer, *args, **kwargs)
95 if renderer._rasterizing:
96 renderer.stop_rasterizing()
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/figure.py:3264, in Figure.draw(self, renderer)
3261 # ValueError can occur when resizing a window.
3263 self.patch.draw(renderer)
-> 3264 mimage._draw_list_compositing_images(
3265 renderer, self, artists, self.suppressComposite)
3267 renderer.close_group('figure')
3268 finally:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/image.py:134, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
132 if not_composite or not has_images:
133 for a in artists:
--> 134 a.draw(renderer)
135 else:
136 # Composite any adjacent images together
137 image_group = []
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axes/_base.py:3226, in _AxesBase.draw(self, renderer)
3223 if artists_rasterized:
3224 _draw_rasterized(self.get_figure(root=True), artists_rasterized, renderer)
-> 3226 mimage._draw_list_compositing_images(
3227 renderer, self, artists, self.get_figure(root=True).suppressComposite)
3229 renderer.close_group('axes')
3230 self.stale = False
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/image.py:134, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
132 if not_composite or not has_images:
133 for a in artists:
--> 134 a.draw(renderer)
135 else:
136 # Composite any adjacent images together
137 image_group = []
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1405, in Axis.draw(self, renderer)
1402 renderer.open_group(__name__, gid=self.get_gid())
1404 ticks_to_draw = self._update_ticks()
-> 1405 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
1407 for tick in ticks_to_draw:
1408 tick.draw(renderer)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1332, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
1330 if renderer is None:
1331 renderer = self.get_figure(root=True)._get_renderer()
-> 1332 return ([tick.label1.get_window_extent(renderer)
1333 for tick in ticks if tick.label1.get_visible()],
1334 [tick.label2.get_window_extent(renderer)
1335 for tick in ticks if tick.label2.get_visible()])
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1332, in <listcomp>(.0)
1330 if renderer is None:
1331 renderer = self.get_figure(root=True)._get_renderer()
-> 1332 return ([tick.label1.get_window_extent(renderer)
1333 for tick in ticks if tick.label1.get_visible()],
1334 [tick.label2.get_window_extent(renderer)
1335 for tick in ticks if tick.label2.get_visible()])
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:969, in Text.get_window_extent(self, renderer, dpi)
964 raise RuntimeError(
965 "Cannot get window extent of text w/o renderer. You likely "
966 "want to call 'figure.draw_without_rendering()' first.")
968 with cbook._setattr_cm(fig, dpi=dpi):
--> 969 bbox, info, descent = self._get_layout(self._renderer)
970 x, y = self.get_unitless_position()
971 x, y = self.get_transform().transform((x, y))
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:373, in Text._get_layout(self, renderer)
370 ys = []
372 # Full vertical extent of font, including ascenders and descenders:
--> 373 _, lp_h, lp_d = _get_text_metrics_with_cache(
374 renderer, "lp", self._fontproperties,
375 ismath="TeX" if self.get_usetex() else False,
376 dpi=self.get_figure(root=True).dpi)
377 min_dy = (lp_h - lp_d) * self._linespacing
379 for i, line in enumerate(lines):
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:69, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
66 """Call ``renderer.get_text_width_height_descent``, caching the results."""
67 # Cached based on a copy of fontprop so that later in-place mutations of
68 # the passed-in argument do not mess up the cache.
---> 69 return _get_text_metrics_with_cache_impl(
70 weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:77, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
73 @functools.lru_cache(4096)
74 def _get_text_metrics_with_cache_impl(
75 renderer_ref, text, fontprop, ismath, dpi):
76 # dpi is unused, but participates in cache invalidation (via the renderer).
---> 77 return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backends/backend_agg.py:211, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
209 _api.check_in_list(["TeX", True, False], ismath=ismath)
210 if ismath == "TeX":
--> 211 return super().get_text_width_height_descent(s, prop, ismath)
213 if ismath:
214 ox, oy, width, height, descent, font_image = \
215 self.mathtext_parser.parse(s, self.dpi, prop)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backend_bases.py:566, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
562 fontsize = prop.get_size_in_points()
564 if ismath == 'TeX':
565 # todo: handle properties
--> 566 return self.get_texmanager().get_text_width_height_descent(
567 s, fontsize, renderer=self)
569 dpi = self.points_to_pixels(72)
570 if ismath:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:364, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
362 if tex.strip() == '':
363 return 0, 0, 0
--> 364 dvifile = cls.make_dvi(tex, fontsize)
365 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
366 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:293, in TexManager.make_dvi(cls, tex, fontsize)
290 with TemporaryDirectory(dir=dvifile.parent) as tmpdir:
291 Path(tmpdir, "file.tex").write_text(
292 cls._get_tex_source(tex, fontsize), encoding='utf-8')
--> 293 cls._run_checked_subprocess(
294 ["latex", "-interaction=nonstopmode", "-halt-on-error",
295 "-no-shell-escape", "file.tex"], tex, cwd=tmpdir)
296 Path(tmpdir, "file.dvi").replace(dvifile)
297 # Also move the tex source to the main cache directory, but
298 # only for backcompat.
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:254, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
250 report = subprocess.check_output(
251 command, cwd=cwd if cwd is not None else cls._texcache,
252 stderr=subprocess.STDOUT)
253 except FileNotFoundError as exc:
--> 254 raise RuntimeError(
255 f'Failed to process string with tex because {command[0]} '
256 'could not be found') from exc
257 except subprocess.CalledProcessError as exc:
258 raise RuntimeError(
259 '{prog} was not able to process the following string:\n'
260 '{tex!r}\n\n'
(...) 267 exc=exc.output.decode('utf-8', 'backslashreplace'))
268 ) from None
RuntimeError: Failed to process string with tex because latex could not be found
<Figure size 640x480 with 1 Axes>
Napaka trapeznega pravila#
Razlika med analitično vrednostjo integrala in numeričnim približkom \(I\) je napaka metode:
Če je funkcija \(f(x)\) vsaj dvakrat odvedljiva, se lahko (glejte npr. vir: Burden, Faires, Burden: Numerical Analysis 10th Ed) izpelje ocena napake, ki velja samo za trapezni približek prek celega integracijskega intervala:
kjer je \(h=b-a\) in \(\xi\) neznana vrednost na intervalu \([a,b]\).
Sestavljeno trapezno pravilo#
Če razdelimo interval \([a, b]\) na \(n\) podintervalov in na vsakem uporabimo trapezno pravilo integriranja, govorimo o sestavljenem trapeznem pravilu (angl. composite trapezoidal rule).
V tem primeru za vsak podinterval \(i\) uporabimo trapezno pravilo in torej za meje podinterval \(x_i\) in \(x_{i+1}\) uporabimo uteži \(A_i=A_{i+i}=h/2\). Ker so notranja vozlišča podvojena, sledi:
Pri tem smo predpostavili podintervale enake širine:
Sledi torej:
Numerična implementacija#
Numerična implementacija je:
def trapezno_sest(y, h):
"""
Sestavljeno trapezno pravilo integriranja.
:param y: funkcijske vrednosti
:param h: korak integriranja
"""
return (np.sum(y) - 0.5*y[0] - 0.5*y[-1])*h
Numerični zgled#
Zgoraj smo že pripravili podatke za dva podintervala (tri vozlišča):
x3v
array([1. , 1.5, 2. ])
h3v
Izračunajmo oceno integrala s sestavljenim trapeznim pravilom:
I_trapezno_sest = trapezno_sest(y3v, h=h3v)
I_trapezno_sest
Pripravimo sliko:
def fig_trapezno_sest():
plt.fill_between(x3v, y3v, alpha=0.25, facecolor='r')
plt.vlines(x3v, 0, y3v, color='r', linestyles='dashed', lw=1)
plt.annotate('$I_{\\textrm{trapezno sestavljeno}}$', (1.2, 0.5), fontsize=22)
plt.annotate('Napaka', fontsize=20, xy=(1.75, 1.68), xytext=(1.4, 1.8),
arrowprops=dict(facecolor='gray', shrink=0.05))
plt.annotate('Napaka', fontsize=20, xy=(1.2, 1.1), xytext=(1., 1.4),
arrowprops=dict(facecolor='gray', shrink=0.05))
plt.plot(xg, yg, lw=3, alpha=0.5, label='$x\\,\\sin(x)$')
plt.plot(x3v, y3v, 'o', alpha=0.5, label=f'$h={h3v}$')
plt.legend(loc=(1.01, 0))
plt.ylim(0, 2)
plt.show()
Prikažemo:
fig_trapezno_sest()
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:250, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
249 try:
--> 250 report = subprocess.check_output(
251 command, cwd=cwd if cwd is not None else cls._texcache,
252 stderr=subprocess.STDOUT)
253 except FileNotFoundError as exc:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:466, in check_output(timeout, *popenargs, **kwargs)
464 kwargs['input'] = empty
--> 466 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
467 **kwargs).stdout
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:548, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
546 kwargs['stderr'] = PIPE
--> 548 with Popen(*popenargs, **kwargs) as process:
549 try:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:1026, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize, process_group)
1023 self.stderr = io.TextIOWrapper(self.stderr,
1024 encoding=encoding, errors=errors)
-> 1026 self._execute_child(args, executable, preexec_fn, close_fds,
1027 pass_fds, cwd, env,
1028 startupinfo, creationflags, shell,
1029 p2cread, p2cwrite,
1030 c2pread, c2pwrite,
1031 errread, errwrite,
1032 restore_signals,
1033 gid, gids, uid, umask,
1034 start_new_session, process_group)
1035 except:
1036 # Cleanup if the child failed starting.
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:1955, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group)
1954 if err_filename is not None:
-> 1955 raise child_exception_type(errno_num, err_msg, err_filename)
1956 else:
FileNotFoundError: [Errno 2] No such file or directory: 'latex'
The above exception was the direct cause of the following exception:
RuntimeError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backend_bases.py:2157, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
2154 # we do this instead of `self.figure.draw_without_rendering`
2155 # so that we can inject the orientation
2156 with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2157 self.figure.draw(renderer)
2158 if bbox_inches:
2159 if bbox_inches == "tight":
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:94, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
92 @wraps(draw)
93 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 94 result = draw(artist, renderer, *args, **kwargs)
95 if renderer._rasterizing:
96 renderer.stop_rasterizing()
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/figure.py:3264, in Figure.draw(self, renderer)
3261 # ValueError can occur when resizing a window.
3263 self.patch.draw(renderer)
-> 3264 mimage._draw_list_compositing_images(
3265 renderer, self, artists, self.suppressComposite)
3267 renderer.close_group('figure')
3268 finally:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/image.py:134, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
132 if not_composite or not has_images:
133 for a in artists:
--> 134 a.draw(renderer)
135 else:
136 # Composite any adjacent images together
137 image_group = []
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axes/_base.py:3226, in _AxesBase.draw(self, renderer)
3223 if artists_rasterized:
3224 _draw_rasterized(self.get_figure(root=True), artists_rasterized, renderer)
-> 3226 mimage._draw_list_compositing_images(
3227 renderer, self, artists, self.get_figure(root=True).suppressComposite)
3229 renderer.close_group('axes')
3230 self.stale = False
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/image.py:134, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
132 if not_composite or not has_images:
133 for a in artists:
--> 134 a.draw(renderer)
135 else:
136 # Composite any adjacent images together
137 image_group = []
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1405, in Axis.draw(self, renderer)
1402 renderer.open_group(__name__, gid=self.get_gid())
1404 ticks_to_draw = self._update_ticks()
-> 1405 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
1407 for tick in ticks_to_draw:
1408 tick.draw(renderer)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1332, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
1330 if renderer is None:
1331 renderer = self.get_figure(root=True)._get_renderer()
-> 1332 return ([tick.label1.get_window_extent(renderer)
1333 for tick in ticks if tick.label1.get_visible()],
1334 [tick.label2.get_window_extent(renderer)
1335 for tick in ticks if tick.label2.get_visible()])
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1332, in <listcomp>(.0)
1330 if renderer is None:
1331 renderer = self.get_figure(root=True)._get_renderer()
-> 1332 return ([tick.label1.get_window_extent(renderer)
1333 for tick in ticks if tick.label1.get_visible()],
1334 [tick.label2.get_window_extent(renderer)
1335 for tick in ticks if tick.label2.get_visible()])
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:969, in Text.get_window_extent(self, renderer, dpi)
964 raise RuntimeError(
965 "Cannot get window extent of text w/o renderer. You likely "
966 "want to call 'figure.draw_without_rendering()' first.")
968 with cbook._setattr_cm(fig, dpi=dpi):
--> 969 bbox, info, descent = self._get_layout(self._renderer)
970 x, y = self.get_unitless_position()
971 x, y = self.get_transform().transform((x, y))
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:373, in Text._get_layout(self, renderer)
370 ys = []
372 # Full vertical extent of font, including ascenders and descenders:
--> 373 _, lp_h, lp_d = _get_text_metrics_with_cache(
374 renderer, "lp", self._fontproperties,
375 ismath="TeX" if self.get_usetex() else False,
376 dpi=self.get_figure(root=True).dpi)
377 min_dy = (lp_h - lp_d) * self._linespacing
379 for i, line in enumerate(lines):
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:69, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
66 """Call ``renderer.get_text_width_height_descent``, caching the results."""
67 # Cached based on a copy of fontprop so that later in-place mutations of
68 # the passed-in argument do not mess up the cache.
---> 69 return _get_text_metrics_with_cache_impl(
70 weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:77, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
73 @functools.lru_cache(4096)
74 def _get_text_metrics_with_cache_impl(
75 renderer_ref, text, fontprop, ismath, dpi):
76 # dpi is unused, but participates in cache invalidation (via the renderer).
---> 77 return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backends/backend_agg.py:211, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
209 _api.check_in_list(["TeX", True, False], ismath=ismath)
210 if ismath == "TeX":
--> 211 return super().get_text_width_height_descent(s, prop, ismath)
213 if ismath:
214 ox, oy, width, height, descent, font_image = \
215 self.mathtext_parser.parse(s, self.dpi, prop)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backend_bases.py:566, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
562 fontsize = prop.get_size_in_points()
564 if ismath == 'TeX':
565 # todo: handle properties
--> 566 return self.get_texmanager().get_text_width_height_descent(
567 s, fontsize, renderer=self)
569 dpi = self.points_to_pixels(72)
570 if ismath:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:364, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
362 if tex.strip() == '':
363 return 0, 0, 0
--> 364 dvifile = cls.make_dvi(tex, fontsize)
365 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
366 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:293, in TexManager.make_dvi(cls, tex, fontsize)
290 with TemporaryDirectory(dir=dvifile.parent) as tmpdir:
291 Path(tmpdir, "file.tex").write_text(
292 cls._get_tex_source(tex, fontsize), encoding='utf-8')
--> 293 cls._run_checked_subprocess(
294 ["latex", "-interaction=nonstopmode", "-halt-on-error",
295 "-no-shell-escape", "file.tex"], tex, cwd=tmpdir)
296 Path(tmpdir, "file.dvi").replace(dvifile)
297 # Also move the tex source to the main cache directory, but
298 # only for backcompat.
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:254, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
250 report = subprocess.check_output(
251 command, cwd=cwd if cwd is not None else cls._texcache,
252 stderr=subprocess.STDOUT)
253 except FileNotFoundError as exc:
--> 254 raise RuntimeError(
255 f'Failed to process string with tex because {command[0]} '
256 'could not be found') from exc
257 except subprocess.CalledProcessError as exc:
258 raise RuntimeError(
259 '{prog} was not able to process the following string:\n'
260 '{tex!r}\n\n'
(...) 267 exc=exc.output.decode('utf-8', 'backslashreplace'))
268 ) from None
RuntimeError: Failed to process string with tex because latex could not be found
<Figure size 640x480 with 1 Axes>
Napaka sestavljenega trapeznega pravila#
Napaka sestavljenega trapeznega pravila izhaja iz napake trapeznega pravila; pri tem tako napako naredimo \(n\)-krat.
Ker velja \(h\cdot n=b-a\), izpeljemo napako sestavljenega trapeznega pravila kot:
\(\eta\) je vrednost na intervalu \([a,b]\). Napaka je drugega reda \(\mathcal{O}(h^2)\).
Boljši približek integrala#
V nadaljevanju si bomo pogledali t. i. Richardsonovo ekstrapolacijo, pri kateri na podlagi ocene integrala s korakom \(h\) in \(2h\) izračunamo boljši približek.
V kolikor integral \(I\) numerično izračunamo pri dveh različnih korakih \(h\) in \(2\,h\), velja:
kjer sta \(I_h\) in \(I_{2h}\) približka integrala s korakom \(h\) in \(2h\) ter \(E_h\) in \(E_{2h}\) oceni napake pri koraku \(h\) in \(2h\). Izpeljemo \(I_{2h}-I_{h} = E_{h}-E_{2h}\)
Naprej zapišemo:
Ob predpostavki, da je \(f''\left (\eta \right )\) pri koraku \(h\) in \(2h\) enak (\(\eta\) je pri koraku \(h\) in \(2h\) dejansko različen), zapišemo:
Sledi:
Sedaj lahko ocenimo napako pri koraku \(h\):
Na podlagi ocene napake lahko izračunamo boljši numerični približek \(I_{h}^*\):
ali
Numerični zgled#
Predhodno smo s trapeznim pravilom že izračunali integral pri koraku \(h=1\) in pri koraku \(h=0,5\), rezultata sta bila:
[I_trapezno, I_trapezno_sest]
S pomočjo zgornje formule izračunamo boljši približek:
I_trapezno_boljši = 4/3*I_trapezno_sest - 1/3*I_trapezno
print(f'Točen rezultat: {I_točno}\nBoljši približek: {I_trapezno_boljši}')
Točen rezultat: 1.4404224209802097
Boljši približek: 1.4408392930139313
Sestavljeno trapezno pravilo je implementirano tudi v paketu numpy, s funkcijo numpy.trapz:
trapz(y, x=None, dx=1.0, axis=-1)
ypredstavlja tabelo funkcijskih vrednosti,xje opcijski parameter in definira vozlišča; če parameter ni definiran, se privzame ekvidistančna vozlišča na razdaljidx,dxdefinira (konstanten) korak integracije, ima privzeto vrednost 1,axisdefinira os po kateri se integrira (v primeru, da jeyvečdimenzijsko numerično polje).
Funkcija vrne izračunani integral po sestavljenem trapeznem pravilu. Več informacij lahko najdete v dokumentaciji.
numpy implementacija sestavljenega trapeznega pravila#
Poglejmo si primer:
#%%timeit
I_trapezno_np = np.trapezoid(y3v, dx=h3v)
I_trapezno_np
Simpsonova in druge metode#
Zgoraj smo si pogledali trapezno pravilo, ki temelji na linearni interpolacijski funkciji na posameznem podintervalu. Z interpolacijo višjega reda lahko izpeljemo še druge integracijske metode.
Izračunati moramo:
Tabeliramo podintegralsko funkcijo \(f(x)\) in tabelo interpoliramo z Lagrangevim interpolacijskim polinomom \(P_n(x)\) stopnje \(n\):
kjer so \(y_i=f(x_i)\) funkcijske vrednosti v vozliščih \(x_i\) in je Lagrangev polinom \(l_i\) definiran kot:
Za numerični izračun integrala \(\int_{a}^b f(x)\,dx\) (meje so: \(a=x_0\), \(b=x_n\)) namesto funkcije \(f(x)\) vstavimo v integral interpolacijski polinom \(P_n(x)\):
Ker je integriranje linearna operacija, lahko zamenjamo integriranje in vsoto:
Lagrangev polinom integriramo in dobimo uteži \(A_i\):
Izpeljava trapeznega pravila z uporabo Lagrangevih polinomov#
Poglejmo si kako z Lagrangevim interpolacijskim polinomom prve stopnje strojno izpeljemo uteži \(A_i\) v primeru trapeznega pravila.
Najprej v simbolni obliki definirajmo spremenljivko x, vozlišči x0 in x1 ter korak h:
x, x0, x1, h = sym.symbols('x x0, x1, h')
Pripravimo Python funkcijo, ki v simbolni obliki vrne seznam \(n\) koeficientov Lagrangevih polinomov \([l_0(x), l_1(x),\dots, l_{n-1}(x)]\) stopnje \(n-1\):
def lagrange(n, x, vozlišča_predpona='x'):
if isinstance(vozlišča_predpona, str):
vozlišča = sym.symbols(f'{vozlišča_predpona}:{n}')
coeffs = []
for i in range(0, n):
numer = []
denom = []
for j in range(0, n):
if i == j:
continue
numer.append(x - vozlišča[j])
denom.append(vozlišča[i] - vozlišča[j])
numer = sym.Mul(*numer)
denom = sym.Mul(*denom)
coeffs.append(numer/denom)
return coeffs
Najprej poglejmo Lagrangeva polinoma za linearno interpolacijo (\(n=2\)):
lag = lagrange(2, x)
lag
Sedaj Lagrangev polinom \(l_0(x)\) integriramo čez celotni interval:
int0 = sym.integrate(lag[0], (x, x0, x1))
int0
Izraz poenostavimo in dobimo:
int1 = int0.factor()
int1
Ker je širina podintervala konstantna je \(x_1=h_0+h\), izvedemo zamenjavo:
zamenjave = {x1: x0+h}
int1.subs(zamenjave)
Zgornje korake za Lagrangev polinom \(l_0(x)\) lahko posplošimo za seznam Lagrangevih polinomov:
x, x0, x1, h = sym.symbols('x, x0, x1, h')
zamenjave = {x1: x0+h}
A_trapez = [sym.integrate(li, (x, x0, x1)).factor().subs(zamenjave)
for li in lagrange(2, x)] # za vsak lagrangev polimom `li` v seznamu lagrange(2,x)
A_trapez
Izpeljali smo uteži, ki smo jih uporabili pri trapezni metodi:
Trapezno pravilo je:
Ocena napake je (vir: Burden, Faires, Burden: Numerical Analysis 10th Ed):
Izračun uteži za Simpsonovo pravilo#
Potem ko smo zgoraj pokazali strnjen izračun za trapezno pravilo, lahko podobno izvedemo za kvadratno interpolacijo čez tri točke (\(n=3\)).
Izračun uteži je analogen zgornjemu:
x, x0, x1, x2, h = sym.symbols('x, x0, x1, x2, h')
zamenjave = {x1: x0+h, x2: x0+2*h}
A_Simpson1_3 = [sym.integrate(li, (x, x0, x2)).factor().subs(zamenjave).factor()
for li in lagrange(3, x)]
A_Simpson1_3
Simpsonovo pravilo (to pravilo se imenuje tudi Simpsonovo 1/3 pravilo) je:
Ocena napake je (vir: Burden, Faires, Burden: Numerical Analysis 10th Ed):
Pri tem je treba izpostaviti, da je napaka lokalno 5 reda \(\mathcal{O}(h^5)\) in definirana z neznano vrednostjo četrtega odvoda \(f^{(4)}(\xi)\), posledično je to pravilo točno za polinome stopnje 3 ali manj.
Primer uporabe:
I_Simps = h3v/3 * np.sum(y3v * [1, 4, 1])
I_Simps
Pripravimo sliko. Ker Simsonovo pravilo temelji na kvadratni interpolaciji, moramo naprej pripraviti interpolacijski polinom (pomagamo si s scipy.interpolate):
from scipy import interpolate
def fig_Simpsonovo():
y_interpolate = interpolate.lagrange(x3v, y3v)
plt.fill_between(xg, y_interpolate(xg), alpha=0.25, facecolor='r')
plt.vlines(x3v, 0, y3v, color='r', linestyles='dashed', lw=1)
plt.annotate('$I_{\\textrm{Simpsonovo}}$', (1.2, 0.5), fontsize=22)
plt.annotate('Napaka', fontsize=20, xy=(1.75, 1.7), xytext=(1.4, 1.8),
arrowprops=dict(facecolor='gray', shrink=0.05))
plt.annotate('Napaka', fontsize=20, xy=(1.2, 1.1), xytext=(1., 1.4),
arrowprops=dict(facecolor='gray', shrink=0.05))
plt.plot(xg, yg, lw=3, alpha=0.5, label='$x\\,\\sin(x)$')
plt.plot(x3v, y3v, 'o', alpha=0.5, label=f'$h={h3v}$')
plt.legend(loc=(1.01, 0))
plt.ylim(0, 2)
plt.show()
Prikažemo:
fig_Simpsonovo()
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:250, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
249 try:
--> 250 report = subprocess.check_output(
251 command, cwd=cwd if cwd is not None else cls._texcache,
252 stderr=subprocess.STDOUT)
253 except FileNotFoundError as exc:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:466, in check_output(timeout, *popenargs, **kwargs)
464 kwargs['input'] = empty
--> 466 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
467 **kwargs).stdout
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:548, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
546 kwargs['stderr'] = PIPE
--> 548 with Popen(*popenargs, **kwargs) as process:
549 try:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:1026, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize, process_group)
1023 self.stderr = io.TextIOWrapper(self.stderr,
1024 encoding=encoding, errors=errors)
-> 1026 self._execute_child(args, executable, preexec_fn, close_fds,
1027 pass_fds, cwd, env,
1028 startupinfo, creationflags, shell,
1029 p2cread, p2cwrite,
1030 c2pread, c2pwrite,
1031 errread, errwrite,
1032 restore_signals,
1033 gid, gids, uid, umask,
1034 start_new_session, process_group)
1035 except:
1036 # Cleanup if the child failed starting.
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:1955, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group)
1954 if err_filename is not None:
-> 1955 raise child_exception_type(errno_num, err_msg, err_filename)
1956 else:
FileNotFoundError: [Errno 2] No such file or directory: 'latex'
The above exception was the direct cause of the following exception:
RuntimeError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backend_bases.py:2157, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
2154 # we do this instead of `self.figure.draw_without_rendering`
2155 # so that we can inject the orientation
2156 with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2157 self.figure.draw(renderer)
2158 if bbox_inches:
2159 if bbox_inches == "tight":
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:94, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
92 @wraps(draw)
93 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 94 result = draw(artist, renderer, *args, **kwargs)
95 if renderer._rasterizing:
96 renderer.stop_rasterizing()
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/figure.py:3264, in Figure.draw(self, renderer)
3261 # ValueError can occur when resizing a window.
3263 self.patch.draw(renderer)
-> 3264 mimage._draw_list_compositing_images(
3265 renderer, self, artists, self.suppressComposite)
3267 renderer.close_group('figure')
3268 finally:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/image.py:134, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
132 if not_composite or not has_images:
133 for a in artists:
--> 134 a.draw(renderer)
135 else:
136 # Composite any adjacent images together
137 image_group = []
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axes/_base.py:3226, in _AxesBase.draw(self, renderer)
3223 if artists_rasterized:
3224 _draw_rasterized(self.get_figure(root=True), artists_rasterized, renderer)
-> 3226 mimage._draw_list_compositing_images(
3227 renderer, self, artists, self.get_figure(root=True).suppressComposite)
3229 renderer.close_group('axes')
3230 self.stale = False
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/image.py:134, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
132 if not_composite or not has_images:
133 for a in artists:
--> 134 a.draw(renderer)
135 else:
136 # Composite any adjacent images together
137 image_group = []
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1405, in Axis.draw(self, renderer)
1402 renderer.open_group(__name__, gid=self.get_gid())
1404 ticks_to_draw = self._update_ticks()
-> 1405 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
1407 for tick in ticks_to_draw:
1408 tick.draw(renderer)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1332, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
1330 if renderer is None:
1331 renderer = self.get_figure(root=True)._get_renderer()
-> 1332 return ([tick.label1.get_window_extent(renderer)
1333 for tick in ticks if tick.label1.get_visible()],
1334 [tick.label2.get_window_extent(renderer)
1335 for tick in ticks if tick.label2.get_visible()])
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1332, in <listcomp>(.0)
1330 if renderer is None:
1331 renderer = self.get_figure(root=True)._get_renderer()
-> 1332 return ([tick.label1.get_window_extent(renderer)
1333 for tick in ticks if tick.label1.get_visible()],
1334 [tick.label2.get_window_extent(renderer)
1335 for tick in ticks if tick.label2.get_visible()])
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:969, in Text.get_window_extent(self, renderer, dpi)
964 raise RuntimeError(
965 "Cannot get window extent of text w/o renderer. You likely "
966 "want to call 'figure.draw_without_rendering()' first.")
968 with cbook._setattr_cm(fig, dpi=dpi):
--> 969 bbox, info, descent = self._get_layout(self._renderer)
970 x, y = self.get_unitless_position()
971 x, y = self.get_transform().transform((x, y))
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:373, in Text._get_layout(self, renderer)
370 ys = []
372 # Full vertical extent of font, including ascenders and descenders:
--> 373 _, lp_h, lp_d = _get_text_metrics_with_cache(
374 renderer, "lp", self._fontproperties,
375 ismath="TeX" if self.get_usetex() else False,
376 dpi=self.get_figure(root=True).dpi)
377 min_dy = (lp_h - lp_d) * self._linespacing
379 for i, line in enumerate(lines):
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:69, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
66 """Call ``renderer.get_text_width_height_descent``, caching the results."""
67 # Cached based on a copy of fontprop so that later in-place mutations of
68 # the passed-in argument do not mess up the cache.
---> 69 return _get_text_metrics_with_cache_impl(
70 weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:77, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
73 @functools.lru_cache(4096)
74 def _get_text_metrics_with_cache_impl(
75 renderer_ref, text, fontprop, ismath, dpi):
76 # dpi is unused, but participates in cache invalidation (via the renderer).
---> 77 return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backends/backend_agg.py:211, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
209 _api.check_in_list(["TeX", True, False], ismath=ismath)
210 if ismath == "TeX":
--> 211 return super().get_text_width_height_descent(s, prop, ismath)
213 if ismath:
214 ox, oy, width, height, descent, font_image = \
215 self.mathtext_parser.parse(s, self.dpi, prop)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backend_bases.py:566, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
562 fontsize = prop.get_size_in_points()
564 if ismath == 'TeX':
565 # todo: handle properties
--> 566 return self.get_texmanager().get_text_width_height_descent(
567 s, fontsize, renderer=self)
569 dpi = self.points_to_pixels(72)
570 if ismath:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:364, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
362 if tex.strip() == '':
363 return 0, 0, 0
--> 364 dvifile = cls.make_dvi(tex, fontsize)
365 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
366 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:293, in TexManager.make_dvi(cls, tex, fontsize)
290 with TemporaryDirectory(dir=dvifile.parent) as tmpdir:
291 Path(tmpdir, "file.tex").write_text(
292 cls._get_tex_source(tex, fontsize), encoding='utf-8')
--> 293 cls._run_checked_subprocess(
294 ["latex", "-interaction=nonstopmode", "-halt-on-error",
295 "-no-shell-escape", "file.tex"], tex, cwd=tmpdir)
296 Path(tmpdir, "file.dvi").replace(dvifile)
297 # Also move the tex source to the main cache directory, but
298 # only for backcompat.
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:254, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
250 report = subprocess.check_output(
251 command, cwd=cwd if cwd is not None else cls._texcache,
252 stderr=subprocess.STDOUT)
253 except FileNotFoundError as exc:
--> 254 raise RuntimeError(
255 f'Failed to process string with tex because {command[0]} '
256 'could not be found') from exc
257 except subprocess.CalledProcessError as exc:
258 raise RuntimeError(
259 '{prog} was not able to process the following string:\n'
260 '{tex!r}\n\n'
(...) 267 exc=exc.output.decode('utf-8', 'backslashreplace'))
268 ) from None
RuntimeError: Failed to process string with tex because latex could not be found
<Figure size 640x480 with 1 Axes>
scipy.integrate.newton_cotes#
Koeficiente integracijskega pristopa Newton-Cotes pridobimo tudi s pomočjo scipy.integrate.newton_cotes() dokumentacija:
newton_cotes(rn, equal=0)
kjer sta parametra:
rn, ki definira število podintervalov (mogoč je tudi nekonstanten korak, glejte dokumentacijo),equal, ki definira ali se zahteva konstantno široke podintervale.
Funkcija vrne terko, pri čemer prvi element predstavlja numerično polje uteži in drugi člen oceno napake.
Poglejmo si primer:
from scipy import integrate
integrate.newton_cotes(2)
(array([0.33333333, 1.33333333, 0.33333333]), -0.011111111111111112)
Izračun uteži za Simpsonovo 3/8 pravilo#
Nadaljujemo lahko s kubično interpolacijo čez štiri točke (\(n=4\)):
x, x0, x1, x2, x3, h = sym.symbols('x, x0, x1, x2, x3, h')
zamenjave = {x1: x0+h, x2: x0+2*h, x3: x0+3*h}
A_Simpson3_8 = [sym.integrate(li, (x, x0, x3)).factor().subs(zamenjave).factor()
for li in lagrange(4, x)]
A_Simpson3_8
Simpsonovo 3/8 pravilo je:
Ocena napake je (vir: Burden, Faires, Burden: Numerical Analysis 10th Ed):
Poglejmo si primer uporabe. Uporabimo pripravljeno tabelo vrednosti funkcije v štirih točkah:
y4v
array([0.84147098, 1.2959172 , 1.65901326, 1.81859485])
I_Simps38 = 3*h4v/8 * np.sum(y4v * [1, 3, 3, 1])
I_Simps38
Pripravimo še prikaz:
def fig_Simpsonovo38():
y_interpolate = interpolate.lagrange(x4v, y4v)
plt.fill_between(xg, y_interpolate(xg), alpha=0.25, facecolor='r')
plt.vlines(x4v, 0, y4v, color='r', linestyles='dashed', lw=1)
plt.annotate('$I_{\\textrm{Simpsonovo 3/8}}$', (1.2, 0.5), fontsize=22)
plt.annotate('Napaka', fontsize=20, xy=(1.75, 1.7), xytext=(1.4, 1.8),
arrowprops=dict(facecolor='gray', shrink=0.05))
plt.annotate('Napaka', fontsize=20, xy=(1.5, 1.47), xytext=(1.1, 1.6),
arrowprops=dict(facecolor='gray', shrink=0.05))
plt.annotate('Napaka', fontsize=20, xy=(1.2, 1.1), xytext=(1., 1.4),
arrowprops=dict(facecolor='gray', shrink=0.05))
plt.plot(xg, yg, lw=3, alpha=0.5, label='$x\\,\\sin(x)$')
plt.plot(x4v, y4v, 'o', alpha=0.5, label=f'$h={h4v:.6f}$')
plt.legend(loc=(1.01, 0))
plt.ylim(0, 2)
plt.show()
Prikažemo:
fig_Simpsonovo38()
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:250, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
249 try:
--> 250 report = subprocess.check_output(
251 command, cwd=cwd if cwd is not None else cls._texcache,
252 stderr=subprocess.STDOUT)
253 except FileNotFoundError as exc:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:466, in check_output(timeout, *popenargs, **kwargs)
464 kwargs['input'] = empty
--> 466 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
467 **kwargs).stdout
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:548, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
546 kwargs['stderr'] = PIPE
--> 548 with Popen(*popenargs, **kwargs) as process:
549 try:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:1026, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize, process_group)
1023 self.stderr = io.TextIOWrapper(self.stderr,
1024 encoding=encoding, errors=errors)
-> 1026 self._execute_child(args, executable, preexec_fn, close_fds,
1027 pass_fds, cwd, env,
1028 startupinfo, creationflags, shell,
1029 p2cread, p2cwrite,
1030 c2pread, c2pwrite,
1031 errread, errwrite,
1032 restore_signals,
1033 gid, gids, uid, umask,
1034 start_new_session, process_group)
1035 except:
1036 # Cleanup if the child failed starting.
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:1955, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group)
1954 if err_filename is not None:
-> 1955 raise child_exception_type(errno_num, err_msg, err_filename)
1956 else:
FileNotFoundError: [Errno 2] No such file or directory: 'latex'
The above exception was the direct cause of the following exception:
RuntimeError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backend_bases.py:2157, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
2154 # we do this instead of `self.figure.draw_without_rendering`
2155 # so that we can inject the orientation
2156 with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2157 self.figure.draw(renderer)
2158 if bbox_inches:
2159 if bbox_inches == "tight":
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:94, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
92 @wraps(draw)
93 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 94 result = draw(artist, renderer, *args, **kwargs)
95 if renderer._rasterizing:
96 renderer.stop_rasterizing()
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/figure.py:3264, in Figure.draw(self, renderer)
3261 # ValueError can occur when resizing a window.
3263 self.patch.draw(renderer)
-> 3264 mimage._draw_list_compositing_images(
3265 renderer, self, artists, self.suppressComposite)
3267 renderer.close_group('figure')
3268 finally:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/image.py:134, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
132 if not_composite or not has_images:
133 for a in artists:
--> 134 a.draw(renderer)
135 else:
136 # Composite any adjacent images together
137 image_group = []
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axes/_base.py:3226, in _AxesBase.draw(self, renderer)
3223 if artists_rasterized:
3224 _draw_rasterized(self.get_figure(root=True), artists_rasterized, renderer)
-> 3226 mimage._draw_list_compositing_images(
3227 renderer, self, artists, self.get_figure(root=True).suppressComposite)
3229 renderer.close_group('axes')
3230 self.stale = False
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/image.py:134, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
132 if not_composite or not has_images:
133 for a in artists:
--> 134 a.draw(renderer)
135 else:
136 # Composite any adjacent images together
137 image_group = []
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1405, in Axis.draw(self, renderer)
1402 renderer.open_group(__name__, gid=self.get_gid())
1404 ticks_to_draw = self._update_ticks()
-> 1405 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
1407 for tick in ticks_to_draw:
1408 tick.draw(renderer)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1332, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
1330 if renderer is None:
1331 renderer = self.get_figure(root=True)._get_renderer()
-> 1332 return ([tick.label1.get_window_extent(renderer)
1333 for tick in ticks if tick.label1.get_visible()],
1334 [tick.label2.get_window_extent(renderer)
1335 for tick in ticks if tick.label2.get_visible()])
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1332, in <listcomp>(.0)
1330 if renderer is None:
1331 renderer = self.get_figure(root=True)._get_renderer()
-> 1332 return ([tick.label1.get_window_extent(renderer)
1333 for tick in ticks if tick.label1.get_visible()],
1334 [tick.label2.get_window_extent(renderer)
1335 for tick in ticks if tick.label2.get_visible()])
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:969, in Text.get_window_extent(self, renderer, dpi)
964 raise RuntimeError(
965 "Cannot get window extent of text w/o renderer. You likely "
966 "want to call 'figure.draw_without_rendering()' first.")
968 with cbook._setattr_cm(fig, dpi=dpi):
--> 969 bbox, info, descent = self._get_layout(self._renderer)
970 x, y = self.get_unitless_position()
971 x, y = self.get_transform().transform((x, y))
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:373, in Text._get_layout(self, renderer)
370 ys = []
372 # Full vertical extent of font, including ascenders and descenders:
--> 373 _, lp_h, lp_d = _get_text_metrics_with_cache(
374 renderer, "lp", self._fontproperties,
375 ismath="TeX" if self.get_usetex() else False,
376 dpi=self.get_figure(root=True).dpi)
377 min_dy = (lp_h - lp_d) * self._linespacing
379 for i, line in enumerate(lines):
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:69, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
66 """Call ``renderer.get_text_width_height_descent``, caching the results."""
67 # Cached based on a copy of fontprop so that later in-place mutations of
68 # the passed-in argument do not mess up the cache.
---> 69 return _get_text_metrics_with_cache_impl(
70 weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:77, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
73 @functools.lru_cache(4096)
74 def _get_text_metrics_with_cache_impl(
75 renderer_ref, text, fontprop, ismath, dpi):
76 # dpi is unused, but participates in cache invalidation (via the renderer).
---> 77 return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backends/backend_agg.py:211, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
209 _api.check_in_list(["TeX", True, False], ismath=ismath)
210 if ismath == "TeX":
--> 211 return super().get_text_width_height_descent(s, prop, ismath)
213 if ismath:
214 ox, oy, width, height, descent, font_image = \
215 self.mathtext_parser.parse(s, self.dpi, prop)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backend_bases.py:566, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
562 fontsize = prop.get_size_in_points()
564 if ismath == 'TeX':
565 # todo: handle properties
--> 566 return self.get_texmanager().get_text_width_height_descent(
567 s, fontsize, renderer=self)
569 dpi = self.points_to_pixels(72)
570 if ismath:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:364, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
362 if tex.strip() == '':
363 return 0, 0, 0
--> 364 dvifile = cls.make_dvi(tex, fontsize)
365 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
366 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:293, in TexManager.make_dvi(cls, tex, fontsize)
290 with TemporaryDirectory(dir=dvifile.parent) as tmpdir:
291 Path(tmpdir, "file.tex").write_text(
292 cls._get_tex_source(tex, fontsize), encoding='utf-8')
--> 293 cls._run_checked_subprocess(
294 ["latex", "-interaction=nonstopmode", "-halt-on-error",
295 "-no-shell-escape", "file.tex"], tex, cwd=tmpdir)
296 Path(tmpdir, "file.dvi").replace(dvifile)
297 # Also move the tex source to the main cache directory, but
298 # only for backcompat.
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:254, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
250 report = subprocess.check_output(
251 command, cwd=cwd if cwd is not None else cls._texcache,
252 stderr=subprocess.STDOUT)
253 except FileNotFoundError as exc:
--> 254 raise RuntimeError(
255 f'Failed to process string with tex because {command[0]} '
256 'could not be found') from exc
257 except subprocess.CalledProcessError as exc:
258 raise RuntimeError(
259 '{prog} was not able to process the following string:\n'
260 '{tex!r}\n\n'
(...) 267 exc=exc.output.decode('utf-8', 'backslashreplace'))
268 ) from None
RuntimeError: Failed to process string with tex because latex could not be found
<Figure size 640x480 with 1 Axes>
Sestavljeno Simpsonovo pravilo#
Interval \([a, b]\) razdelimo na sodo število \(n\) podintervalov enake širine \(h=(b - a)/n\), s čimer so definirana vozlišča \(x_i=a+i\,h\) za \(i=0,1,\dots,n\). V tem primeru zapišemo sestavljeno Simpsonovo pravilo:
kjer je \(\eta\) neznana vrednost na intervalu \([a, b]\). Napaka je četrtega reda \(\mathcal{O}(h^4)\).
Numerična implementacija:
def simpsonovo_sest(y, h):
"""
Sestavljeno Simpsonovo pravilo integriranja.
:param y: funkcijske vrednosti
:param h: korak integriranja
"""
return h/3 * (y[0] + 4*np.sum(y[1:-1:2]) + 2*np.sum(y[2:-1:2]) + y[-1])
I_Simps_sest = simpsonovo_sest(y5v, h=h5v)
I_Simps_sest
Pripravimo sliko:
def fig_Simpsonovo_sest():
y_interpolate = interpolate.lagrange(x5v, y5v)
plt.fill_between(xg, y_interpolate(xg), alpha=0.25, facecolor='r')
plt.vlines(x5v, 0, y5v, color='r', linestyles='dashed', lw=1)
plt.annotate('$I_{\\textrm{Simpsonovo sestavljeno}}$', (1.2, 0.5), fontsize=22)
plt.annotate('Napaka', fontsize=20, xy=(1.70, 1.68), xytext=(1.4, 1.8),
arrowprops=dict(facecolor='gray', shrink=0.05))
plt.plot(xg, yg, lw=3, alpha=0.5, label='$x\\,\\sin(x)$')
plt.plot(x5v, y5v, 'o', alpha=0.5, label=f'$h={h5v}$')
plt.legend(loc=(1.01, 0))
plt.ylim(0, 2)
plt.show()
Prikažemo:
fig_Simpsonovo_sest()
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:250, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
249 try:
--> 250 report = subprocess.check_output(
251 command, cwd=cwd if cwd is not None else cls._texcache,
252 stderr=subprocess.STDOUT)
253 except FileNotFoundError as exc:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:466, in check_output(timeout, *popenargs, **kwargs)
464 kwargs['input'] = empty
--> 466 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
467 **kwargs).stdout
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:548, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
546 kwargs['stderr'] = PIPE
--> 548 with Popen(*popenargs, **kwargs) as process:
549 try:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:1026, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize, process_group)
1023 self.stderr = io.TextIOWrapper(self.stderr,
1024 encoding=encoding, errors=errors)
-> 1026 self._execute_child(args, executable, preexec_fn, close_fds,
1027 pass_fds, cwd, env,
1028 startupinfo, creationflags, shell,
1029 p2cread, p2cwrite,
1030 c2pread, c2pwrite,
1031 errread, errwrite,
1032 restore_signals,
1033 gid, gids, uid, umask,
1034 start_new_session, process_group)
1035 except:
1036 # Cleanup if the child failed starting.
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:1955, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group)
1954 if err_filename is not None:
-> 1955 raise child_exception_type(errno_num, err_msg, err_filename)
1956 else:
FileNotFoundError: [Errno 2] No such file or directory: 'latex'
The above exception was the direct cause of the following exception:
RuntimeError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backend_bases.py:2157, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
2154 # we do this instead of `self.figure.draw_without_rendering`
2155 # so that we can inject the orientation
2156 with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2157 self.figure.draw(renderer)
2158 if bbox_inches:
2159 if bbox_inches == "tight":
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:94, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
92 @wraps(draw)
93 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 94 result = draw(artist, renderer, *args, **kwargs)
95 if renderer._rasterizing:
96 renderer.stop_rasterizing()
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/figure.py:3264, in Figure.draw(self, renderer)
3261 # ValueError can occur when resizing a window.
3263 self.patch.draw(renderer)
-> 3264 mimage._draw_list_compositing_images(
3265 renderer, self, artists, self.suppressComposite)
3267 renderer.close_group('figure')
3268 finally:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/image.py:134, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
132 if not_composite or not has_images:
133 for a in artists:
--> 134 a.draw(renderer)
135 else:
136 # Composite any adjacent images together
137 image_group = []
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axes/_base.py:3226, in _AxesBase.draw(self, renderer)
3223 if artists_rasterized:
3224 _draw_rasterized(self.get_figure(root=True), artists_rasterized, renderer)
-> 3226 mimage._draw_list_compositing_images(
3227 renderer, self, artists, self.get_figure(root=True).suppressComposite)
3229 renderer.close_group('axes')
3230 self.stale = False
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/image.py:134, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
132 if not_composite or not has_images:
133 for a in artists:
--> 134 a.draw(renderer)
135 else:
136 # Composite any adjacent images together
137 image_group = []
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1405, in Axis.draw(self, renderer)
1402 renderer.open_group(__name__, gid=self.get_gid())
1404 ticks_to_draw = self._update_ticks()
-> 1405 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
1407 for tick in ticks_to_draw:
1408 tick.draw(renderer)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1332, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
1330 if renderer is None:
1331 renderer = self.get_figure(root=True)._get_renderer()
-> 1332 return ([tick.label1.get_window_extent(renderer)
1333 for tick in ticks if tick.label1.get_visible()],
1334 [tick.label2.get_window_extent(renderer)
1335 for tick in ticks if tick.label2.get_visible()])
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1332, in <listcomp>(.0)
1330 if renderer is None:
1331 renderer = self.get_figure(root=True)._get_renderer()
-> 1332 return ([tick.label1.get_window_extent(renderer)
1333 for tick in ticks if tick.label1.get_visible()],
1334 [tick.label2.get_window_extent(renderer)
1335 for tick in ticks if tick.label2.get_visible()])
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:969, in Text.get_window_extent(self, renderer, dpi)
964 raise RuntimeError(
965 "Cannot get window extent of text w/o renderer. You likely "
966 "want to call 'figure.draw_without_rendering()' first.")
968 with cbook._setattr_cm(fig, dpi=dpi):
--> 969 bbox, info, descent = self._get_layout(self._renderer)
970 x, y = self.get_unitless_position()
971 x, y = self.get_transform().transform((x, y))
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:373, in Text._get_layout(self, renderer)
370 ys = []
372 # Full vertical extent of font, including ascenders and descenders:
--> 373 _, lp_h, lp_d = _get_text_metrics_with_cache(
374 renderer, "lp", self._fontproperties,
375 ismath="TeX" if self.get_usetex() else False,
376 dpi=self.get_figure(root=True).dpi)
377 min_dy = (lp_h - lp_d) * self._linespacing
379 for i, line in enumerate(lines):
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:69, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
66 """Call ``renderer.get_text_width_height_descent``, caching the results."""
67 # Cached based on a copy of fontprop so that later in-place mutations of
68 # the passed-in argument do not mess up the cache.
---> 69 return _get_text_metrics_with_cache_impl(
70 weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:77, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
73 @functools.lru_cache(4096)
74 def _get_text_metrics_with_cache_impl(
75 renderer_ref, text, fontprop, ismath, dpi):
76 # dpi is unused, but participates in cache invalidation (via the renderer).
---> 77 return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backends/backend_agg.py:211, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
209 _api.check_in_list(["TeX", True, False], ismath=ismath)
210 if ismath == "TeX":
--> 211 return super().get_text_width_height_descent(s, prop, ismath)
213 if ismath:
214 ox, oy, width, height, descent, font_image = \
215 self.mathtext_parser.parse(s, self.dpi, prop)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backend_bases.py:566, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
562 fontsize = prop.get_size_in_points()
564 if ismath == 'TeX':
565 # todo: handle properties
--> 566 return self.get_texmanager().get_text_width_height_descent(
567 s, fontsize, renderer=self)
569 dpi = self.points_to_pixels(72)
570 if ismath:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:364, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
362 if tex.strip() == '':
363 return 0, 0, 0
--> 364 dvifile = cls.make_dvi(tex, fontsize)
365 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
366 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:293, in TexManager.make_dvi(cls, tex, fontsize)
290 with TemporaryDirectory(dir=dvifile.parent) as tmpdir:
291 Path(tmpdir, "file.tex").write_text(
292 cls._get_tex_source(tex, fontsize), encoding='utf-8')
--> 293 cls._run_checked_subprocess(
294 ["latex", "-interaction=nonstopmode", "-halt-on-error",
295 "-no-shell-escape", "file.tex"], tex, cwd=tmpdir)
296 Path(tmpdir, "file.dvi").replace(dvifile)
297 # Also move the tex source to the main cache directory, but
298 # only for backcompat.
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:254, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
250 report = subprocess.check_output(
251 command, cwd=cwd if cwd is not None else cls._texcache,
252 stderr=subprocess.STDOUT)
253 except FileNotFoundError as exc:
--> 254 raise RuntimeError(
255 f'Failed to process string with tex because {command[0]} '
256 'could not be found') from exc
257 except subprocess.CalledProcessError as exc:
258 raise RuntimeError(
259 '{prog} was not able to process the following string:\n'
260 '{tex!r}\n\n'
(...) 267 exc=exc.output.decode('utf-8', 'backslashreplace'))
268 ) from None
RuntimeError: Failed to process string with tex because latex could not be found
<Figure size 640x480 with 1 Axes>
Boljša ocena integrala#
Napaka sestavljene Simpsonove metode je definirana z:
kjer je \(\eta\) neznana vrednost na intervalu \([a, b]\).
Izboljšano oceno integrala določimo na podoben način kakor pri sestavljeni trapezni metodi; integral \(I\) ocenjujemo pri dveh različnih korakih \(h\) in \(2\,h\), velja natančno:
kjer je \(I_h\) približek integrala s korakom \(h\) in \(E_h\) ocena napake pri koraku \(h\); analogno velja za \(I_{2h}\) in \(E_{2h}\).
Če predpostavimo, da je \(f^{(4)}\left (\eta \right )\) v obeh primerih enak, lahko določimo razliko \(I_{2h}-I_{h} = E_{h}-E_{2h}\).
Naprej zapišemo:
Ob predpostavki, da je \(f^{(4)}\left (\eta \right )\) pri koraku \(h\) in \(2h\) enak (\(\eta\) je pri koraku \(h\) in \(2h\) dejansko različen), zapišemo:
Sledi:
Sedaj lahko ocenimo napako pri koraku \(h\):
Na podlagi ocene napake lahko izračunamo boljši približek \(I_{h}^*\):
ali
Numerični zgled#
Predhodno smo s Simpsonovim pravilom že izračunali integral pri koraku \(h=0,5\) in pri koraku \(h=0,25\), rezultata sta bila:
[I_Simps, I_Simps_sest]
S pomočjo zgornje formule izračunamo boljši približek:
I_Simps_boljši = 16/15*I_Simps_sest - 1/15*I_Simps
print(f'Točen rezultat: {I_točno}\nBoljši približek: {I_Simps_boljši}')
Točen rezultat: 1.4404224209802097
Boljši približek: 1.4404218714139077
Pridobimo boljši numerični približek, izgubimo pa oceno napake!
Simpsonova metoda v scipy.integrate.simps#
V scipy je implementirano sestavljeno Simpsonovo pravilo v scipy.integrate.simpson() (dokumentacija):
simpson(y, x=None, dx=1, axis=-1, even='avg')
kjer so parametri:
ytabela funkcijskih vrednosti, ki jih integriramo,xvozlišča, gre za opcijski parameter, če jex=None, se predpostavi ekvidistantne podintervale širinedx,dxširina ekvidistantnih podintervalov oz korak integriranja,axisos integriranja (pomembno v primeru večdimenzijskega numeričnega polja)evenje lahko {'avg','first','last'} in definira način integriranja v primeru lihega števila podintervalov.
Poglejmo si primer, najprej uvozimo funkcijo simpson:
from scipy.integrate import simpson
#%%timeit
simpson(y5v, dx=h5v)
Rombergova metoda#
Rombergova metoda temelji na Richardsonovi ekstrapolaciji. Predpostavimo, da integral \(\int_a^b f(x)\textrm{d}x\) integriramo na intervalu \([a,b]\), ki ga razdelimo na \(2^{n-1}\) podintervalov (\(n=1,2,4,8, \dots\)).
Rezultat trapeznega pravila pri \(n=1\) označimo z \(R_{\underbrace{1}_{n},\underbrace{1}_{j}}\), pri čemer \(j\) označuje natančnost pridobljenega rezultata \(\mathcal{O}(h^{2j})\).
Če uporabimo trapezno integracijsko pravilo pri \(n=1,2,4 \dots\) podintervalih, izračunamo:
\(R_{1,1}\), korak \(h_1=h\), red natančnosti \(\mathcal{O}(h_1^2)\),
\(R_{2,1}\), korak \(h_2=h/2\), red natančnosti \(\mathcal{O}(h_2^2)\),
\(R_{3,1}\), korak \(h_3=h/4\), red natančnosti \(\mathcal{O}(h_3^2)\),
\(R_{4,1}\), korak \(h_4=h/8\), red natančnosti \(\mathcal{O}(h_4^2)\),
\(\dots\)
\(R_{n,1}\), korak \(h_4=h/(2^{n-1})\), red natančnosti \(\mathcal{O}(h_n^2)\).
Na podlagi Richardsonove ekstrapolacije izračunamo boljši približek
\(R_{2,2} = R_{2,1} + \frac{1}{3}\left(R_{2,1}-R_{1,1}\right)\), korak \(h_2=h/2\), red natančnosti \(\mathcal{O}(h_2^4)\),
\(R_{3,2} = R_{3,1} + \frac{1}{3}\left(R_{3,1}-R_{2,1}\right)\), korak \(h_3=h/4\), red natančnosti \(\mathcal{O}(h_3^4)\),
\(\dots\)
\(R_{n,2} = R_{n,1} + \frac{1}{3}\left(R_{n,1}-R_{n-1,1}\right)\), korak \(h_n=h/(2^{n-1})\), red natančnosti \(\mathcal{O}(h_n^4)\).
Nato nadaljujemo z Richardsonovo ekstrapolacijo:
\(R_{3,3} = R_{3,2} + \frac{1}{15}\left(R_{3,2}-R_{2,2}\right)\), korak \(h_3=h/4\), red natančnosti \(\mathcal{O}(h_3^6)\),
\(\dots\)
\(R_{n,3} = R_{n,2} + \frac{1}{15}\left(R_{n,2}-R_{n-1,2}\right)\), korak \(h_n=h/(2^{n-1})\), red natančnosti \(\mathcal{O}(h_n^6)\).
Richardsonovo extrapolacijo lahko posplošimo:
\(R_{n,j} = R_{n,j-1} + \frac{1}{4^{j-1}-1}\left(R_{n,j-1}-R_{n-1,j-1}\right)\), korak \(h_n=h/(2^{n-1})\), red natančnosti \(\mathcal{O}(h_n^{2j})\)
Pri tem je boljši približek \(R_{2,2}\) pri koraku \(h/2\) enak rezultatu, ki ga dobimo po Simpsonovi metodi pri koraku \(h/2\). Podobno je boljši približek \(R_{3,2}\) pri koraku \(h/4\) enak numeričnemu integralu Simpsonove metode pri koraku \(h/4\). In je dalje \(R_{3,3}\) enak popravljenemu približku Simpsonove metode pri koraku \(h/4\).
Pripravimo numerične podatke:
x9v, h9v = np.linspace(1, 2, 9, retstep=True) # korak h9v = 0.125 (9 vozlišč)
y9v = x9v * np.sin(x9v)
Poglejmo si primer od zgoraj. Najprej s sestavljeno trapezno metodo izračunamo integral pri različnih korakih (drugi red napake):
## O(h^2)
R1_1 = trapezno_sest(y9v[::8], 8*h9v) # h=1.0
R2_1 = trapezno_sest(y9v[::4], 4*h9v) # h=0.5
R3_1 = trapezno_sest(y9v[::2], 2*h9v) # h=0.25
R4_1 = trapezno_sest(y9v, h9v) # h=0.125
[R1_1, R2_1, R3_1, R4_1]
Nato izračunamo boljše približke (dobimo četrti red napake):
## O(h^4)
R2_2 = R2_1 + 1/3 * (R2_1 - R1_1)
R3_2 = R3_1 + 1/3 * (R3_1 - R2_1)
R4_2 = R4_1 + 1/3 * (R4_1 - R3_1)
[R2_2, R3_2, R4_2]
Rezultati predstavljajo rezultat Simpsonove metode pri koraku \(h=0,5\), \(h=0,25\) in \(h=0.125\):
[simpsonovo_sest(y9v[::4], 4*h9v), simpsonovo_sest(y9v[::2], 2*h9v), simpsonovo_sest(y9v, h9v)]
Ponovno izračunamo boljše približke (dobimo šesti red napake):
## O(h6)
R3_3 = R3_2 + 1/15 * (R3_2 - R2_2)
R4_3 = R4_2 + 1/15 * (R4_2 - R3_2)
[R3_3, R4_3]
Rezultat predstavlja boljši rezultat Simpsonove pri koraku \(h=0,25\) in \(h=0.125\):
a4h, a2h, ah = [simpsonovo_sest(y9v[::4], 4*h9v), simpsonovo_sest(y9v[::2], 2*h9v), simpsonovo_sest(y9v, h9v)]
[16/15*a2h-1/15*a4h, 16/15*ah-1/15*a2h]
Ponovno izračunamo boljše približke (dobimo osmi red napake):
## O(h8)
R4_4 = R4_3 + 1/63 * (R4_3 - R3_3)
R4_4
Rombergova metoda nam torej ponuja visoko natančnost rezultata za relativno majhno numerično ceno. Napako pa ocenimo:
Rombergova metoda v scipy.integrate.romb#
V scipy je implementirana Rombergova metoda v scipy.integrate.romb() (dokumentacija):
romb(y, dx=1.0, axis=-1, show=False)
kjer so parametri:
ytabela funkcijskih vrednosti, ki jih integriramo,dxširina ekvidistantnih podintervalov oz korak integriranja,axisor integriranja (pomembno v primeru večdimenzijskega numeričnega polja),showče jeTrueprikaže elemente Richardsonove ekstrapolacije.
Poglejmo si primer od zgoraj:
from scipy.integrate import romb
y9v
array([0.84147098, 1.01505104, 1.18623077, 1.34872795, 1.49624248,
1.62261343, 1.72197541, 1.78891084, 1.81859485])
romb(y9v, dx=h9v, show=True)
Richardson Extrapolation Table for Romberg Integration
======================================================
1.33003
1.41314 1.44084
1.43362 1.44045 1.44042
1.43872 1.44042 1.44042 1.44042
======================================================
Gaussov integracijski pristop#
Newton-Cotesov pristop temelji na polinomu \(n\)-te stopnje in napaka je \(n+1\) stopnje. To pomeni, da integracija daje točen rezultat, če je integrirana funkcija polinom stopnje \(n\) ali manj.
Gaussov integracijski pristop je v principu drugačen: cilj je integral funkcije \(f(x)\) nadomestiti z uteženo vsoto vrednosti funkcije pri diskretnih vrednostih \(f(x_i)\):
Pri tem je neznana utež \(A_i\) in tudi lega vozlišča \(x_i\). Za stopnje polinoma \(n\) bomo potrebovali tudi več točk \((x_i, f(x_i))\).
V nadaljevanju bomo spoznali, da lahko zelo učinkovito izračunamo numerično točen integral. Prednost Gaussove integracije je tudi, da lahko izračuna integral funkcij s singularnostmi (npr: \(\int_0^1\sin(x)/\sqrt{(x)}\,dx\)).
Gaussova kvadratura z enim vozliščem#
Predpostavimo, da želimo integrirati polinom stopnje \(n=1\) (linearna funkcija):
Izračunajmo:
Po drugi strani pa želimo integral izračunati glede na ustrezno uteženo \(A_0\) vrednost funkcije \(f(x_0)\) v neznanem vozlišču \(x_0\) (samo eno vozlišče!):
Z enačenjem zgornjih izrazov izpeljemo:
\(a_0\) in \(a_1\) sta koeficienta linearne funkcije, ki lahko zavzame poljubne vrednosti, zato velja:
Gre za sistem linearnih enačb z rešitvijo:
Če je integrirana funkcija linearna, bomo samo na podlagi vrednosti v eni točki izračunali pravo vrednost!
Da je Gaussov integracijski pristop neodvisen od mej integriranja \(x_L\), \(x_D\), pa uvedemo standardne meje.
Standardne meje: \(x_L=-1\) in \(x_D=1\)#
Zaradi splošnosti meje \(x\in[x_L, x_D]\) transformiramo v \(\xi\in[-1, +1]\) s pomočjo:
in
Velja:
kjer je:
V primeru standardnih mej, je pri eni Gaussovi točki utež \(A_0=2\) in \(x_0=0\) vrednost, pri kateri moramo izračunati funkcijo \(f(x_0)\).
Strojno izpeljevanje uteži in Gaussove točke#
Definirajmo simbole in nastavimo enačbo:
a_0, a_1, x, x_L, x_D, A_0, x_0 = sym.symbols('a_0, a_1, x, x_L, x_D, A_0, x_0') # simboli
P1 = a_0 + a_1*x # linearni polinom
eq = sym.Eq(P1.integrate((x, x_L, x_D)).expand(), A_0*P1.subs(x, x_0)) # teoretični integral = ocen z utežmi
eq
Pripravimo dve enačbi (za prvo predpostavimo \(a_0=0, a_1=1\), za drugo predpostavimo \(a_0=1, a_1=0\)) ter rešimo sistem za A_0 in x_0:
sym.solve([eq.subs(a_0, 0).subs(a_1, 1), eq.subs(a_1, 0).subs(a_0, 1)], [A_0, x_0])
Za dodatno razlago priporočam video posnetek.
Gaussova integracijska metoda z več vozlišči#
Izpeljati želimo Gaussovo integracijsko metodo, ki bo upoštevala na intervalu \([a,b]\) \(v\) vozlišč in bo točno izračunala integral polinomov do stopnje \(n=2v-1\). Veljati mora:
Pri izpeljavi se bomo omejili na standardne meje \(x_L=-1\), \(x_D=1\),
kjer je polinom stopnje \(n=2v-1\) definiran kot:
Z dvema Gaussovima točkama/vozliščema točno izračunamo integral polinoma do tretjega reda, s tremi Gaussovimi vozlišči pa točno izračunamo integral polinoma do petega reda!
Strojno izpeljevanje#
Pripravimo si najprej simbolni zapis polinoma in ustreznih spremenljivk:
def P_etc(n=1, a='a', x='x'): # n je stopnja polinoma
ai = sym.symbols(f'{a}:{n+1}') # seznam a_i
x = sym.symbols(x) # spremenljivka x
return ai, x, sum([ai[i]*x**i for i in range(n+1)])
Sedaj pa poiščimo uteži \(A_i\) in vozlišča \(x_i\) za primer dveh Gaussovih vozlišč; polinom je torej tretje stopnje.
v = 2 # število vozlišč
ai, x, P = P_etc(n=2*v-1)
xi = sym.symbols(f'x:{v}') # seznam x_i
Ai = sym.symbols(f'A:{v}') # seznam w_i
print(f'Vozlišča: {xi}\nUteži: {Ai}')
Vozlišča: (x0, x1)
Uteži: (A0, A1)
Polinom:
P
Podobno kakor zgoraj za eno vozlišče, tukaj definirajmo enačbe:
eqs = [sym.Eq(P.integrate((x, -1, 1)).coeff(a_),\
sum([Ai[i]*P.subs(x, xi[i]) \
for i in range(v)]).expand().coeff(a_)) \
for a_ in ai]
eqs
Rešimo jih za neznane \(x_i\) in \(w_i\):
sol = sym.solve(eqs, sym.flatten((xi, Ai)))
sol
Določili smo seznam dveh (enakih) rešitev.
Najprej sta definirani vozlišči: \(x_0=-\sqrt{3}/3\) in \(x_1=\sqrt{3}/3\), katerima pripadata uteži \(A_0=A_1=1\).
Koda zgoraj je izpeljana v splošnem - število vozlišč v lahko povečate ter izračunate vozlišča ter pripadajoče uteži.
Spodaj je podana tabela vozlišč in uteži za eno, dve in tri vozlišča (za meje \(a=-1\), \(b=1\)):
Število točk 1:
\(i\) |
Vozlišče \(x_i\) |
Utež \(A_i\) |
|---|---|---|
0 |
0 |
2 |
Število točk 2:
\(i\) |
Vozlišče \(x_i\) |
Utež \(A_i\) |
|---|---|---|
0 |
\(-\frac{\sqrt{3}}{3}\) |
1 |
1 |
\(+\frac{\sqrt{3}}{3}\) |
1 |
Število točk 3:
\(i\) |
Vozlišče \(x_i\) |
Utež \(A_i\) |
|---|---|---|
0 |
\(-\frac{\sqrt{15}}{5}\) |
\(\frac{5}{9}\) |
1 |
\(0\) |
\(\frac{8}{9}\) |
2 |
\(\frac{\sqrt{15}}{5}\) |
\(\frac{5}{9}\) |
Za več vozlišč in tudi oceno napake, glejte Mathworld Legendre-Gauss Quadrature.
Za primer treh Gaussovih točk numerični integral izračunamo (standardne meje):
Numerična implementacija#
Numerična implementacija (vključno s transformacijo mej) za eno, dve ali tri vozlišča:
def Gaussova(fun, a, b, vozlišč=1):
"""
Gaussova integracijska metoda.
:param fun: objekt funkcije, ki jo integriramo
:param a: spodnja meja
:param b: zgornja meja
:param vozlišča: število vozlišč (1, 2 ali 3)
"""
def g(xi): # funkcija za transformacijo mej
return (b-a)/2 * fun((b+a +xi * (b-a))/2)
if vozlišč == 1:
return 2*g(0.)
elif vozlišč == 2:
return 1. * g(-np.sqrt(3)/3) + 1. * g(np.sqrt(3)/3)
elif vozlišč == 3:
return 5/9 * g(-np.sqrt(15)/5) +8/9 * g(0.) + 5/9 * g(np.sqrt(15)/5)
Poglejmo si zgled. Najprej definirajmo funkcijo, ki jo želimo integrirati:
def f(x):
return x*np.sin(x)
Sedaj pa funkcijo (v konkretnem primeru f) in ne vrednosti (npr. f(0.)) posredujemo funkciji Gaussova. Najprej za eno vozlišče, nato dve in tri:
Gaussova(fun=f, a=1., b=2., vozlišč=1)
Gaussova(fun=f, a=1., b=2., vozlišč=2)
Gaussova(fun=f, a=1., b=2., vozlišč=3)
scipy.integrate.fixed_quad#
Znotraj scipy je Gaussova integracijska metoda implementirana v okviru funkcije scipy.integrate.fixed_quad() (dokumentacija):
fixed_quad(func, a, b, args=(), n=5)
kjer so parametri:
funcje ime funkcije, ki jo kličemo,aje spodnja meja,bje zgornja meja,argsje terka morebitnih dodatnih argumentov funkcijefunc,nje število vozlišč Gaussove integracije, privzeton=5.
Funkcija vrne terko z rezultatom integriranja val in vrednost None: (val, None)
Poglejmo primer od zgoraj:
from scipy.integrate import fixed_quad
fixed_quad(f, a=1, b=2, n=3)[0]
Rezultat je enak predhodnemu:
Gaussova(fun=f, a=1., b=2., vozlišč=3)
scipy.integrate#
scipy.integrate je močno orodje za numerično integriranje (glejte dokumentacijo). V nadaljevanju si bomo pogledali nekatere funkcije.
Intergracijske funkcije, ki zahtevajo definicijsko funkcijo:#
quad(func, a, b[, args, full_output, ...])izračuna določeni integralfunc(x)v mejah [a,b],dblquad(func, a, b, gfun, hfun[, args, ...])izračuna določeni integralfunc(x,y),tplquad(func, a, b, gfun, hfun, qfun, rfun)izračuna določeni integralfunc(x,y,z),nquad(func, ranges[, args, opts, full_output])izračuna določeni integral \(n\) dimenzijske funkcijefunc( ...),romberg(function, a, b[, args, tol, rtol, ...])integracija Romberg za funkcijofunction,
scipy.integrate.quad#
Poglejmo si zelo uporabno funkcijo za integriranje, scipy.integrate.quad() (dokumentacija):
quad(func, a, b, args=(), full_output=0, epsabs=1.49e-08, epsrel=1.49e-08, limit=50,
points=None, weight=None, wvar=None, wopts=None, maxp1=50, limlst=50)
Izbrani parametri so:
funcPython funkcija, ki jo integriramo,aspodnja meja integriranja (lahko se uporabinp.infza mejo v neskončnosti),bzgornja meja integriranja (lahko se uporabinp.infza mejo v neskončnosti),full_outputza prikaz vseh rezultatov, privzeto 0,epsabsdovoljena absolutna napaka,epsreldovoljena relativna napaka.
Poglejmo primer od zgoraj:
from scipy import integrate
integrate.quad(f, a=1, b=2)
scipy.integrate.dblquad#
Gre za podobno funkcijo kot quad, vendar za integriranje po dveh spremenljivkah (dokumentacija).
Funkcija scipy.integrate.dblquad() izračuna dvojni integral func(y, x) v mejah od x = [a, b] in y = [gfun(x), hfun(x)].
dblquad(func, a, b, gfun, hfun, args=(), epsabs=1.49e-08, epsrel=1.49e-08)
Izbrani parametri so:
funcje Python funkcija, ki jo integriramo,aje spodnja meja integriranjax(lahko se uporabinp.infza mejo v neskončnosti),bje zgornja meja integriranjax(lahko se uporabinp.infza mejo v neskončnosti),gfunje Python funkcija, ki definira spodnjo mejoyv odvisnosti odx,hfunje Python funkcija, ki definira zgornjo mejoyv odvisnosti odx.
Poglejmo primer izračuna površine polkroga s polmerom 1:
Definirajmo ustrezne Python funkcije in izračunajmo rezultat:
def func(y, x): # integracijska funkcija je enostavna, konstanta = 1!
return 1.
def gfun(x): # spodnja meja = 0
return 0.
def hfun(x): # zgornja meja
return np.sqrt(1-x**2)
integrate.dblquad(func=func, a=-1, b=1, gfun=gfun, hfun=hfun)
Intergracijske funkcije, ki zahtevajo tabelo vrednosti:#
trapz(y[, x, dx, axis])sestavljeno trapezno pravilo,cumulative_trapezoid(y[, x, dx, axis, initial])kumulativni integral podintegralske funkcije (vrne rezultat v vsakem vozlišču),simps(y[, x, dx, axis, even])Simpsonova metoda,romb(y[, dx, axis, show])Rombergova metoda.
Tukaj si bomo na primeru ogledali funkcijo cumulative_trapezoid. Kot primer si, ko na maso \(m=1\) (enote izpustimo) deluje sila \(F=\sin(t)\). Iz 2. Newtonovega zakona sledi: \(F=m\,\ddot x\). Pospešek integriramo, da izračunamo hitrost; nato integriramo še enkrat za pomik. Definirajmo najprej funkcijo za pospešek:
def pospešek(t):
F = np.sin(t)
m = 1
return F/m
Zanima nas dogajanje v času 3 sekund:
t, h = np.linspace(0, 3, 100, retstep=True)
Izračunajmo tabelo pospeškov ter nato integrirajmo za hitrost (pri tem je pomembno, da definiramo začetno vrednost):
a = pospešek(t)
v = integrate.cumulative_trapezoid(y=a, dx=h, initial=0)
Hitrost sedaj še enkrat integrirajmo, da izračunamo pot:
s = integrate.cumulative_trapezoid(y=v, dx=h, initial=0)
Prikažimo rezultat:
plt.plot(t, a, label='Pospesek')
plt.plot(t, v, label='Hitrost')
plt.plot(t, s, label='Pot')
plt.xlabel('$t$ [s]')
plt.legend();
Error in callback <function _draw_all_if_interactive at 0x7f1ac5885c60> (for post_execute), with arguments args (),kwargs {}:
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:250, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
249 try:
--> 250 report = subprocess.check_output(
251 command, cwd=cwd if cwd is not None else cls._texcache,
252 stderr=subprocess.STDOUT)
253 except FileNotFoundError as exc:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:466, in check_output(timeout, *popenargs, **kwargs)
464 kwargs['input'] = empty
--> 466 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
467 **kwargs).stdout
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:548, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
546 kwargs['stderr'] = PIPE
--> 548 with Popen(*popenargs, **kwargs) as process:
549 try:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:1026, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize, process_group)
1023 self.stderr = io.TextIOWrapper(self.stderr,
1024 encoding=encoding, errors=errors)
-> 1026 self._execute_child(args, executable, preexec_fn, close_fds,
1027 pass_fds, cwd, env,
1028 startupinfo, creationflags, shell,
1029 p2cread, p2cwrite,
1030 c2pread, c2pwrite,
1031 errread, errwrite,
1032 restore_signals,
1033 gid, gids, uid, umask,
1034 start_new_session, process_group)
1035 except:
1036 # Cleanup if the child failed starting.
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:1955, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group)
1954 if err_filename is not None:
-> 1955 raise child_exception_type(errno_num, err_msg, err_filename)
1956 else:
FileNotFoundError: [Errno 2] No such file or directory: 'latex'
The above exception was the direct cause of the following exception:
RuntimeError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/pyplot.py:278, in _draw_all_if_interactive()
276 def _draw_all_if_interactive() -> None:
277 if matplotlib.is_interactive():
--> 278 draw_all()
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/_pylab_helpers.py:131, in Gcf.draw_all(cls, force)
129 for manager in cls.get_all_fig_managers():
130 if force or manager.canvas.figure.stale:
--> 131 manager.canvas.draw_idle()
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backend_bases.py:1893, in FigureCanvasBase.draw_idle(self, *args, **kwargs)
1891 if not self._is_idle_drawing:
1892 with self._idle_draw_cntx():
-> 1893 self.draw(*args, **kwargs)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backends/backend_agg.py:382, in FigureCanvasAgg.draw(self)
379 # Acquire a lock on the shared font cache.
380 with (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
381 else nullcontext()):
--> 382 self.figure.draw(self.renderer)
383 # A GUI class may be need to update a window using this draw, so
384 # don't forget to call the superclass.
385 super().draw()
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:94, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
92 @wraps(draw)
93 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 94 result = draw(artist, renderer, *args, **kwargs)
95 if renderer._rasterizing:
96 renderer.stop_rasterizing()
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/figure.py:3264, in Figure.draw(self, renderer)
3261 # ValueError can occur when resizing a window.
3263 self.patch.draw(renderer)
-> 3264 mimage._draw_list_compositing_images(
3265 renderer, self, artists, self.suppressComposite)
3267 renderer.close_group('figure')
3268 finally:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/image.py:134, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
132 if not_composite or not has_images:
133 for a in artists:
--> 134 a.draw(renderer)
135 else:
136 # Composite any adjacent images together
137 image_group = []
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axes/_base.py:3226, in _AxesBase.draw(self, renderer)
3223 if artists_rasterized:
3224 _draw_rasterized(self.get_figure(root=True), artists_rasterized, renderer)
-> 3226 mimage._draw_list_compositing_images(
3227 renderer, self, artists, self.get_figure(root=True).suppressComposite)
3229 renderer.close_group('axes')
3230 self.stale = False
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/image.py:134, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
132 if not_composite or not has_images:
133 for a in artists:
--> 134 a.draw(renderer)
135 else:
136 # Composite any adjacent images together
137 image_group = []
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1405, in Axis.draw(self, renderer)
1402 renderer.open_group(__name__, gid=self.get_gid())
1404 ticks_to_draw = self._update_ticks()
-> 1405 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
1407 for tick in ticks_to_draw:
1408 tick.draw(renderer)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1332, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
1330 if renderer is None:
1331 renderer = self.get_figure(root=True)._get_renderer()
-> 1332 return ([tick.label1.get_window_extent(renderer)
1333 for tick in ticks if tick.label1.get_visible()],
1334 [tick.label2.get_window_extent(renderer)
1335 for tick in ticks if tick.label2.get_visible()])
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1332, in <listcomp>(.0)
1330 if renderer is None:
1331 renderer = self.get_figure(root=True)._get_renderer()
-> 1332 return ([tick.label1.get_window_extent(renderer)
1333 for tick in ticks if tick.label1.get_visible()],
1334 [tick.label2.get_window_extent(renderer)
1335 for tick in ticks if tick.label2.get_visible()])
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:969, in Text.get_window_extent(self, renderer, dpi)
964 raise RuntimeError(
965 "Cannot get window extent of text w/o renderer. You likely "
966 "want to call 'figure.draw_without_rendering()' first.")
968 with cbook._setattr_cm(fig, dpi=dpi):
--> 969 bbox, info, descent = self._get_layout(self._renderer)
970 x, y = self.get_unitless_position()
971 x, y = self.get_transform().transform((x, y))
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:373, in Text._get_layout(self, renderer)
370 ys = []
372 # Full vertical extent of font, including ascenders and descenders:
--> 373 _, lp_h, lp_d = _get_text_metrics_with_cache(
374 renderer, "lp", self._fontproperties,
375 ismath="TeX" if self.get_usetex() else False,
376 dpi=self.get_figure(root=True).dpi)
377 min_dy = (lp_h - lp_d) * self._linespacing
379 for i, line in enumerate(lines):
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:69, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
66 """Call ``renderer.get_text_width_height_descent``, caching the results."""
67 # Cached based on a copy of fontprop so that later in-place mutations of
68 # the passed-in argument do not mess up the cache.
---> 69 return _get_text_metrics_with_cache_impl(
70 weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:77, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
73 @functools.lru_cache(4096)
74 def _get_text_metrics_with_cache_impl(
75 renderer_ref, text, fontprop, ismath, dpi):
76 # dpi is unused, but participates in cache invalidation (via the renderer).
---> 77 return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backends/backend_agg.py:211, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
209 _api.check_in_list(["TeX", True, False], ismath=ismath)
210 if ismath == "TeX":
--> 211 return super().get_text_width_height_descent(s, prop, ismath)
213 if ismath:
214 ox, oy, width, height, descent, font_image = \
215 self.mathtext_parser.parse(s, self.dpi, prop)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backend_bases.py:566, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
562 fontsize = prop.get_size_in_points()
564 if ismath == 'TeX':
565 # todo: handle properties
--> 566 return self.get_texmanager().get_text_width_height_descent(
567 s, fontsize, renderer=self)
569 dpi = self.points_to_pixels(72)
570 if ismath:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:364, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
362 if tex.strip() == '':
363 return 0, 0, 0
--> 364 dvifile = cls.make_dvi(tex, fontsize)
365 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
366 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:293, in TexManager.make_dvi(cls, tex, fontsize)
290 with TemporaryDirectory(dir=dvifile.parent) as tmpdir:
291 Path(tmpdir, "file.tex").write_text(
292 cls._get_tex_source(tex, fontsize), encoding='utf-8')
--> 293 cls._run_checked_subprocess(
294 ["latex", "-interaction=nonstopmode", "-halt-on-error",
295 "-no-shell-escape", "file.tex"], tex, cwd=tmpdir)
296 Path(tmpdir, "file.dvi").replace(dvifile)
297 # Also move the tex source to the main cache directory, but
298 # only for backcompat.
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:254, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
250 report = subprocess.check_output(
251 command, cwd=cwd if cwd is not None else cls._texcache,
252 stderr=subprocess.STDOUT)
253 except FileNotFoundError as exc:
--> 254 raise RuntimeError(
255 f'Failed to process string with tex because {command[0]} '
256 'could not be found') from exc
257 except subprocess.CalledProcessError as exc:
258 raise RuntimeError(
259 '{prog} was not able to process the following string:\n'
260 '{tex!r}\n\n'
(...) 267 exc=exc.output.decode('utf-8', 'backslashreplace'))
268 ) from None
RuntimeError: Failed to process string with tex because latex could not be found
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:250, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
249 try:
--> 250 report = subprocess.check_output(
251 command, cwd=cwd if cwd is not None else cls._texcache,
252 stderr=subprocess.STDOUT)
253 except FileNotFoundError as exc:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:466, in check_output(timeout, *popenargs, **kwargs)
464 kwargs['input'] = empty
--> 466 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
467 **kwargs).stdout
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:548, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
546 kwargs['stderr'] = PIPE
--> 548 with Popen(*popenargs, **kwargs) as process:
549 try:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:1026, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize, process_group)
1023 self.stderr = io.TextIOWrapper(self.stderr,
1024 encoding=encoding, errors=errors)
-> 1026 self._execute_child(args, executable, preexec_fn, close_fds,
1027 pass_fds, cwd, env,
1028 startupinfo, creationflags, shell,
1029 p2cread, p2cwrite,
1030 c2pread, c2pwrite,
1031 errread, errwrite,
1032 restore_signals,
1033 gid, gids, uid, umask,
1034 start_new_session, process_group)
1035 except:
1036 # Cleanup if the child failed starting.
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/subprocess.py:1955, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group)
1954 if err_filename is not None:
-> 1955 raise child_exception_type(errno_num, err_msg, err_filename)
1956 else:
FileNotFoundError: [Errno 2] No such file or directory: 'latex'
The above exception was the direct cause of the following exception:
RuntimeError Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backend_bases.py:2157, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
2154 # we do this instead of `self.figure.draw_without_rendering`
2155 # so that we can inject the orientation
2156 with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2157 self.figure.draw(renderer)
2158 if bbox_inches:
2159 if bbox_inches == "tight":
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:94, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
92 @wraps(draw)
93 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 94 result = draw(artist, renderer, *args, **kwargs)
95 if renderer._rasterizing:
96 renderer.stop_rasterizing()
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/figure.py:3264, in Figure.draw(self, renderer)
3261 # ValueError can occur when resizing a window.
3263 self.patch.draw(renderer)
-> 3264 mimage._draw_list_compositing_images(
3265 renderer, self, artists, self.suppressComposite)
3267 renderer.close_group('figure')
3268 finally:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/image.py:134, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
132 if not_composite or not has_images:
133 for a in artists:
--> 134 a.draw(renderer)
135 else:
136 # Composite any adjacent images together
137 image_group = []
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axes/_base.py:3226, in _AxesBase.draw(self, renderer)
3223 if artists_rasterized:
3224 _draw_rasterized(self.get_figure(root=True), artists_rasterized, renderer)
-> 3226 mimage._draw_list_compositing_images(
3227 renderer, self, artists, self.get_figure(root=True).suppressComposite)
3229 renderer.close_group('axes')
3230 self.stale = False
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/image.py:134, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
132 if not_composite or not has_images:
133 for a in artists:
--> 134 a.draw(renderer)
135 else:
136 # Composite any adjacent images together
137 image_group = []
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/artist.py:71, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
68 if artist.get_agg_filter() is not None:
69 renderer.start_filter()
---> 71 return draw(artist, renderer)
72 finally:
73 if artist.get_agg_filter() is not None:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1405, in Axis.draw(self, renderer)
1402 renderer.open_group(__name__, gid=self.get_gid())
1404 ticks_to_draw = self._update_ticks()
-> 1405 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
1407 for tick in ticks_to_draw:
1408 tick.draw(renderer)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1332, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
1330 if renderer is None:
1331 renderer = self.get_figure(root=True)._get_renderer()
-> 1332 return ([tick.label1.get_window_extent(renderer)
1333 for tick in ticks if tick.label1.get_visible()],
1334 [tick.label2.get_window_extent(renderer)
1335 for tick in ticks if tick.label2.get_visible()])
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/axis.py:1332, in <listcomp>(.0)
1330 if renderer is None:
1331 renderer = self.get_figure(root=True)._get_renderer()
-> 1332 return ([tick.label1.get_window_extent(renderer)
1333 for tick in ticks if tick.label1.get_visible()],
1334 [tick.label2.get_window_extent(renderer)
1335 for tick in ticks if tick.label2.get_visible()])
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:969, in Text.get_window_extent(self, renderer, dpi)
964 raise RuntimeError(
965 "Cannot get window extent of text w/o renderer. You likely "
966 "want to call 'figure.draw_without_rendering()' first.")
968 with cbook._setattr_cm(fig, dpi=dpi):
--> 969 bbox, info, descent = self._get_layout(self._renderer)
970 x, y = self.get_unitless_position()
971 x, y = self.get_transform().transform((x, y))
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:373, in Text._get_layout(self, renderer)
370 ys = []
372 # Full vertical extent of font, including ascenders and descenders:
--> 373 _, lp_h, lp_d = _get_text_metrics_with_cache(
374 renderer, "lp", self._fontproperties,
375 ismath="TeX" if self.get_usetex() else False,
376 dpi=self.get_figure(root=True).dpi)
377 min_dy = (lp_h - lp_d) * self._linespacing
379 for i, line in enumerate(lines):
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:69, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
66 """Call ``renderer.get_text_width_height_descent``, caching the results."""
67 # Cached based on a copy of fontprop so that later in-place mutations of
68 # the passed-in argument do not mess up the cache.
---> 69 return _get_text_metrics_with_cache_impl(
70 weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/text.py:77, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
73 @functools.lru_cache(4096)
74 def _get_text_metrics_with_cache_impl(
75 renderer_ref, text, fontprop, ismath, dpi):
76 # dpi is unused, but participates in cache invalidation (via the renderer).
---> 77 return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backends/backend_agg.py:211, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
209 _api.check_in_list(["TeX", True, False], ismath=ismath)
210 if ismath == "TeX":
--> 211 return super().get_text_width_height_descent(s, prop, ismath)
213 if ismath:
214 ox, oy, width, height, descent, font_image = \
215 self.mathtext_parser.parse(s, self.dpi, prop)
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/backend_bases.py:566, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
562 fontsize = prop.get_size_in_points()
564 if ismath == 'TeX':
565 # todo: handle properties
--> 566 return self.get_texmanager().get_text_width_height_descent(
567 s, fontsize, renderer=self)
569 dpi = self.points_to_pixels(72)
570 if ismath:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:364, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
362 if tex.strip() == '':
363 return 0, 0, 0
--> 364 dvifile = cls.make_dvi(tex, fontsize)
365 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
366 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:293, in TexManager.make_dvi(cls, tex, fontsize)
290 with TemporaryDirectory(dir=dvifile.parent) as tmpdir:
291 Path(tmpdir, "file.tex").write_text(
292 cls._get_tex_source(tex, fontsize), encoding='utf-8')
--> 293 cls._run_checked_subprocess(
294 ["latex", "-interaction=nonstopmode", "-halt-on-error",
295 "-no-shell-escape", "file.tex"], tex, cwd=tmpdir)
296 Path(tmpdir, "file.dvi").replace(dvifile)
297 # Also move the tex source to the main cache directory, but
298 # only for backcompat.
File /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/matplotlib/texmanager.py:254, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
250 report = subprocess.check_output(
251 command, cwd=cwd if cwd is not None else cls._texcache,
252 stderr=subprocess.STDOUT)
253 except FileNotFoundError as exc:
--> 254 raise RuntimeError(
255 f'Failed to process string with tex because {command[0]} '
256 'could not be found') from exc
257 except subprocess.CalledProcessError as exc:
258 raise RuntimeError(
259 '{prog} was not able to process the following string:\n'
260 '{tex!r}\n\n'
(...) 267 exc=exc.output.decode('utf-8', 'backslashreplace'))
268 ) from None
RuntimeError: Failed to process string with tex because latex could not be found
<Figure size 640x480 with 1 Axes>
Vprašanja za vaje#
Vprašanje 1: Z uporabo orodij paketa sympy simbolno določite vrednost statičnega momenta prereza v obliki četrtine kroga na sliki:
Pripravite tudi numerično funkcijo odvisnosti integranda \(f(\varphi) = \Big(\frac{r^3}{3}\, \sin (\varphi) \Big)\) pri podani vrednosti polmera \(R\).
Podatki:
\(R = 7.5\) mm
Vprašanje 2: Uporabite numerično funkcijo, pripravljeno pri prejšnji nalogi, in izračunajte ter grafično prikažite vrednosti integranda iz prve naloge \(\Big(f(\varphi) = \frac{r^3}{3}\sin (\varphi) \Big)\) pri 100 diskretnih točkah na intervalu \(\varphi \in [0, \pi/2]\).
Izračunajte vrednost določenega integrala \(S\) še numerično, s pomočjo trapezne in Simpsonove 1/3 metode iz paketov numpy oziroma scipy.
Trapezno pravilo#
Vprašanje 3: Z uporabo lastne implementacije trapeznega pravila (osnovnega, ne sestavljenega) izračunajte določeni integral
Dobljeno vrednost primerjajte z rezultatom funkcije numpy.trapz (ali scipy.integrate.trapezoid), kjer opazovan interval razdelite na 10 ekvidistantnih odsekov.
Izboljšan približek z Richardsonovo esktrapolacijo:#
Vprašanje 4 : Uporabite Richardsonovo ekstrapolacijo in določite natančnejšo vrednost integrala iz prejšnje naloge tako, da opazovan interval \(x \in [0, 2]\) najprej razdelite na 2, nato še na 4 ekvidistantne segmente in uporabite sestavljeno trapezno metodo iz paketa numpy.
Simpsonovo 1/3 pravilo#
Vprašanje 5: Določen integral iz prejšnje naloge izračunajte z lastno kodo Simpsonove 1/3 metode (osnovne, ne sestavljene).
Dobljeno vrednost primerjajte z rezultatom funkcije scipy.integrate.simpson, kjer opazovan interval razdelite na 7 ekvidistantnih točk.
Vprašanje 6: Podane so izmerjene vrednosti pospeška avtomobila v smeri vožnje v času. Z uporabo kumulativne trapezne metode (scipy.integrate.cumulative_trapezoid) določite vrednosti hitrosti in opravljene poti avtomobila v opazovanm časovnem intervalu.
Avto pri času \(t = 0\) miruje (namig: argument initial).
#Podatki
t = np.linspace(0, 7, 10) # s
a = np.array([ 3.47, 4.03, 4.36, 4.48, 4.27, 3.78, 3.19, 2.73, 2.54, 2.53]) # m/s^2
Gaussova integracijska metoda (Gaussova kvadratura)#
Vprašanje 7: Z uporabo sestavljene trapezne metode iz scipy in metode Gaussove integracije (scipy.integrate.quad) izračunajte vrednosti integralov:
Pri uporabi trapezne metode razdelite opazovan interval na 10 točk.
Vprašanje 8: Integral:
izračunajte še z uporabo funkcije scipy.integrate.fixed_quad, ki ji lahko podamo tudi parameter števila vozlišč pri integraciji, n. Najprej uporabite integracijo z enim vozliščem, nato z dvema in nazadnje še s tremi vozlišči.