Disabled external gits

This commit is contained in:
2022-04-07 18:46:57 +02:00
parent 88cb3426ad
commit 15e7120d6d
5316 changed files with 4563444 additions and 6 deletions

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 67 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,188 @@
from energies import *
from optimization import compute_optimization_objective, compute_optimization_objective_gradient
from linesearch import *
import numpy as np
import time
import igl
def compute_approximate_hessian_matrix(sk, yk, B_prev):
"""
Compute the approximated hessian matrix
Input:
- s_k : np.array(#V * 2, 1)
s_k = x_{k+1} - x_{k}, the difference in variables at two consecutive iterations.
Note that x_{k} is the vertices' coordinate V at the k-th iteration.
The vertices' cooridnate V however is a np.array(#V, 3)
We use x_{k} = V[:, 0 : 2].flatten() to flatten the vertices coordinartes.
- y_k : np.array(#V * 2, 1)
y_k = grad(f(x_{k+1})) - grad(f(x_{k})),
the difference in function gradient at two consecutive iterations.
The grad(f(x_{k})) is the gradient of our objective energy,
which is a np.array(#V, 2)
To be used for BFGS, we flatten the gradient.
The flatten process asks the all x coordinates to be first
then all y cooridnates to be the second.
- B_prev: np.array(#V * 2, #V * 2)
The approximated hessian matrix from last iteration
Output
-B_new: np.array(#V * 2, #V * 2)
The approximated hessian matrix of current iteration
"""
a = (yk @ yk.T)/(yk.T @ sk)
bt = B_prev @ sk @ sk.T @ B_prev.T
bb = sk.T @ B_prev @ sk
B_new = B_prev + a - bt/bb
return B_new
def compute_inverse_approximate_hessian_matrix(sk, yk, invB_prev):
"""
Compute the inverse approximated hessian matrix
Input:
- s_k : np.array(#V * 2, 1)
s_k = x_{k+1} - x_{k}, the difference in variables at two consecutive iterations.
Note that x_{k} is the vertices' coordinate V at the k-th iteration.
The vertices' cooridnate V however is a np.array(#V, 3)
We use x_{k} = V[:, 0 : 2].flatten() to flatten the vertices coordinartes.
- y_k : np.array(#V * 2, 1)
y_k = grad(f(x_{k+1})) - grad(f(x_{k})),
the difference in function gradient at two consecutive iterations.
The grad(f(x_{k})) is the gradient of our objective energy,
which is a np.array(#V, 2)
To be used for BFGS, we flatten the gradient.
The flatten process asks the all x coordinates to be first
then all y cooridnates to be the second.
- invB_prev: np.array(#V * 2, #V * 2)
The inversed matrix of the approximated hessian from last iteration
Output
- invB_new: np.array(#V * 2, #V * 2)
The inversed matrix of the approximated hessian at current iteration
"""
d = sk.T @ yk
e = invB_prev @ yk
a = (d + (yk.T @ e)) * (sk @ sk.T)/(d * d)
b = ((e @ sk.T) + ((sk @ yk.T) @ invB_prev))/d
invB_new = invB_prev + a - b
return invB_new
def bfgs_with_line_search(V, F, x_csl, w, obj_tol, theta, beta, c, iter):
"""
Find equilibrium shape by using BFGS method
Input:
- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (#F, 3)
The array of triangle faces.
- x_csl : float
The x coordinate of the center of the support line.
- w : float
The weight for shape preservation energy.
- obj_tol: float
The termination condition for optimization.
The program stop running if
the absolute different between the objectives of two consecutive iterations is smaller than obj_tol
- theta : float
The initial gradient descent step size.
- beta : float
The backtracking ratio, alpha = beta * alpha
- c: float
The coefficient for armijo condition
- iter : int
The number of iteration for gradient descent.
Output:
- V1 : np.array (#V, 3)
The optimized mesh's vertices
- F : np.array (#F, 3)
The array of triangle faces.
- energy: np.array(iters, 1)
The objective function energy curve with respect to the number of iterations.
- running_time: float
The tot running time of the optimization
"""
V1 = V.copy()
# this function of libigl returns an array (#edges, 2) where i-th row
# contains the indices of the two vertices of i-th edge.
E = igl.edges(F)
fix = np.where(V1[:, 1] < 1e-3)[0]
L0 = compute_edges_length(V1, E)
t0 = time.time()
energy = []
obj_prev = 0
it_time = 0
gradprev= None
vprev = V1
Hprev = np.identity(V.shape[0]*2)/theta
while (True):
# energy
obj = compute_optimization_objective(V1, F, E, x_csl, L0, w)
if abs(obj_prev - obj) < obj_tol:
break
if it_time > iter:
break
obj_prev = obj
energy.append(obj)
grad = compute_optimization_objective_gradient(V1, F, E, x_csl, L0, w)
grad[fix] = 0
if gradprev is None:
gradprev = grad
### start of your code.
gradf = grad.flatten()
ff = F.flatten()
vf = V[:, 0 : 2].flatten()
unflatten = lambda x: np.concatenate((np.reshape(x,(V.shape[0],2)),np.zeros((V.shape[0],1))),axis=-1)
f = lambda x: compute_optimization_objective(unflatten(x), F, E, x_csl, L0, w)
alpha = backtracking_line_search(-gradf, gradf, vf, theta, beta, c, f)
x_cm = compute_mesh_centroid(V, F)[0]
HV = (V1 - vprev)[:,:2].flatten()[:,None]
HG = (grad-gradprev).flatten()[:,None]
Hcur = compute_inverse_approximate_hessian_matrix(HV, HG, Hprev)
d = np.concatenate((np.reshape(Hcur @ gradf,(V.shape[0],2)),np.zeros((V.shape[0],1))),axis=-1)
vprev = V1
gradprev = grad
Hprev = Hcur
V1 = V1 - (alpha * d)
### end of your code.
it_time = it_time + 1
running_time = time.time() - t0
return [V1, F, energy, running_time]

