Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
nomad-lab
soap-plus-plus
Commits
5f8a2b3c
Commit
5f8a2b3c
authored
Sep 14, 2017
by
Carl Poelking
Browse files
Network optimiser for dim-red.
parent
d941ea9c
Changes
1
Hide whitespace changes
Inline
Side-by-side
src/soap/soapy/dimred.py
View file @
5f8a2b3c
...
...
@@ -3,13 +3,195 @@ import numpy as np
import
sklearn.manifold
import
sklearn.decomposition
def
compute_dist_matrix_2d
(
X
,
Y
):
dX
=
np
.
subtract
.
outer
(
X
,
X
)
dY
=
np
.
subtract
.
outer
(
Y
,
Y
)
return
dX
,
dY
,
(
dX
*
dX
+
dY
*
dY
)
**
0.5
def
compute_dist_matrix_3d
(
X
,
Y
,
Z
):
dX
=
np
.
subtract
.
outer
(
X
,
X
)
dY
=
np
.
subtract
.
outer
(
Y
,
Y
)
dZ
=
np
.
subtract
.
outer
(
Z
,
Z
)
return
dX
,
dY
,
(
dX
*
dX
+
dY
*
dY
+
dZ
*
dZ
)
**
0.5
class
BondNetwork
(
object
):
def
__init__
(
self
,
tags
,
K
,
M
):
"""
Args:
tags (list of str, len=N): string labels for nodes
K (np.ndarray, shape=(N,N)): kernel matrix, measuring similarity between nodes
M (np.ndarray, shape=(N,)): list of node masses
Example:
>>> bond_network = BondNetwork(tags, K, M)
>>> bond_network.initialise(method='kernelpca')
>>> bond_network.integrate_md(
>>> n_steps=7000,
>>> rms_cut=1e-7,
>>> dt=0.01,
>>> dn_out=10,
>>> append_traj=False)
>>> ofs = open('confout.txt', 'w')
>>> for i in range(bond_network.N):
>>> ofs.write('%20s %3d %+1.7e %+1.7e
\n
' % (
>>> bond_network.tags[i], bond_network.M[i],
>>> bond_network.X[i], bond_network.Y[i]))
>>> ofs.close()
"""
self
.
tags
=
tags
self
.
N
=
len
(
tags
)
self
.
K
=
K
self
.
D
=
(
1.
-
K
**
2
+
1e-7
)
**
0.5
self
.
M
=
M
# Masses
# Exclusions and constraints
self
.
have_excl
=
False
self
.
have_constr
=
False
assert
K
.
shape
[
0
]
==
self
.
N
assert
K
.
shape
[
1
]
==
self
.
N
def
initialise
(
self
,
method
):
# Positions
if
method
==
'random'
:
X
=
np
.
random
.
uniform
(
size
=
self
.
N
)
Y
=
np
.
random
.
uniform
(
size
=
self
.
N
)
elif
method
in
[
'mds'
,
'kernelpca'
]:
pos_mat
=
dimred_matrix
(
method
=
method
,
#'kernelpca', #'mds',
kmat
=
self
.
K
,
distmat
=
self
.
D
,
symmetrize
=
True
,
outfile
=
None
)
self
.
X
=
pos_mat
[:,
0
]
self
.
Y
=
pos_mat
[:,
1
]
else
:
raise
NotImplementedMethod
(
method
)
# Velocities
self
.
Vx
=
np
.
zeros
((
self
.
N
,),
dtype
=
'float64'
)
self
.
Vy
=
np
.
zeros
((
self
.
N
,),
dtype
=
'float64'
)
# Equilibrium distances
self
.
R0
=
self
.
D
# Harmonic force constants
alpha
=
10.
# 10.
beta
=
1.
k_t
=
0.85
# 0.85 # 0.85
self
.
H
=
beta
*
0.5
*
(
1.
+
np
.
tanh
(
alpha
*
(
K
-
k_t
))
)
# Universal force constant?
self
.
H
.
fill
(
0.28
)
# NOTE HACK
np
.
fill_diagonal
(
self
.
H
,
0.0
)
return
def
steep
(
self
,
n_steps
,
dt
):
"""
TODO Turn this into a proper gradient descent (step size opt etc.)
"""
ofs
=
open
(
'traj.xyz'
,
'w'
)
for
i
in
range
(
n_steps
):
# Compute distance matrix
dX
,
dY
,
dR
=
compute_dist_matrix_2d
(
self
.
X
,
self
.
Y
)
# Compute forces
Fx_harm
=
self
.
H
*
(
dR
-
self
.
R0
)
*
dX
# Xij = xi-xj. Thus dR > R0 => Fij ~ -(xi-xj) is force experienced by j
Fy_harm
=
self
.
H
*
(
dR
-
self
.
R0
)
*
dY
Fx_harm
=
np
.
sum
(
Fx_harm
,
axis
=
1
)
Fy_harm
=
np
.
sum
(
Fy_harm
,
axis
=
1
)
# Integrate
rms
=
(
1.
/
self
.
N
*
dt
**
2
*
(
np
.
dot
(
Fx_harm
,
Fx_harm
)
+
np
.
dot
(
Fy_harm
,
Fy_harm
)))
**
0.5
self
.
X
=
self
.
X
-
Fx_harm
*
dt
self
.
Y
=
self
.
Y
-
Fy_harm
*
dt
# Energy
E
=
np
.
sum
(
0.5
*
self
.
H
*
(
dR
-
self
.
R0
)
**
2
)
print
"Step %d %+1.7e %+1.7e"
%
(
i
,
rms
,
E
)
# Trajectory
scale
=
100.
ofs
.
write
(
'%d
\n\n
'
%
(
self
.
N
))
for
i
in
range
(
self
.
N
):
if
'OR'
in
self
.
tags
[
i
]:
type_
=
'O'
else
:
type_
=
'C'
ofs
.
write
(
'%s %+1.7e %+1.7e 0.000
\n
'
%
(
type_
,
self
.
X
[
i
]
*
scale
,
self
.
Y
[
i
]
*
scale
))
ofs
.
close
()
return
self
.
X
,
self
.
Y
def
exclude_below_mass
(
self
,
m_th
):
self
.
have_excl
=
True
self
.
idcs_excl
=
np
.
where
(
self
.
M
<
m_th
)
self
.
idcs_noexcl
=
np
.
where
(
self
.
M
>=
m_th
)
def
constrain_above_mass
(
self
,
m_th
):
self
.
have_constr
=
True
self
.
idcs_constr
=
np
.
where
(
self
.
M
>
m_th
)
self
.
idcs_free
=
np
.
where
(
self
.
M
<=
m_th
)
def
constrain_below_mass
(
self
,
m_th
):
self
.
have_constr
=
True
self
.
idcs_constr
=
np
.
where
(
self
.
M
<
m_th
)
self
.
idcs_free
=
np
.
where
(
self
.
M
>=
m_th
)
def
integrate_md
(
self
,
n_steps
,
dt
,
append_traj
=
False
,
dn_out
=
1
,
rms_cut
=
1.e-5
):
ofs
=
open
(
'traj.xyz'
,
'a'
if
append_traj
else
'w'
)
gamma
=
1.
if
self
.
have_excl
:
print
"Noexcl"
,
self
.
idcs_noexcl
print
"Constrain"
,
self
.
idcs_constr
for
i
in
range
(
n_steps
):
# Compute distance matrix
dX
,
dY
,
dR
=
compute_dist_matrix_2d
(
self
.
X
,
self
.
Y
)
# Update H
self
.
H
.
fill
(
0.28
)
np
.
fill_diagonal
(
self
.
H
,
0.0
)
bool_D
=
np
.
zeros
(
self
.
R0
.
shape
,
dtype
=
'i4'
)
bool_R
=
np
.
zeros
(
dR
.
shape
,
dtype
=
'i4'
)
bool_D
[
np
.
where
(
self
.
R0
>
0.8
)]
=
1
bool_R
[
np
.
where
(
dR
>
0.8
)]
=
1
self
.
H
[
np
.
where
((
bool_D
+
bool_R
)
>
1
)]
=
0.0
# Compute forces
Fx_harm
=
self
.
H
*
(
dR
-
self
.
R0
)
*
dX
# Xij = xi-xj. Thus dR > R0 => Fij ~ -(xi-xj) is force experienced by j
Fy_harm
=
self
.
H
*
(
dR
-
self
.
R0
)
*
dY
# ... Exclusions
if
self
.
have_excl
:
Fx_harm
[:,
self
.
idcs_excl
]
=
0.0
Fy_harm
[:,
self
.
idcs_excl
]
=
0.0
# ... Sum pair forces
Fx_harm
=
np
.
sum
(
Fx_harm
,
axis
=
1
)
Fy_harm
=
np
.
sum
(
Fy_harm
,
axis
=
1
)
# Integrate
rms
=
(
1.
/
self
.
N
*
dt
**
2
*
(
np
.
dot
(
Fx_harm
,
Fx_harm
)
+
np
.
dot
(
Fy_harm
,
Fy_harm
)))
**
0.5
self
.
Vx
=
(
1.
-
gamma
*
dt
)
*
self
.
Vx
-
Fx_harm
*
dt
#/self.M
self
.
Vy
=
(
1.
-
gamma
*
dt
)
*
self
.
Vy
-
Fy_harm
*
dt
#/self.M
# ... Constraints
if
self
.
have_constr
:
self
.
Vx
[
self
.
idcs_constr
]
=
0.0
self
.
Vy
[
self
.
idcs_constr
]
=
0.0
delta_X
=
self
.
Vx
*
dt
delta_Y
=
self
.
Vy
*
dt
self
.
X
=
self
.
X
+
delta_X
self
.
Y
=
self
.
Y
+
delta_Y
rms
=
(
np
.
sum
(
delta_X
*
delta_X
+
delta_Y
*
delta_Y
)
/
self
.
N
)
**
0.5
rms_max
=
np
.
max
((
delta_X
*
delta_X
+
delta_Y
*
delta_Y
)
**
0.5
)
# Energy
if
self
.
have_excl
:
E
=
np
.
sum
(
0.5
*
self
.
H
[
self
.
idcs_noexcl
][:,
self
.
idcs_noexcl
]
*
(
dR
[
self
.
idcs_noexcl
][:,
self
.
idcs_noexcl
]
-
self
.
R0
[
self
.
idcs_noexcl
][:,
self
.
idcs_noexcl
])
**
2
)
else
:
E
=
np
.
sum
(
0.5
*
self
.
H
*
(
dR
-
self
.
R0
)
**
2
)
print
"Step %d %+1.7e/%+1.7e %+1.7e"
%
(
i
,
rms
,
rms_max
,
E
)
# Trajectory
if
i
%
dn_out
==
0
:
scale
=
100.
ofs
.
write
(
'%d
\n\n
'
%
(
self
.
N
))
for
i
in
range
(
self
.
N
):
if
'OR'
in
self
.
tags
[
i
]:
type_
=
'O'
else
:
type_
=
'C'
ofs
.
write
(
'%s %+1.7e %+1.7e 0.000
\n
'
%
(
type_
,
self
.
X
[
i
]
*
scale
,
self
.
Y
[
i
]
*
scale
))
if
rms
<
rms_cut
and
rms_max
<
rms_cut
:
print
"*** converged ***"
break
ofs
.
close
()
return
self
.
X
,
self
.
Y
def
dimred_matrix
(
method
,
kmat
=
None
,
distmat
=
None
,
outfile
=
None
,
ix
=
None
,
symmetrize
=
False
,
prj_dimension
=
2
):
dmat
=
distmat
if
symmetrize
:
if
type
(
kmat
)
!=
type
(
None
):
kmat
=
0.5
*
(
kmat
+
kmat
.
T
)
if
type
(
dmat
)
!=
type
(
None
):
dmat
=
0.5
*
(
dmat
+
dmat
.
T
)
if
type
(
d
ist
mat
)
!=
type
(
None
):
d
ist
mat
=
0.5
*
(
d
ist
mat
+
d
ist
mat
.
T
)
if
method
==
'mds'
:
# MDS
# http://scikit-learn.org/stable/modules/generated/sklearn.manifold.MDS.html#sklearn.manifold.MDS
...
...
@@ -58,31 +240,21 @@ def diffusion_map(kmat, n_components, alpha=0.5):
kmat_norm
=
kmat
/
kmat_diag
kmat_norm
=
kmat_norm
.
T
/
kmat_diag
np
.
fill_diagonal
(
kmat_norm
,
1.
)
#print kmat_norm
# Rescale kernel
D0
=
np
.
sum
(
kmat_norm
,
axis
=
1
)
D0_diag
=
np
.
zeros
(
kmat_norm
.
shape
)
np
.
fill_diagonal
(
D0_diag
,
D0
)
kmat_norm
=
kmat_norm
/
D0
**
alpha
kmat_norm
=
kmat_norm
.
T
/
D0
**
alpha
#print kmat_norm
# Form Markov matrix
D1
=
np
.
sum
(
kmat_norm
,
axis
=
1
)
kmat_norm
=
(
kmat_norm
/
D1
).
T
#print kmat_norm
#print np.sum(kmat_norm, axis=1)
# Decompose
import
scipy.sparse
evals
,
evecs
=
scipy
.
sparse
.
linalg
.
eigs
(
kmat_norm
,
n_components
+
1
,
which
=
"LM"
)
order
=
evals
.
argsort
()[::
-
1
]
evals
=
evals
[
order
]
evecs
=
evecs
.
T
[
order
].
T
#print evals
#print evecs
# Project
return
kmat_norm
.
dot
(
evecs
[:,
1
:])
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment