Uma classe para vectores
#ifndef __SIMPLEARRAY__
#define __SIMPLEARRAY__
#include <iostream>
using namespace std;
template<class T>
class SimpleArray {
template<class U> friend ostream &operator <<(ostream&, const SimpleArray<U>&);
public:
SimpleArray(int n);
// Create array of n elements
SimpleArray();
// Create array of 0 elements
SimpleArray(const SimpleArray<T>&);
// Copy array
~SimpleArray();
// Destroy array
T& operator[](int i);
// Subscripting
int numElts();
// Number of elements
SimpleArray<T>& operator=(const SimpleArray<T>&); // Array assignment
SimpleArray<T>& operator=(T);
// Scalar assignment
void setSize(int n);
// Change size
private:
int num_elts;
// Number of elements
T* ptr_to_data;
// Pointer to built-in array of elements
void copy(const SimpleArray<T>& a);
// Copy in elements of a
};
#endif
Curso C++ (J. Seixas)
Overloading de operadores
Primeiro: nem todos os operadores são passíveis de overloading.
Operadores que podem ser overloaded
+ - * / = < > += -= *= /= << >> <<= >>= == != <= >= ++ -% & ^ ! | ~ &= ^= |= && || %= [] () , ->* -> new delete new[]
delete[]
Operadores que não podem ser overloaded
:: .* . ?:
Segundo: não é possível alterar nem a precedência, nem a associatividade
dos operadores.
Terceiro: Os operadores iniciais ficam inacessíveis! Não há garantia quanto
à ordem segundo a qual os operandos são avaliados.
Quarto: O significado dos operadores para os tipos pré-definidos não pode
ser alterado. Não alterar operadores como , &, && ou ||
Curso C++ (J. Seixas)
Uma classe para vectores
Overloading do operador []:
template<class T>
SimpleArray<T>::~SimpleArray() {
delete [] ptr_to_data;
}
template<class T>
T& SimpleArray<T>::operator[](int i) {
return ptr_to_data[i];
}
template<class T>
int SimpleArray<T>::numElts() {
return num_elts;
}
Curso C++ (J. Seixas)
Uma classe para vectores
Overloading do operador =: (assignment)
template<class T>
SimpleArray<T>& SimpleArray<T>::operator=(const SimpleArray<T>& rhs) {
if ( ptr_to_data != rhs.ptr_to_data ) {
setSize( rhs.num_elts );
copy(rhs);
}
return *this;
}
Os operadores = retornam uma referência: não é necessário criar e
destruir uma cópia temporária do resultado. Como retornam uma
referência ao objecto da esquerda permitem pôr
a=b=c;
Curso C++ (J. Seixas)
Uma classe para vectores
Overloading do operador <<: (assignment)
template<class T>
ostream &operator <<(ostream& stream, const SimpleArray<T>& v){
for(int i=0; i < v.num_elts ;++i)
stream << v.ptr_to_data[i] << " ";
return stream;
}
Os operadores << retornam uma referência a ostream e
assim podemos por cout << v << u << endl;
Curso C++ (J. Seixas)
Uma classe para vectores
Uma função com o qualificativo friend, seja ela
membro de outra classe ou global, pode
aceder a membros não públicos da classe que
a classificou como friend.
A classificação de friend a uma dada função
só se aplica a essa função, não a todas com o
mesmo nome!
Se se declarar uma classe como friend todas
as suas funções serão friend.
A posição onde a declaração de friend está na
definição da classe é irrelevante. Os
especificadores de acesso private e public não
têm qualquer efeito em friend.
Curso C++ (J. Seixas)
Uma classe para vectores
Implementação (I):
template<class T>
SimpleArray<T>::SimpleArray(int n) {
num_elts = n;
ptr_to_data = new T[n];
}
template<class T>
SimpleArray<T>::SimpleArray() {
num_elts = 0;
ptr_to_data = 0;
}
template<class T>
SimpleArray<T>::SimpleArray(const SimpleArray<T>& a) {
num_elts = a.num_elts;
ptr_to_data = new T[num_elts];
copy(a); // Copy a's elements
}
template<class T>
void SimpleArray<T>::copy(const SimpleArray<T>& a) {
// Copy a's elements into the elements of *this
T* p = ptr_to_data + num_elts;
T* q = a.ptr_to_data + num_elts;
while (p > ptr_to_data) *--p = *--q;
}
Curso C++ (J. Seixas)
Uma classe para vectores
Implementação (II):
template<class T>
SimpleArray<T>::~SimpleArray() {
delete [] ptr_to_data;
}
template<class T>
T& SimpleArray<T>::operator[](int i) {
return ptr_to_data[i];
}
template<class T>
int SimpleArray<T>::numElts() {
return num_elts;
}
Curso C++ (J. Seixas)
Uma classe para vectores
Implementação (III):
template<class T>
SimpleArray<T>& SimpleArray<T>::operator=(const SimpleArray<T>& rhs) {
if ( ptr_to_data != rhs.ptr_to_data ) {
setSize( rhs.num_elts );
copy(rhs);
}
return *this;
}
template<class T>
void SimpleArray<T>::setSize(int n) {
if (n != num_elts) {
delete [] ptr_to_data;
num_elts = n;
// Delete old elements,
// set new count,
ptr_to_data = new T[n]; // and allocate new elements
}
}
Curso C++ (J. Seixas)
Uma classe para vectores
Implementação (IV):
template<class T>
SimpleArray<T>& SimpleArray<T>::operator=(T rhs) {
T* p = ptr_to_data + num_elts;
while (p > ptr_to_data) *--p = rhs;
return *this;
}
Curso C++ (J. Seixas)
Exemplo: O modelo de Ising
O modelo de Ising (estudado inicialmente
pelo físico Ernst Ising por sugestão do seu
orientador de doutoramento Wilhelm Lenz)
é um modelo matemático em Física
Estatística, muito importante para estudar
fenómenos como o ferromagnetismo. Teve
e tem um papel fundamental na moderna
teoria das transições de fase e fenómenos
críticos.
Curso C++ (J. Seixas)
Exemplo: O modelo de Ising
O modelo mais simples consiste numa
cadeia de “spins” Si cada um só podendo
tomar os valores ±1.
A energia do sistema para uma dada
configuração de spins é dada por
Cada configuração de spins é uma
“fotografia” do sistema num dado instante
Curso C++ (J. Seixas)
Exemplo: O modelo de Ising
O objectivo da Física Estatística é
determinar o valor das grandezas
termodinâmicas macroscópicas a partir da
dinâmica microscópica do sistema.
A energia do sistema em cada instante é
dada pela expressão anterior. A energia
média ao longo do tempo é dada por
1 Nconf
E 
En