View File

@@ -0,0 +1,244 @@
import numpy as np
from scipy import sparse
# -----------------------------------------------------------------------------
# Functions from assignment_1_1
# -----------------------------------------------------------------------------
from geometry import compute_mesh_centroid
from geometry import compute_faces_centroid
from geometry import compute_faces_area
# -----------------------------------------------------------------------------
# Provided functions
# -----------------------------------------------------------------------------
def vertex_cells_sum(values, cells):
"""
Sums values at vertices from each incident n-cell.
Input:
- values : np.array (#cells,) or (#cells, n)
The cell values to be summed at vertices.
If shape (#cells,): The value is per-cell,
If shape (#cells, n): The value refers to the corresponding cell vertex.
- cells : np.array (#cells, n)
The array of cells.
Output:
- v_sum : np.array (#vertices,)
A vector with the sum at each i-th vertex in i-th position.
Note:
If n = 2 the cell is an edge, if n = 3 the cell is a triangle,
if n = 4 the cell can be a tetrahedron or a quadrilateral, depending on
the data structure.
"""
i = cells.flatten('F')
j = np.arange(len(cells))
j = np.tile(j, cells.shape[1])
v = values.flatten('F')
if len(v) == len(cells):
v = v[j]
v_sum = sparse.coo_matrix((v, (i, j)), (np.max(cells) + 1, len(cells)))
return np.array(v_sum.sum(axis=1)).flatten()
def compute_edges_length(V, E):
"""
Computes the edge length of each mesh edge.
Input:
- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- E : np.array (#edges, 2)
The array of mesh edges.
generated from the function E = igl.edges(F)
returns an array (#edges, 2) where i-th row contains the indices of the two vertices of i-th edge.
Output:
- l : np.array (#edges,)
The edge lengths.
"""
l = np.linalg.norm(V[E[:, 0]] - V[E[:, 1]], axis=1)
return l
# -----------------------------------------------------------------------------
# 2.5.1 Target energies
# -----------------------------------------------------------------------------
def compute_equilibrium_energy(V, F, x_csl):
"""
Computes the equilibrium energy E_eq = 1/2*(x_cm - x_csl)^2.
Input:
-- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (#F, 3)
The array of triangle faces.
- x_csl : float
The x coordinate of the center of the support line.
Output:
- E_eq : float
the equilibrium energy of the mesh with respect to the target centroid
x_csl.
"""
x_cm = compute_mesh_centroid(V,F)[0]
E_eq = 0.5 * (x_cm - x_csl)**2
return E_eq
def compute_shape_energy(V, E, L):
"""
Computes the energy E_sh = 1/2 sum_e (l_e - L_e)^2 in the current
configuration V, where l_e is the length of mesh edges, and L_e the
corresponding length in the undeformed configuration.
Input:
- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- E : np.array (#edges, 2)
The array of mesh edges.
- L : np.array (#edges,)
The rest lengths of mesh edges.
Output:
- E_sh : float
The energy E_sh in the current configuration V.
"""
l = compute_edges_length(V,E)
Lf = np.array(L)
e_vec = np.arange(len(E))
ldiff = (l[e_vec]-Lf[e_vec])**2
E_sh = 0.5 * np.sum(ldiff)
return E_sh
# -----------------------------------------------------------------------------
# 2.5.2 Faces area gradient
# -----------------------------------------------------------------------------
def compute_faces_area_gradient(V, F):
"""
Computes the gradient of faces area.
Input:
- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (#F, 3)
The array of triangle faces.
Output:
- dA_x : np.array (#F, 3)
The gradient of faces areas A_i with respect to the x coordinate of each
face vertex x_1, x_2, and x_3, with (i,0) = dA_i/dx_1, (i,1) = dA_i/dx_2,
and (i,2) = dA_i/dx_3.
- dA_y : np.array (#F, 3)
The gradient of faces areas A_i with respect to the y coordinate of each
face vertex y_1, y_2, and y_3, with (i,0) = dA_i/dy_1, (i,1) = dA_i/dy_2,
and (i,2) = dA_i/dy_3.
"""
grad = lambda a,b: (V[a]-V[b])
gradABC = lambda fi: [grad(fi[2],fi[1]),grad(fi[0],fi[2]),grad(fi[1],fi[0])]
dA = np.apply_along_axis(gradABC,1,F)/2
dA_x = -dA[:,:,1]
dA_y = dA[:,:,0]
return dA_x, dA_y
# -----------------------------------------------------------------------------
# 2.5.3 Equilibrium energy gradient
# -----------------------------------------------------------------------------
def compute_equilibrium_energy_gradient(V, F, x_csl):
"""
Computes the gradient of the energy E_eq = 1/2*(x_cm - x_csl)^2 with respect
to the x and y coordinates of each vertex, where x_cm is the x coordinate
of the area centroid and x_csl x coordinate of the center of the support
line.
Input:
- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (#F, 3)
The array of triangle faces.
- x_csl : float
The x coordinate of the center of the support line.
Output:
- grad_E_eq : np.array (#V, 2)
The gradient of the energy E_eq with respect to vertices v_i,
with (i, 0) = dE_eq/dx_i and (i, 1) = dE_eq/dy_i
"""
cm = compute_mesh_centroid(V,F)
x_cm = cm[0]
x_f = compute_faces_centroid(V,F)
A_f = compute_faces_area(V,F)
A_f_V_nonp = compute_faces_area_gradient(V, F)
A_f_V = np.stack(A_f_V_nonp,axis=-1)
A_omega = np.sum(A_f)
xfact = (x_cm - x_csl)/A_omega
xfV = lambda v: np.apply_along_axis(lambda x: np.array([1/3,0.0]) if np.any(x[:]==v) else np.zeros((2)),1,F)
AfV = lambda v: (np.where(F[:,0][:,None]==v,A_f_V[:,0,:2],
np.where(F[:,1][:,None]==v,A_f_V[:,1,:2],
np.where(F[:,2][:,None]==v,A_f_V[:,2,:2],np.zeros((F.shape[0],2))) )) )
cf = lambda v : AfV(v)*(x_f[:,0] - x_cm)[:, None] + (A_f[:, None]*xfV(v))
#v_vec = np.arange(len(V))
#veq = np.sum(cf(v_vec),axis=0)*xfact
veq = np.array([np.sum(cf(v),axis=0) for v in range(0,len(V))])*xfact
return veq
# -----------------------------------------------------------------------------
# 2.5.4 Shape energy gradient
# -----------------------------------------------------------------------------
def compute_shape_energy_gradient(V, E, L):
"""
Computes the gradient of the energy E_sh = 1/2 sum_e (l_e - L_e)^2 with
respect to the x and y coordinates of each vertex, where l_e is the length
of mesh edges, and L_e the corresponding length in the undeformed
configuration.
Input:
- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- E : np.array (#edges, 2)
The array of mesh edges.
- L : np.array (#edges,)
The rest lengths of mesh edges.
Output:
- grad_E_sh : np.array (#V, 2)
The gradient of the energy E_sh with respect to vertices v_i,
with (i, 0) = dE_sh/dx_i, (i, 1) = dE_sh/dy_i
"""
vdif = lambda ee0, ee1: (V[ee0]-V[ee1])[:,:2]
len_e_d = vdif(E[:,0],E[:,1])
len_e = np.linalg.norm(len_e_d, axis=1)
len_e_t = lambda v: (np.where(E[:,0][:,None]==v,len_e_d[:],
np.where(E[:,1][:,None]==v,-len_e_d[:],np.zeros(E.shape))))
veq = np.sum(np.array([len_e_t(v) for v in range(0,len(V))]),axis=1) - np.sum(L/len_e,axis=0)
return veq

