presentation prototype with llm

main
Antonio De Lucreziis 11 months ago
parent b74be29ee6
commit d498205e42

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

@ -398,7 +398,10 @@ Vedremo come questi assiomi definiscono un unico invariante di isotopia regolare
*Notazione.* Per rendere alcuni calcoli più leggibili, in questo capitolo utilizzeremo in modo intercambiabile le notazioni $L_K, L[K]$ per indicare il polinomio di Kauffman associato ad un certo diagramma.
#definition[
#definition(
numbered: true,
name: [Assiomi di $L_K$],
)[
Sia $K$ un diagramma di un link non orientato, e sia $bb(Z)[a, a^(-1), z, z^(-1)]$ l'anello dei polinomi di Laurent sugli interi nelle variabili $a$ e $z$.
Allora $L_K in bb(Z)[a, a^(-1), z, z^(-1)]$, e verifica i seguenti assiomi:
@ -833,9 +836,9 @@ per $K = K_1 union.sq K_2$ con $K_1$ sovrastante#footnote[Questo include anche i
sempre con $delta = (a + a^(-1)) slash z - 1$.
=== La definizione induttiva
== La definizione induttiva
#definition(name: [Formula chiusa per $L_K$])[
#definition(numbered: true, name: [Formula chiusa per $L_K$])[
Il polinomio $kL_(K)(a,z)$ è definito induttivamente come segue, abbiamo i seguenti casi:
] <kauffman-rec-inductive-def>
@ -899,6 +902,7 @@ Per prima cosa osserviamo che in ogni termine della definizione induttiva per $L
Nel corso della dimostrazione tutti gli argomenti per induzione si baseranno sul numero di incroci dei diagrammi di link. Ometteremo i casi base, ovvero i controlli per diagrammi con pochi vertici che fanno partire l'induzione in quanto sono tutte semplici verifiche.
#definition(
numbered: true,
name: [L'ipotesi induttiva],
)[
L'ipotesi induttiva che useremo nel corso della dimostrazione è la seguente:
@ -1110,7 +1114,7 @@ La dimostrazione procede sempre mostrando l'indipendenza dalla scelta di punto b
1. Ci sono due casi, in uno otteniamo _due nodi banali in forma standard_, nell'altro _un solo nodo banale_ (non necessariamente in forma discendente).
2. La proprietà del lemma @std-unknot-to-curls, ovvero che i nodi banali standard sono equivalenti a meno di isotopia regolare a diagrammi di nodi formati solo da riccioli, si estende al diagramma del caso dello splice con una sola componente.
2. La proprietà del @std-unknot-to-curls, ovvero che i nodi banali standard sono equivalenti a meno di isotopia regolare a diagrammi di nodi formati solo da riccioli, si estende al diagramma del caso dello splice con una sola componente.
]
#proof[
@ -1118,7 +1122,7 @@ La dimostrazione procede sempre mostrando l'indipendenza dalla scelta di punto b
Dunque abbiamo due casi, in una abbiamo due componenti una sopra l'altra, ognuna delle quali sarà ancora in forma discendente in quanto eredita la proprietà secondo cui la prima volta che si passa su un incrocio questo è un sopra-incrocio.
Se assumiamo che il link del caso precedente sia della forma $E_i hat(K) = hat(K)_1 union hat(K)_2$ con $hat(K)_1$, $hat(K)_2$ i due nodi banali standard con $hat(K)_1$ sovrastante $hat(K)_2$, allora l'altro caso sarà $e_i hat(K) = hat(K)_1 hash hat(K)_2^*$ dove $hat(K)_2^*$ è ottenuto percorrendo $hat(K)_2$ in direzione opposta.
Se assumiamo che il diagramma del caso precedente sia della forma $E_i hat(K) = hat(K)_1 union hat(K)_2$ con $hat(K)_1$, $hat(K)_2$ i due nodi banali standard con $hat(K)_1$ sovrastante $hat(K)_2$, allora l'altro caso sarà $e_i hat(K) = hat(K)_1 hash hat(K)_2^*$ dove $hat(K)_2^*$ è ottenuto percorrendo $hat(K)_2$ in direzione opposta.
#figure(image("assets/splice-circuits.png", width: 4cm))

@ -25,15 +25,19 @@
// })
// }
#let definition(body, name: none) = {
#let definition(body, name: none, numbered: false) = {
// show figure: statement-style(name, numbered: false)
figure(body, kind: "definition", supplement: {
[Definizione]
if name != none {
[ -- ]
name
}
})
figure(
//
body,
kind: "definition",
supplement: if name != none {
[#name]
},
numbering: if numbered {
"1"
},
)
}
#let fact(body, numbered: false, name: none) = {

@ -0,0 +1,416 @@
#import "@preview/touying:0.6.1": *
#import "./presentation/theme.typ": *
#import "@preview/cetz:0.3.2"
#import "@preview/fletcher:0.5.4" as fletcher: node, edge
#import "@preview/numbly:0.1.0": numbly
#import "@preview/theorion:0.3.2": *
#show: show-theorion
// cetz and fletcher bindings for touying
#let cetz-canvas = touying-reducer.with(reduce: cetz.canvas, cover: cetz.draw.hide.with(bounds: true))
#let fletcher-diagram = touying-reducer.with(reduce: fletcher.diagram, cover: fletcher.hide)
#show: dm-unipi-theme.with(aspect-ratio: "16-9", config-common(frozen-counters: (theorem-counter,)), config-info(
title: [Il Polinomio di Kauffman: Un Invariante di Isotopia Regolare],
subtitle: [Tesi di Laurea Triennale],
author: [Antonio De Lucreziis],
date: datetime.today(),
institution: [Dipartimento di Matematica \ Università di Pisa],
logo: image("assets/dm-unipi-logo-bianco.png"),
))
#set text(font: "Source Sans Pro", weight: 500, size: 20pt)
#set strong(delta: 100)
#set par(leading: 0.75em)
#title-slide()
= Introduzione e Motivazione
== Motivazione
#slide[
Come distinguere matematicamente due nodi?
#pause
- I nodi possono apparire diversi ma essere topologicamente equivalenti
- Abbiamo bisogno di *invarianti*: proprietà che non cambiano sotto deformazioni ammesse
- Gli invarianti polinomiali sono strumenti potenti e computabili
#pause
#align(center)[
#text(size: 1.2em, weight: "bold")[
Obiettivo: costruire un invariante polinomiale robusto
]
]
]
== Nodi e Diagrammi
#slide[
*Definizione:* Un *nodo tame* è un sottoinsieme $K subset bb(R)^3$ per cui esiste un embedding $f : bb(S)^1 arrow.hook bb(R)^3$ localmente piatto con $K = f(bb(S)^1)$.
#pause
*Problema:* Lavorare direttamente con embedding in $bb(R)^3$ è complesso
#pause
*Soluzione:* Proiezioni su un piano
- Proiettiamo il nodo su un piano
- Aggiungiamo informazione *sopra/sotto* ad ogni incrocio
- Otteniamo un *diagramma* del nodo
#pause
#align(center)[
I diagrammi sono l'interfaccia computazionale per studiare i nodi
]
]
== Equivalenze tra Nodi
#slide[
*Isotopia Ambiente:* Deformare un nodo senza tagliarlo o incollarlo
Due nodi $K_0, K_1 subset bb(R)^3$ sono *equivalenti* se esiste un'*isotopia ambiente* $H : bb(R)^3 times [0,1] arrow bb(R)^3$
#pause
*Teorema di Reidemeister:* Due diagrammi rappresentano nodi equivalenti se e solo se sono collegati da mosse I, II, III
#pause
*Isotopia Regolare:* Equivalenza generata solo da mosse II e III (ignoriamo la mossa I)
#pause
#align(center)[
L'isotopia regolare "vede" i riccioli (curls)
]
]
= Teoria e Costruzione
== Il Writhe: Un Primo Invariante
#slide[
*Definizione del segno di un incrocio:*
$epsilon(+) = +1 quad quad epsilon(-) = -1$
#pause
*Il writhe:* $w(K) := sum_("incroci " c) epsilon(c)$
#pause
*Proprietà:*
- Invariante per mosse II e III ✓
- NON invariante per mossa I ✗
#pause
*Formula di correzione:* Se $L_K$ è invariante per isotopia regolare con
$L(#text("sopra-ricciolo")) = a L(#text("filo"))$, $L(#text("sotto-ricciolo")) = a^(-1) L(#text("filo"))$
Allora: $F_K := a^(-w(K)) L_K$ è invariante per isotopia ambiente!
]
== Il Polinomio di Kauffman: Definizione
#slide[
Il protagonista: $L_K (a,z) in bb(Z)[a, a^(-1), z, z^(-1)]$
*Assiomi:*
1. Se $K$, $K'$ sono equivalenti a meno di isotopia regolare, allora $L_K = L_{K'}$
#pause
2. Relazioni skein:
- $L(#text("sopra")) + L(#text("sotto")) = z(L(#text("h-splice")) + L(#text("v-splice")))$
- $L(#text("nodo banale")) = 1$
- $L(#text("sopra-ricciolo")) = a L(#text("filo"))$, $L(#text("sotto-ricciolo")) = a^(-1) L(#text("filo"))$
#pause
*Domanda:* Gli assiomi definiscono univocamente $L_K$?
]
== Esempio: Link di Hopf
#slide[
Applichiamo la relazione skein:
$L[#text("Hopf")] + L[#text("versione scambiata")] = z(L[#text("due cerchi")] + L[#text("due fili")])$
#pause
Sapendo che:
- $L[#text("due cerchi")] = delta = (a + a^(-1))/z - 1$
- $L[#text("due fili")] = a + a^(-1)$
#pause
Otteniamo:
$L[#text("Hopf")] = -(a + a^(-1))z^(-1) + 1 + (a + a^(-1))z$
#pause
Questi calcoli suggeriscono che $L_K$ esiste, ma serve una dimostrazione rigorosa!
]
== La Sfida della Buona Definizione
#slide[
*Problema centrale:* Gli assiomi definiscono $L_K$ in modo unico?
#pause
*Sfide:*
1. Gli assiomi sono *impliciti* (relazioni, non formule)
2. Come garantire che esista una soluzione?
3. Come garantire l'unicità?
4. Come verificare l'indipendenza dalle scelte computazionali?
#pause
*Scelte che potrebbero influenzare il risultato:*
- Scelta del punto base $p$ su ogni componente
- Direzione del punto base (orario vs antiorario)
- Ordine delle operazioni nelle sequenze
#pause
#align(center)[
#box(fill: red.lighten(80%), inset: 1em, radius: 5pt)[
*Senza questa dimostrazione, $L_K$ non sarebbe ben definito!*
]
]
]
== Ingredienti per la Costruzione
#slide[
*Concetti chiave necessari:*
1. *Nodo banale standard*: $hat(K)(cal(U), p)$
- Percorrere l'ombra planare da un punto base $p$
- Primo passaggio su ogni incrocio = sopra-incrocio
#pause
2. *Operazioni sui diagrammi*:
- $S_i K$: scambia l'incrocio $i$
- $E_i K$, $e_i K$: splice orizzontale e verticale
#pause
3. *Sequenze di scambi*: $lambda = (lambda_n, dots, lambda_0)$
- Trasformano $K$ in $hat(K)(lambda)$
#pause
*Proprietà fondamentale:* $L[hat(K)] = a^(w(hat(K)))$
]
== La Formula Ricorsiva
#slide[
*Idea*: Esprimere $L_K$ in termini di diagrammi "più semplici"
Applicando le relazioni skein incrementalmente:
$
L[K] + L[S_0 K] &= z(L[E_0 K] + L[e_0 K]) \
L[S_0 K] + L[S_1 S_0 K] &= z(L[E_1 S_0 K] + L[e_1 S_0 K]) \
&dots.v \
L[S_(n-1) dots S_0 K] + L[hat(K)] &= z(L[E_n S_(n-1) dots S_0 K] + L[e_n S_(n-1) dots S_0 K])
$
#pause
Sommando e sottraendo membro a membro, i termini intermedi si cancellano!
#pause
*Formula finale:*
$L_K = (-1)^(n+1) L_(hat(K)) + z sum_(i=0)^n (-1)^i (L[A_i^lambda K] + L[B_i^lambda K])$
]
== Definizione Induttiva Completa
#slide[
*Caso 1:* $K = hat(K)$ (nodo banale standard)
$L_K = a^(w(K))$
#pause
*Caso 2:* $K = K_1 union K_2$ con $K_1$ sovrastante $K_2$
$L_K = delta L_(K_1) L_(K_2)$ dove $delta = (a + a^(-1))/z - 1$
#pause
*Caso 3:* Uso della formula ricorsiva:
$L_K = 1/2 [sum_(q = p, overline(p)) ((-1)^(abs(lambda(q))+1) L_(hat(K)(q)) + z sum_K (lambda(q)))]$
#pause
*Proprietà cruciale:* Ogni termine a destra ha meno incroci o è "più vicino" al caso base
]
== Strategia della Dimostrazione
#slide[
*Ipotesi induttiva* (per diagrammi con $< N$ incroci):
1. $L_K$ è ben definito (indipendente dalle scelte)
2. $L_K$ verifica tutte le relazioni skein
3. $L_K$ è invariante per mosse II e III che non aumentano gli incroci
#pause
*Lemmi tecnici fondamentali:*
- *Lemma delle Rotazioni*: L'ordine ciclico degli scambi non influenza il risultato
- *Invarianza del punto base*: La definizione non dipende dal punto base scelto
- *Identità per nodi banali*: $L[hat(K)(p)] + L[hat(K)(q)] = z(L[E_i hat(K)] + L[e_i hat(K)])$
#pause
*Metodo:* Spostando il punto base di un incrocio per volta, si dimostra l'invarianza completa
]
== Verifica degli Assiomi e Invarianza
#slide[
*Teorema*: La definizione induttiva soddisfa tutti gli assiomi di Kauffman
#pause
*Dimostrazione per le relazioni skein*:
1. Scegli il punto base in modo che l'incrocio sia il primo nella sequenza
2. La relazione skein emerge naturalmente dalla formula ricorsiva
3. Gli altri termini si cancellano per simmetria
#pause
*Invarianza per isotopia regolare*:
- *Mossa II*: scegli punti base che evitano gli incroci coinvolti
- *Mossa III*: usa equivalenze locali e induzione
#pause
#align(center)[
La costruzione induttiva "conosce automaticamente" tutte le proprietà necessarie!
]
]
= Risultati e Applicazioni
== Il Risultato Principale
#slide[
*Teorema*: Esiste ed è unico un invariante $L_K (a,z)$ che soddisfa gli assiomi di Kauffman.
#pause
*Dimostrazione completa*:
1. *Esistenza*: La costruzione induttiva fornisce una definizione esplicita
2. *Buona definizione*: Indipendenza dalle scelte arbitrarie
3. *Verifica assiomi*: La definizione soddisfa tutte le relazioni richieste
4. *Unicità*: Gli assiomi determinano univocamente i valori
#pause
*Conseguenza*: Il polinomio di Kauffman è un invariante completo e computabile per l'isotopia regolare
#pause
#align(center)[
#box(fill: green.lighten(80%), inset: 1em, radius: 5pt)[
*La teoria è ora su basi solide!*
]
]
]
== Dal Regolare all'Ambiente: Il Polinomio $F_K$
#slide[
Usando la formula di correzione:
$F_K = a^(-w(K)) L_K$
#pause
*Teorema*: $F_K (a,z)$ è un invariante di isotopia ambiente.
#pause
*Significato*:
- Partendo da un invariante regolare ($L_K$)
- Aggiungiamo la correzione del writhe
- Otteniamo un vero invariante di nodi!
#pause
*Proprietà*:
- $F_(m(K))(a,z) = F_K(1/a, z)$ (comportamento rispetto al mirror)
- $F[K_1 hash K_2] = F[K_1] F[K_2]$ (moltiplicatività per somma connessa)
- $F_K$ distingue nodi che $L_K$ non può distinguere
]
== Implementazione e Verifica
#slide[
*Progetto Computazionale:*
- *Implementazione in Python*: Algoritmo basato sulle relazioni skein
- *Calcolo automatico* di $L_K$ e $F_K$ per diagrammi di nodi
- *Interfaccia user-friendly* per l'inserimento di diagrammi
#pause
*Verifica sperimentale:*
- Confronto con il database *KnotInfo*
- Verifica su centinaia di nodi noti
- Test di coerenza con valori pubblicati
#pause
*Scoperta interessante:* Trovato un *errore* nel valore pubblicato per il nodo $10_{125}$!
#pause
#align(center)[
La teoria e l'implementazione si confermano a vicenda
]
]
== Conclusioni
#slide[
*Percorso compiuto:*
1. Dal concetto geometrico di nodo alla formalizzazione tramite diagrammi
2. Definizione dell'isotopia regolare e degli invarianti
3. Costruzione rigorosa del polinomio di Kauffman
4. Dimostrazione della buona definizione
5. Estensione agli invarianti di isotopia ambiente
#pause
*Risultati principali:*
- *Dimostrazione* della buona definizione di $L_K$
- *Costruzione* di $F_K$ come invariante ambiente
- *Verifica computazionale* e scoperta di errori nella letteratura
#pause
#align(center)[
#text(size: 1.2em, weight: "bold")[
Grazie per l'attenzione!
]
]
*Domande?*
]