Nconf n1
Curso C++ (J. Seixas)
Exemplo: O modelo de Ising
Calcular <E> para todas as possíveis
configurações é possível, mas:
Será que todas as configurações têm a mesma
importância no processo?
Será que no intervalo de tempo (mesmo longo) em que
estamos a observar todas elas aparecem?
Se não, como determinar <E> tendo em vista a
distribuição de configurações mais frequentes?
Como determinar a frequência com que as configurações
aparecem?
…
O objectivo da Física Estatística é dar respostas a estas
perguntas
Curso C++ (J. Seixas)
Exemplo: O modelo de Ising
1ª pergunta: Como calcular a frequência
(probabilidade) com que aparece uma dada
configuração?
Resposta (1ª parte): Há muitas configurações que têm a
mesma energia associada sobretudo se há simetrias no
sistema. Exemplo (modelo de Ising ferromagnético):
Ns
E  J sisi1
i1
Existe uma simetria Z2: trocar s→-s fornece o mesmo
resultado para E. Existem configurações com energia
menor do que outras. Em física temos sempre de tender
para um mínimo de energia.
Curso C++ (J. Seixas)
Exemplo: O modelo de Ising
1ª pergunta: Como calcular a frequência
(probabilidade) com que aparece uma
dada configuração?
Resposta (2ª parte):
Configurações todos os spins para baixo
excepto 1: N;
Configurações todos os spins para baixo
excepto 2: N(N-1); desordenado N(N-1)/2!
Configurações todos os spins para baixo
excepto k: N!/(N-k)!; desordenado N!/k!(N-k)!
Curso C++ (J. Seixas)
Exemplo: O modelo de Ising
1ª pergunta: Como calcular a frequência
(probabilidade) com que aparece uma dada
configuração?
Resposta (2ª parte):
A probabilidade de ter N spins e colocá-los N1 na caixa 1,
N2 na caixa 2, … Nk na caixa k é
k


 1 
N!
(N  N1 )!   Nk ! 

...
  N!  
W  
i1  Ni! 
 N1 (N  N1 )! N2 (N  N1  N2 )!  Nk !0! 
Se houver degenerescência, o número de maneiras de
preencher uma caixa i é gi então a expressão anterior é
gNii
W  N!
i1 Ni!
k
Curso C++ (J. Seixas)
Exemplo: O modelo de Ising
1ª pergunta: Como calcular a frequência
(probabilidade) com que aparece uma
dada configuração?
Resposta (3ª parte):
Qual é o valor máximo da probabilidade, ou
seja, qual o conjunto {Ni} para os quais W é
máxima? Na realidade, essa é a configuração
mais provável, ou seja, a que aparecerá mais
vezes. Resposta: Usar multiplicadores de
Lagrange minimizando
f (Ni )  ln(W)   (N  Ni )   (E Nii )
Curso C++ (J. Seixas)
Exemplo: O modelo de Ising
1ª pergunta: Como calcular a frequência
(probabilidade) com que aparece uma
dada configuração?
Resposta (3ª parte):
Usando a aproximação de Stirling
NN
N! 2N N
e
e pondo igual a 0 a derivada em ordem a Ni temos
Ni 
Curso C++ (J. Seixas)
gi
e   i

gi
e( i   ) / kT
Exemplo: O modelo de Ising
1ª pergunta: Como calcular a frequência
(probabilidade) com que aparece uma
dada configuração?
Resposta (3ª parte):
Função de partição:
N  Ni
Função de partição
e logo
giei / kT
Ni  N
; Z   giei / kT
Z
i
Curso C++ (J. Seixas)
Exemplo: O modelo de Ising
2ª pergunta: O comportamento do sistema
não é portanto possível de seguir em
detalhe analiticamente. Se as configurações
não são todas equiprováveis, como escolher
as melhores de forma a não perder tempo
com as que são mais improváveis?
Resposta (entre outras): Algoritmo de
Metropolis
Curso C++ (J. Seixas)
Download

Uma classe para vectores