View File

@@ -0,0 +1,100 @@
import numpy as np
def compute_faces_area(V, F):
"""
Computes the area of the faces of a given triangle mesh (V, F).
Input:
- V : np.array (|V|, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (|F|, 3)
The array of triangle faces.
Output:
- area : np.array (|F|,)
The area of the faces. The i-th position contains the area of the i-th
face.
"""
# HW.1.3.3
return np.linalg.norm(np.cross(V[F[:,1]] - V[F[:,0]],V[F[:,2]] - V[F[:,0]], axis=1), axis=1)/2.0
def compute_mesh_area(V, F):
"""
Computes the area of a given triangle mesh (V, F).
Input:
- V : np.array (|V|, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (|F|, 3)
The array of triangle faces.
Output:
- area : float
The area of the mesh.
"""
# HW.1.3.3
return np.sum(compute_faces_area(V,F))
def compute_faces_centroid(V, F):
"""
Computes the area centroid of each face of a given triangle mesh (V, F).
Input:
- V : np.array (|V|, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (|F|, 3)
The array of triangle faces.
Output:
- cf : np.array (|F|, 3)
The area centroid of the faces.
"""
# HW.1.3.4
return (V[F[:,0]]+ V[F[:,1]] + V[F[:,2]])/3.0
def compute_mesh_centroid(V, F):
"""
Computes the area centroid of a given triangle mesh (V, F).
Input:
- V : np.array (|V|, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (|F|, 3)
The array of triangle faces.
Output:
- centroid : np.array (3,)
The area centroid of the mesh.
"""
# HW.1.3.4
face_centroid = compute_faces_centroid(V,F)
face_area = compute_faces_area(V,F)
return 1.0/np.sum(face_area) * np.sum(np.einsum('i,ij->ij', face_area, face_centroid), axis=0)
def compute_center_support_line(V):
"""
Computes the x coordinate of the center of the support line
Input:
- V : np.array (|V|, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
Output:
- x_csl : float
the x coordinate of the center of the support line
"""
# HW.1.3.5
support_v = np.fromiter((v[0] for v in V if v[1]<10**-5), dtype=V.dtype)
x_csl = np.amin(support_v)+(np.amax(support_v)-np.amin(support_v))/2
return x_csl