@ -0,0 +1,528 @@
#import "@preview/touying:0.6.1": *
// #let slide(config: (:), repeat: auto, setting: body => body, composer: auto, ..bodies) = touying-slide-wrapper(self => {
// let header(self) = {
// place(left + top, dx: 3em, grid(
// columns: (auto, 1fr),
// column-gutter: 1em,
// align: horizon,
// image("../assets/logo-unipi-top.png"),
// text(fill: self.colors.primary, utils.call-or-display(self, self.store.header)),
// ))
// // place(left + top, line(start: (40%, 0%), end: (40% - 3%, 3em + 0.5em + 0.5em), stroke: .75em + white))
// }
// let footer(self) = {
// set text(size: 0.8em)
// place(left, dx: 3em, utils.call-or-display(self, utils.call-or-display(self, self.store.footer)))
// }
// let self = utils.merge-dicts(self, config-page(header: header, footer: footer))
// touying-slide(self: self, config: config, repeat: repeat, setting: setting, composer: composer, ..bodies)
// })
// #let title-slide(config: (:), ..args) = touying-slide-wrapper(
// self => {
// self = utils.merge-dicts(
// self,
// config,
// config-common(freeze-slide-counter: true),
// config-page(background: utils.call-or-display(self, self.store.background), margin: (x: 0em, top: 30%, bottom: 0%)),
// )
// let info = self.info + args.named()
// let body = {
// set align(center)
// stack(spacing: 3em, if info.title != none {
// text(size: 48pt, weight: "bold", fill: self.colors.primary, info.title)
// }, if info.author != none {
// text(fill: self.colors.primary-light, size: 28pt, weight: "regular", info.author)
// }, if info.date != none {
// text(fill: self.colors.primary-light, size: 20pt, weight: "regular", utils.display-info-date(self))
// })
// }
// touying-slide(self: self, body)
// },
// )
// #let outline-slide(config: (:), leading: 50pt) = touying-slide-wrapper(self => {
// set text(size: 30pt, fill: self.colors.primary)
// set par(leading: leading)
// let body = {
// grid(columns: (1fr, 1fr), rows: (1fr), align(center + horizon, {
// set par(leading: 20pt)
// context {
// if text.lang == "zh" {
// text(size: 80pt, weight: "bold", [#text(size: 36pt)[CONTENTS]\ 目录])
// } else {
// text(size: 48pt, weight: "bold", [CONTENTS])
// }
// }
// }), align(left + horizon, {
// set par(leading: leading)
// set text(weight: "bold")
// components.custom-progressive-outline(level: none, depth: 1, numbered: (true,))
// }))
// }
// self = utils.merge-dicts(
// self,
// config-common(freeze-slide-counter: true),
// config-page(background: utils.call-or-display(self, self.store.background), margin: 0em),
// )
// touying-slide(self: self, config: config, body)
// })
// #let new-section-slide(config: (:), level: 1, body) = touying-slide-wrapper(
// self => {
// let slide-body = {
// stack(
// dir: ttb,
// spacing: 12%,
// align(center, text(fill: self.colors.primary, size: 166pt, utils.display-current-heading-number(level: level))),
// align(center, text(
// fill: self.colors.primary,
// size: 60pt,
// weight: "bold",
// utils.display-current-heading(level: level, numbered: false),
// )),
// )
// body
// }
// self = utils.merge-dicts(self, config-page(
// margin: (left: 0%, right: 0%, top: 20%, bottom: 0%),
// background: utils.call-or-display(self, self.store.background),
// ))
// touying-slide(self: self, config: config, slide-body)
// },
// )
// /// Focus on some content.
// ///
// /// Example: `#focus-slide[Wake up!]`
// ///
// /// - config (dictionary): The configuration of the slide. You can use `config-xxx` to set the configuration of the slide. For more configurations, you can use `utils.merge-dicts` to merge them.
// #let focus-slide(config: (:), body) = touying-slide-wrapper(
// self => {
// self = utils.merge-dicts(self, config-common(freeze-slide-counter: true), config-page(fill: self.colors.primary, margin: 2em))
// set text(fill: self.colors.neutral-lightest, size: 2em, weight: "bold")
// touying-slide(self: self, config: config, align(horizon + center, body))
// },
// )
// #let dm-unipi-theme(
// aspect-ratio: "16-9",
// header: self => utils.display-current-heading(depth: self.slide-level),
// footer: context utils.slide-counter.display(),
// ..args,
// body,
// ) = {
// set text(font: "Open Sans")
// set par(leading: 1em)
// set text(size: 20pt)
// set heading(numbering: "1.1")
// show heading.where(level: 1): set heading(numbering: "1")
// show: touying-slides.with(
// config-page(paper: "presentation-" + aspect-ratio, margin: (x: 3em, top: 5em, bottom: 3em)),
// config-common(slide-fn: slide, new-section-slide-fn: new-section-slide),
// config-methods(init: (self: none, body) => {
// show heading: set text(fill: self.colors.primary-light)
// body
// }, alert: utils.alert-with-primary-color),
// config-colors(
// primary: rgb("#003c71"),
// primary-light: rgb("#00213d"),
// primary-lightest: rgb("#F2F4F8"),
// neutral-lightest: rgb("#FFFFFF"),
// ),
// // save the variables for later use
// config-store(
// align: align,
// header: header,
// footer: footer,
// background: self => {
// let page-width = if self.page.paper == "presentation-16-9" { 841.89pt } else { 793.7pt }
// let r = if self.at("show-notes-on-second-screen", default: none) == none { 1.0 } else { 0.5 }
// let bias1 = - page-width * (1 - r)
// let bias2 = - page-width * 2 * (1 - r)
// place(center + horizon, dx: bias1, polygon(
// fill: self.colors.primary-lightest,
// (35% * page-width, -17%),
// (70% * page-width, 10%),
// (35% * page-width, 30%),
// (0% * page-width, 10%),
// ))
// place(center + horizon, dy: 7%, dx: bias1, ellipse(fill: white, width: r * 45%, height: 120pt))
// place(center + horizon, dy: 5%, dx: bias1, ellipse(fill: self.colors.primary-lightest, width: r * 40%, height: 80pt))
// place(center + horizon, dy: 12%, dx: bias1, rect(fill: self.colors.primary-lightest, width: r * 40%, height: 60pt))
// place(center + horizon, dy: 20%, dx: bias1, ellipse(fill: white, width: r * 40%, height: 70pt))
// },
// ),
// ..args,
// )
// body
// }
//
#let _tblock(self: none, title: none, it) = {
grid(columns: 1, row-gutter: 0pt, block(
fill: self.colors.primary-dark,
width: 100%,
radius: (top: 6pt),
inset: (top: 0.4em, bottom: 0.3em, left: 0.5em, right: 0.5em),
text(fill: self.colors.neutral-lightest, weight: "bold", title),
), rect(
fill: gradient.linear(self.colors.primary-dark, self.colors.primary.lighten(90%), angle: 90deg),
width: 100%,
height: 4pt,
), block(
fill: self.colors.primary.lighten(90%),
width: 100%,
radius: (bottom: 6pt),
inset: (top: 0.4em, bottom: 0.5em, left: 0.5em, right: 0.5em),
it,
))
}
/// Theorem block for the presentation.
///
/// - title (string): The title of the theorem. Default is `none`.
///
/// - it (content): The content of the theorem.
#let tblock(title: none, it) = touying-fn-wrapper(_tblock.with(title: title, it))
/// Default slide function for the presentation.
///
/// - title (string): The title of the slide. Default is `auto`.
///
/// - config (dictionary): The configuration of the slide. You can use `config-xxx` to set the configuration of the slide. For more several configurations, you can use `utils.merge-dicts` to merge them.
///
/// - repeat (auto): The number of subslides. Default is `auto`, which means touying will automatically calculate the number of subslides.
///
/// The `repeat` argument is necessary when you use `#slide(repeat: 3, self => [ .. ])` style code to create a slide. The callback-style `uncover` and `only` cannot be detected by touying automatically.
///
/// - setting (dictionary): The setting of the slide. You can use it to add some set/show rules for the slide.
///
/// - composer (function): The composer of the slide. You can use it to set the layout of the slide.
///
/// For example, `#slide(composer: (1fr, 2fr, 1fr))[A][B][C]` to split the slide into three parts. The first and the last parts will take 1/4 of the slide, and the second part will take 1/2 of the slide.
///
/// If you pass a non-function value like `(1fr, 2fr, 1fr)`, it will be assumed to be the first argument of the `components.side-by-side` function.
///
/// The `components.side-by-side` function is a simple wrapper of the `grid` function. It means you can use the `grid.cell(colspan: 2, ..)` to make the cell take 2 columns.
///
/// For example, `#slide(composer: 2)[A][B][#grid.cell(colspan: 2)[Footer]]` will make the `Footer` cell take 2 columns.
///
/// If you want to customize the composer, you can pass a function to the `composer` argument. The function should receive the contents of the slide and return the content of the slide, like `#slide(composer: grid.with(columns: 2))[A][B]`.
///
/// - bodies (content): The contents of the slide. You can call the `slide` function with syntax like `#slide[A][B][C]` to create a slide.
#let slide(
title: auto,
header: auto,
footer: auto,
align: auto,
config: (:),
repeat: auto,
setting: body => body,
composer: auto,
..bodies,
) = touying-slide-wrapper(self => {
if align != auto {
self.store.align = align
}
if title != auto {
self.store.title = title
}
if header != auto {
self.store.header = header
}
if footer != auto {
self.store.footer = footer
}
let new-setting = body => {
show: std.align.with(self.store.align)
show: setting
body
}
touying-slide(self: self, config: config, repeat: repeat, setting: new-setting, composer: composer, ..bodies)
})
/// Title slide for the presentation. You should update the information in the `config-info` function. You can also pass the information directly to the `title-slide` function.
///
/// Example:
///
/// ```typst
/// #show: stargazer-theme.with(
/// config-info(
/// title: [Title],
/// logo: emoji.city,
/// ),
/// )
///
/// #title-slide(subtitle: [Subtitle])
/// ```
///
/// - config (dictionary): The configuration of the slide. You can use `config-xxx` to set the configuration of the slide. For more several configurations, you can use `utils.merge-dicts` to merge them.
#let title-slide(config: (:), ..args) = touying-slide-wrapper(self => {
self = utils.merge-dicts(self, config)
self.store.title = none
let info = self.info + args.named()
info.authors = {
let authors = if "authors" in info {
info.authors
} else {
info.author
}
if type(authors) == array {
authors
} else {
(authors,)
}
}
let body = {
show: std.align.with(center + horizon)
block(fill: self.colors.primary, inset: 1.5em, radius: 0.5em, breakable: false, {
text(size: 1.2em, fill: self.colors.neutral-lightest, weight: "bold", info.title)
if info.subtitle != none {
parbreak()
text(size: 1.0em, fill: self.colors.neutral-lightest, weight: "bold", info.subtitle)
}
})
// authors
grid(
columns: (1fr,) * calc.min(info.authors.len(), 3),
column-gutter: 1em,
row-gutter: 1em,
..info.authors.map(author => text(fill: black, author)),
)
v(0.5em)
// institution
if info.institution != none {
parbreak()
text(size: 0.7em, info.institution)
}
// date
if info.date != none {
parbreak()
text(size: 1.0em, utils.display-info-date(self))
}
}
touying-slide(self: self, body)
})
/// Outline slide for the presentation.
///
/// - config (dictionary): is the configuration of the slide. You can use `config-xxx` to set the configuration of the slide. For more several configurations, you can use `utils.merge-dicts` to merge them.
///
/// - title (string): is the title of the outline. Default is `utils.i18n-outline-title`.
///
/// - level (int, none): is the level of the outline. Default is `none`.
///
/// - numbered (boolean): is whether the outline is numbered. Default is `true`.
#let outline-slide(config: (:), title: utils.i18n-outline-title, numbered: true, level: none, ..args) = touying-slide-wrapper(
self => {
self.store.title = title
touying-slide(
self: self,
config: config,
std.align(
self.store.align,
components.adaptive-columns(text(fill: self.colors.primary, weight: "bold", components.custom-progressive-outline(
level: level,
alpha: self.store.alpha,
indent: (0em, 1em),
vspace: (.4em,),
numbered: (numbered,),
depth: 1,
..args.named(),
))) + args.pos().sum(default: none),
),
)
},
)
/// New section slide for the presentation. You can update it by updating the `new-section-slide-fn` argument for `config-common` function.
///
/// Example: `config-common(new-section-slide-fn: new-section-slide.with(numbered: false))`
///
/// - config (dictionary): is the configuration of the slide. You can use `config-xxx` to set the configuration of the slide. For more several configurations, you can use `utils.merge-dicts` to merge them.
///
/// - title (content, function): is the title of the section. The default is `utils.i18n-outline-title`.
///
/// - level (int): is the level of the heading. The default is `1`.
///
/// - numbered (boolean): is whether the heading is numbered. The default is `true`.
///
/// - body (none): is the body of the section. It will be passed by touying automatically.
#let new-section-slide(config: (:), title: utils.i18n-outline-title, level: 1, numbered: true, ..args, body) = outline-slide(config: config, title: title, level: level, numbered: numbered, ..args, body)
/// Focus on some content.
///
/// Example: `#focus-slide[Wake up!]`
///
/// - config (dictionary): is the configuration of the slide. You can use `config-xxx` to set the configuration of the slide. For more several configurations, you can use `utils.merge-dicts` to merge them.
///
/// - align (alignment): is the alignment of the content. The default is `horizon + center`.
#let focus-slide(config: (:), align: horizon + center, body) = touying-slide-wrapper(self => {
self = utils.merge-dicts(
self,
config-common(freeze-slide-counter: true),
config-page(fill: self.colors.primary, margin: 2em, header: none, footer: none),
)
set text(fill: self.colors.neutral-lightest, weight: "bold", size: 1.5em)
touying-slide(self: self, config: config, std.align(align, body))
})
/// End slide for the presentation.
///
/// - config (dictionary): is the configuration of the slide. You can use `config-xxx` to set the configuration of the slide. For more several configurations, you can use `utils.merge-dicts` to merge them.
///
/// - title (string): is the title of the slide. The default is `none`.
///
/// - body (array): is the content of the slide.
#let ending-slide(config: (:), title: none, body) = touying-slide-wrapper(self => {
let content = {
set std.align(center + horizon)
if title != none {
block(
fill: self.colors.tertiary,
inset: (top: 0.7em, bottom: 0.7em, left: 3em, right: 3em),
radius: 0.5em,
text(size: 1.5em, fill: self.colors.neutral-lightest, title),
)
}
body
}
touying-slide(self: self, config: config, content)
})
#let dm-unipi-theme(
aspect-ratio: "16-9",
align: horizon,
alpha: 20%,
title: self => utils.display-current-heading(depth: self.slide-level),
header-right: self => self.info.logo,
progress-bar: true,
footer-columns: (25%, 1fr, 5em),
footer-a: self => self.info.author,
footer-c: self => if self.info.short-title == auto {
self.info.title
} else {
self.info.short-title
},
footer-d: context utils.slide-counter.display() + " / " + utils.last-slide-number,
..args,
body,
) = {
let header(self) = {
set std.align(top)
grid(
rows: (auto, auto),
utils.call-or-display(self, self.store.navigation),
utils.call-or-display(self, self.store.header),
)
}
let footer(self) = {
set text(size: .5em)
set std.align(center + bottom)
grid(
rows: (auto, auto),
utils.call-or-display(self, self.store.footer),
if self.store.progress-bar {
utils.call-or-display(self, components.progress-bar(height: 2pt, self.colors.primary, self.colors.neutral-lightest))
},
)
}
show: touying-slides.with(
config-page(
paper: "presentation-" + aspect-ratio,
header: header,
footer: footer,
header-ascent: 0em,
footer-descent: 0em,
margin: (top: 3.5em, bottom: 2.5em, x: 2.5em),
),
config-common(slide-fn: slide, new-section-slide-fn: new-section-slide),
config-methods(init: (self: none, body) => {
set text(size: 18pt, font: "Open Sans")
set par(leading: 0.75em)
set list(marker: {
place(top + left, dy: 0.2em, circle(fill: self.colors.primary, radius: 3pt))
h(0.25em)
})
show figure.caption: set text(size: 0.6em)
show footnote.entry: set text(size: 0.6em)
show heading: set text(fill: self.colors.primary)
show link: it => if type(it.dest) == str {
set text(fill: self.colors.primary)
it
} else {
it
}
show figure.where(kind: table): set figure.caption(position: top)
body
}, alert: utils.alert-with-primary-color, tblock: _tblock),
config-colors(
primary: rgb("#003c71"),
primary-dark: rgb("#005baa"),
secondary: rgb("#ffffff"),
neutral-lightest: rgb("#ffffff"),
neutral-darkest: rgb("#001c35"),
),
// save the variables for later use
config-store(
align: align,
alpha: alpha,
title: title,
header-right: header-right,
progress-bar: progress-bar,
footer-columns: footer-columns,
footer-a: footer-a,
footer-c: footer-c,
footer-d: footer-d,
navigation: self => components.simple-navigation(
self: self,
primary: white,
secondary: gray,
background: self.colors.neutral-darkest,
logo: utils.call-or-display(self, self.store.header-right),
),
header: self => if self.store.title != none {
block(
width: 100%,
height: 2em,
fill: self.colors.primary,
place(
left + horizon,
text(fill: self.colors.neutral-lightest, weight: 600, size: 1.2em, utils.call-or-display(self, self.store.title)),
dx: 1.5em,
),
)
},
footer: self => {
let cell(fill: none, it) = rect(
width: 100%,
height: 100%,
inset: 1mm,
outset: 0mm,
fill: fill,
stroke: none,
std.align(horizon, text(fill: self.colors.neutral-lightest, it)),
)
grid(
columns: self.store.footer-columns,
rows: (1.5em, auto),
cell(fill: self.colors.neutral-darkest, utils.call-or-display(self, self.store.footer-a)),
cell(fill: self.colors.primary, utils.call-or-display(self, self.store.footer-c)),
cell(fill: self.colors.primary, utils.call-or-display(self, self.store.footer-d)),
)
},
),
..args,
)
body
}

@ -223,7 +223,20 @@
block({
strong({
it.supplement
[Definizione]
if it.numbering != none {
[ #(
..counter(heading).get().slice(0, 1).map(it => str(it)),
numbering(it.numbering, ..it.counter.at(it.location())),
).join(".") ]
}
if it.supplement != none {
[ -- ]
it.supplement
}
[.]
})
[ ]
@ -340,7 +353,15 @@
let el = it.element
if el.func() == figure {
link(el.location(), {
if it.supplement != auto { it.supplement } else { el.supplement }
if it.supplement != auto {
it.supplement
} else {
if el.kind == "definition" {
[Definizione]
} else {
el.supplement
}
}
[ ]
(
..counter(heading).at(el.location()).slice(0, 1).map(it => str(it)),
@ -357,9 +378,10 @@
}
}
// Highlight
// show ref: it => {
// set text(fill: white)
// box(fill: red, outset: (y: 0.5em), it)
// set text(fill: red.mix(black))
// box(fill: red.mix(white), outset: (y: 0.5em), it)
// }
// First thesis page

Loading…
Cancel
Save