View File

@@ -0,0 +1,173 @@
from energies import *
from optimization import compute_optimization_objective, compute_optimization_objective_gradient
import numpy as np
import time
import igl
def evaluate_armijo_rule(f_x, f_x1, p, grad, c, alpha):
"""
Check the armijo rule, return true if the armijo condition is satisfied
Input:
- f_x : float
The function value at x
- f_x1 : float
The function value at x_(k+1) = x_k + alpha * p_k
- p: np.array(2 * #V, 1)
The flatten search direction
Here, we use the flatten the search direction.
The flatten process asks the all x coordinates to be first
then all y cooridnates to be the second.
- grad: np.array(2 * #V, 1)
The gradient of the function at x
Here, we use the flatten the gradient
The flatten process asks the all x coordinates to be first
then all y cooridnates to be the second.
- c: float
The coefficient for armijo condition
- alpha: float
The current step size
Output:
- condition: bool
True if the armijio condition is satisfied
"""
return f_x1 <= f_x + c*alpha*np.dot(p.T,grad)
def backtracking_line_search(p, grad, x, theta, beta, c, f, *arg):
"""
Computes the step size for p that satisfies the armijio condition.
Input:
- p: np.array(2 * #V, 1)
The flatten search direction
Here, we use the flatten the search direction.
The flatten process asks the all x coordinates to be first
then all y cooridnates to be the second.
- grad: np.array(2 * #V, 1)
The gradient of the function at x
Here, we use the flatten the gradient
The flatten process asks the all x coordinates to be first
then all y cooridnates to be the second.
- x : np.array(#V * 2, 1)
The array of optimization variables
x = V[:, 0 : 2].flatten()
- theta: float
The initial step size
- beta : float
The backtracking ratio, alpha = beta * alpha
- c: float
The coefficient for armijo condition
- f: function
The objective function (i.e., optimization.compute_optimization_objective)
- *arg: parameters
The rest parameters for the function f except the its first variables Vx
Output:
- alpha: float
The step size for p that satisfies the armijio condition
"""
alpha = theta
x1 = x + alpha*p
while not evaluate_armijo_rule(f(x,*arg),f(x1, *arg), p, grad, c, alpha):
alpha = beta*alpha
x1 = x+alpha*p
return alpha
def gradient_descent_with_line_search(V, F, x_csl, w, obj_tol, theta, beta, c, iter):
"""
Find equilibrium shape by using gradient descent with backtracking line search
Input:
- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row.
- F : np.array (#F, 3)
The array of triangle faces.
- x_csl : float
The x coordinate of the center of the support line.
- w : float
The weight for shape preservation energy.
- obj_tol: float
The termination condition for optimization.
The program stop running if
the absolute difference between the objectives of two consecutive iterations is smaller than obj_tol
- theta : float
The initial gradient descent step size.
- beta : float
The backtracking ratio, alpha = beta * alpha
- c: float
The coefficient for armijo condition.
- iter : int
The maximum number of iteration for gradient descent.
Output:
- V1 : np.array (#V, 3)
The optimized mesh's vertices
- F : np.array (#F, 3)
The array of triangle faces.
- energy: np.array(iters, 1)
The objective function energy curve with respect to the number of iterations.
- running_time: float
The tot running time of the optimization
"""
V1 = V.copy()
# this function of libigl returns an array (#edges, 2) where i-th row
# contains the indices of the two vertices of i-th edge.
E = igl.edges(F)
fix = np.where(V1[:, 1] < 1e-3)[0]
L0 = compute_edges_length(V1, E)
t0 = time.time()
energy = []
obj_prev = 0
it_time = 0
while(True):
# energy
obj = compute_optimization_objective(V1, F, E, x_csl, L0, w)
if abs(obj_prev - obj) < obj_tol:
break
if it_time > iter:
break
obj_prev = obj
energy.append(obj)
grad = compute_optimization_objective_gradient(V1, F, E, x_csl, L0, w)
grad[fix] = 0
### start of your code.
gradf = grad.flatten()
ff = F.flatten()
vf = V[:, 0 : 2].flatten()
unflatten = lambda x: np.concatenate((np.reshape(x,(V.shape[0],2)),np.zeros((V.shape[0],1))),axis=-1)
f = lambda x: compute_optimization_objective(unflatten(x), F, E, x_csl, L0, w)
alpha = backtracking_line_search(-gradf, gradf, vf, theta, beta, c, f)
x_cm = compute_mesh_centroid(V, F)[0]
grad_f = np.zeros((np.shape(grad)[0],3))
grad_f[:,:-1] = grad
V1 = V1 -(alpha * grad_f)
### end of your code.
it_time = it_time + 1
running_time = time.time() - t0
return [V1, F, energy, running_time]

View File

@@ -0,0 +1,137 @@
from energies import compute_edges_length
from energies import compute_equilibrium_energy_gradient, compute_equilibrium_energy
from energies import compute_shape_energy_gradient, compute_shape_energy
from geometry import compute_mesh_centroid
import numpy as np
import time
import igl
def compute_optimization_objective(V, F, E, x_csl, L0, w):
"""
Compute the objective function of make-it-stand problem.
E = E_equilibrium + w * E_shape
Input:
- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (#F, 3)
The array of triangle faces.
- E : np.array (#edges, 2)
The array of mesh edges.
- x_csl : float
The x coordinate of the center of the support line.
- L0 : np.array (#edges,)
The rest lengths of mesh edges.
- w : float
The weight for shape preservation energy.
Output:
- obj : float
The value of the objective function.
"""
E_eq = compute_equilibrium_energy(V, F, x_csl)
E_sh = compute_shape_energy(V, E, L0)
obj = E_eq + w*E_sh
return obj
def compute_optimization_objective_gradient(V, F, E, x_csl, L0, w):
"""
Compute the gradient of the objective function of make-it-stand problem.
D_E = D_E_equilibrium + w * D_E_shape
Input:
- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (#F, 3)
The array of triangle faces.
- E : np.array (#edges, 2)
The array of mesh edges.
- x_csl : float
The x coordinate of the center of the support line.
- l0 : np.array (#edges,)
The rest lengths of mesh edges.
- w : float
The weight for shape preservation energy.
Output:
- grad_obj : np.array (#V, 2)
The gradient of objective function.
"""
grad_E_eq = compute_equilibrium_energy_gradient(V, F, x_csl)
grad_E_sh = compute_shape_energy_gradient(V, E, L0)
grad_obj = grad_E_eq + w * grad_E_sh
return grad_obj
def fixed_step_gradient_descent(V, F, x_csl, w, theta, iters):
"""
Find equilibrium shape by using fixed step gradient descent method
Input:
- V : np.array (#V, 3)
The array of vertices positions.
Contains the coordinates of the i-th vertex in i-th row
- F : np.array (#F, 3)
The array of triangle faces.
- x_csl : float
The x coordinate of the center of the support line.
- w : float
The weight for shape preservation energy.
- theta : float
The optimization step.
- iters : int
The number of iteration for gradient descent.
Output:
- V1 : np.array (#V, 3)
The optimized mesh's vertices
- F : np.array (#F, 3)
The array of triangle faces.
- energy: np.array(iters, 1)
The objective function energy curve with respect to the number of iterations.
- running_time: float
The tot running time of the optimization
"""
V1 = V.copy()
# this function of libigl returns an array (#edges, 2) where i-th row
# contains the indices of the two vertices of i-th edge.
E = igl.edges(F)
fix = np.where(V1[:, 1] < 1e-3)[0]
L0 = compute_edges_length(V1, E)
t0 = time.time()
energy = []
for i in range(iters):
grad = compute_optimization_objective_gradient(V1, F, E, x_csl, L0, w)
obj = compute_optimization_objective(V1, F, E, x_csl, L0, w)
energy.append(obj)
grad[fix] = 0
### start of your code.
x_cm = compute_mesh_centroid(V, F)[0]
if abs(x_csl - x_cm)<=10**-3:
break
if (np.linalg.norm(grad)<=10**-3):
break
grad_f = np.zeros((np.shape(grad)[0],3))
grad_f[:,:-1] = grad
V1 = V1 -(theta * grad_f)
### end of your code.
running_time = time.time() - t0
return [V1, F, energy, running_time]

View File

@@ -0,0 +1,45 @@
import numpy as np
import cv2 as cv
import triangle as tr
def triangulate_mesh(Ps, Holes, area_density):
'''
Triangulates a set of points given by P using Delaunay scheme
Input:
- P : list of N lists of 2 elements giving the vertices positions
- Holes: list of M lists of 2 elements giving the holes positions
- area_density: the maximum triangle area
Output:
- V : array of shape (nNodes, 3) containing the vertices position
- F : array of vertices ids (list of length nTri of lists of length 3). The ids are such that the algebraic area of
each triangle is positively oriented
'''
num_points = 0
points = []
segments = []
for k, _ in enumerate(Ps):
P = np.array(Ps[k])
N = P.shape[0]
points.append(P)
index = np.arange(N)
seg = np.stack([index, index + 1], axis=1) % N + num_points
segments.append(seg)
num_points += N
points = np.vstack(points)
segments = np.vstack(segments)
data = []
if Holes == [] or Holes == [[]] or Holes == None:
data = dict(vertices=points, segments=segments)
else:
data = dict(vertices=points, segments=segments, holes = Holes)
tri = tr.triangulate(data, 'qpa{}'.format(area_density))
V = np.array([[v[0], v[1], 0] for v in tri["vertices"]])
F = np.array([[f[0], f[1], f[2]] for f in tri["triangles"]])
return [V, F]

View File

@@ -0,0 +1,67 @@
# import pytest
import time
import pytest
import json
import sys
import igl
import numpy as np
sys.path.append('../')
sys.path.append('../src')
from src.energies import *
from src.linesearch import *
from src.bfgs import *
eps = 1E-6
with open('test_data3.json', 'r') as infile:
homework_datas = json.load(infile)
@pytest.mark.timeout(1)
@pytest.mark.parametrize("data", homework_datas[0])
def test_armijo_rule(data):
Fx = data[0]
Fy = data[1]
p = np.array(data[2], dtype=float)
grad = np.array(data[3], dtype=float)
c = data[4]
alpha = data[5]
armijo_rule_ground_truth = data[6]
armijo_rule_student = int(evaluate_armijo_rule(Fx, Fy, p, grad, c, alpha))
assert armijo_rule_ground_truth == armijo_rule_student
def func(x):
return np.linalg.norm(x) ** 2
@pytest.mark.timeout(1)
@pytest.mark.parametrize("data", homework_datas[1])
def test_backtracking_line_search(data):
p = np.array(data[0], dtype=float)
grad = np.array(data[1], dtype=float)
x = np.array(data[2], dtype=float)
theta = data[3]
beta = data[4]
c = data[5]
backtracking_line_search_ground_truth = data[6]
backtracking_line_search_student = backtracking_line_search(p, grad, x, theta, beta, c, func)
assert np.linalg.norm(backtracking_line_search_ground_truth - backtracking_line_search_student) < eps
@pytest.mark.timeout(1)
@pytest.mark.parametrize("data", homework_datas[2])
def test_compute_approximate_hessian_matrix(data):
sk = np.array(data[0], dtype=float)
yk = np.array(data[1], dtype=float)
Bk = np.array(data[2], dtype=float)
newBk_student = compute_approximate_hessian_matrix(sk, yk, Bk)
newBk_ground_truth = np.array(data[3], dtype=float)
assert np.linalg.norm(newBk_student - newBk_ground_truth) < eps
@pytest.mark.timeout(1)
@pytest.mark.parametrize("data", homework_datas[3])
def test_compute_inverse_approximate_hessian_matrix(data):
sk = np.array(data[0], dtype=float)
yk = np.array(data[1], dtype=float)
invBk = np.array(data[2], dtype=float)
inv_newBk_student = compute_inverse_approximate_hessian_matrix(sk, yk, invBk)
inv_newBk_ground_truth = np.array(data[3], dtype=float)
assert np.linalg.norm(inv_newBk_student - inv_newBk_ground_truth) < eps

View File

@@ -0,0 +1 @@
[[[2.0000000000000004, 2.0000000000000004, [-2, -2], [2, 2], 0.5, 1.0, 0], [2.0000000000000004, 0.0, [-2, -2], [2, 2], 0.5, 0.5, 1]], [[[-2, -2], [2, 2], [1, 1], 2.1, 0.5, 0.5, 0.2625]], [[[[-2.0], [-2.0]], [[-4.0], [-4.0]], [[1.0, 0.0], [0.0, 1.0]], [[1.5, 0.5], [0.5, 1.5]]]], [[[[-2.0], [-2.0]], [[-4.0], [-4.0]], [[1.0, 0.0], [0.0, 1.0]], [[0.75, -0.25], [-0.25, 0.75]]]]]