def face_of_span(S): """ Returns the face matrix S^F of the span matrix S, that is, a matrix such that {x = S z, z >= 0} if and only if {S^F x <= 0}. """ V = hstack([zeros((S.shape[1], 1)), S.T]) # V-representation: first column is 0 for rays V_cdd = Matrix(V, number_type="float") V_cdd.rep_type = RepType.GENERATOR P = Polyhedron(V_cdd) ineq = P.get_inequalities() H = array(ineq) if H.shape == (0,): # H = [] return H # b, A = H[:, 0], -H[:, 1:] # H matrix is [b, -A] A = [] for i in xrange(H.shape[0]): if H[i, 0] != 0: # b should be zero raise NotConeSpan(S) elif i not in ineq.lin_set: A.append(-H[i, 1:]) return array(A)
def cone_span_to_face(S, eliminate_redundancies=False): """ Returns the face matrix S^F of the span matrix S, that is, a matrix such that {x = S z, z >= 0} if and only if {S^F x <= 0}. """ V = hstack([zeros((S.shape[1], 1)), S.T]) # V-representation: first column is 0 for rays V_cdd = Matrix(V, number_type=NUMBER_TYPE) V_cdd.rep_type = RepType.GENERATOR P = Polyhedron(V_cdd) H_matrix = P.get_inequalities(); if(eliminate_redundancies): H_matrix.canonicalize(); H = array(H_matrix); if(H.shape[1]>1): b = H[:, 0] A = H[:, 1:] else: b, A = H[:, 0], zeros((H.shape[0],S.shape[0])); for i in xrange(H.shape[0]): if b[i] != 0: raise NotConeSpan(S) return -A
def discard_redundant(self): """Remove redundant elements from the credal set Redundant elements are those that are not vertices of the credal set's convex hull. >>> K = CredalSet('abc') >>> K.add({'a': 1, 'b': 1, 'c': 1}) >>> assert ( ... K == ... CredalSet( ... {PMFunc({'a': '1/3', 'c': '1/3', 'b': '1/3'}), ... PMFunc({'a': 1}), PMFunc({'b': 1}), PMFunc({'c': 1})} ... ) ... ) >>> K.discard_redundant() >>> assert ( ... K == ... CredalSet( ... {PMFunc({'a': 1}), PMFunc({'b': 1}), PMFunc({'c': 1})}) ... ) """ pspace = list(self.pspace()) K = list(self) mat = Matrix(list([1] + list(p[x] for x in pspace) for p in K), number_type='fraction') mat.rep_type = RepType.GENERATOR lin, red = mat.canonicalize() for i in red: self.discard(K[i])
def cone_span_to_face(S, eliminate_redundancies=False): """ Returns the face matrix S^F of the span matrix S, that is, a matrix such that {x = S z, z >= 0} if and only if {S^F x <= 0}. """ V = hstack([ones((S.shape[1], 1)), S.T]) # V-representation: first column is 0 for rays V_cdd = Matrix(V, number_type=NUMBER_TYPE) V_cdd.rep_type = RepType.GENERATOR P = Polyhedron(V_cdd) H_matrix = P.get_inequalities() if (eliminate_redundancies): H_matrix.canonicalize() H = array(H_matrix) if (H.shape[1] > 1): b = H[:, 0] A = H[:, 1:] else: b, A = H[:, 0], zeros((H.shape[0], S.shape[0])) #~ for i in xrange(H.shape[0]): #~ if b[i] != 0: #~ raise NotConeSpan(S) return -A, b
def vf_enumeration(data=[]): """Perform vertex/facet enumeration :type `data`: an argument accepted by the :class:`~murasyp.vectors.Polytope` constructor. :returns: the vertex/facet enumeration of the polytope (assumed to be in facet/vertex-representation) :rtype: a :class:`~murasyp.vectors.Polytope` """ vf_poly = Polytope(data) coordinates = list(vf_poly.domain()) mat = Matrix(list([0] + [vector[x] for x in coordinates] for vector in vf_poly), number_type='fraction') mat.rep_type = RepType.INEQUALITY poly = Polyhedron(mat) ext = poly.get_generators() fv_poly = Polytope([{coordinates[j-1]: ext[i][j] for j in range(1, ext.col_size)} for i in range(0, ext.row_size)] + [{coordinates[j-1]: -ext[i][j] for j in range(1, ext.col_size)} for i in ext.lin_set]) return fv_poly
def span_of_face(F): """ Compute the span matrix F^S of the face matrix F, that is, a matrix such that {F x <= 0} if and only if {x = F^S z, z >= 0}. """ b, A = zeros((F.shape[0], 1)), F # H-representation: b - A x >= 0 # ftp://ftp.ifor.math.ethz.ch/pub/fukuda/cdd/cddlibman/node3.html # the input to pycddlib is [b, -A] F_cdd = Matrix(hstack([b, -A]), number_type="float") F_cdd.rep_type = RepType.INEQUALITY P = Polyhedron(F_cdd) g = P.get_generators() V = array(g) rays = [] for i in xrange(V.shape[0]): if V[i, 0] != 0: # 1 = vertex, 0 = ray raise NotConeFace(F) elif i not in g.lin_set: rays.append(V[i, 1:]) return array(rays).T
def eliminate_redundant_inequalities(A,b): # H-representation: A x + b >= 0 A_plot = Matrix(hstack([b.reshape((A.shape[0],1)), -A]), number_type=NUMBER_TYPE) A_plot.rep_type = RepType.INEQUALITY A_plot.canonicalize() A_plot = np.array(A_plot) b_plot, A_plot = A_plot[:, 0], -A_plot[:, 1:] return (A_plot, b_plot);
def eliminate_redundant_inequalities(A,b): ''' Input format is A x + b <= 0''' # H-representation: A x + b >= 0 A_plot = Matrix(hstack([-b.reshape((A.shape[0],1)), -A]), number_type=NUMBER_TYPE) A_plot.rep_type = RepType.INEQUALITY A_plot.canonicalize() A_plot = np.array(A_plot) b_plot, A_plot = -A_plot[:, 0], -A_plot[:, 1:] return (A_plot, b_plot);
def make_hrep(lhs, rhs, num_type='fraction'): """Create an H-representation cdd.Matrix The `lhs` input list of lists should have element lists of equal length and integer values; the `rhs` list should have length equal to `lhs` and integer values. """ mat = Matrix(lhs_rhs2constraints(lhs, rhs), number_type=num_type) mat.rep_type = RepType.INEQUALITY return mat
def make_vrep(points, rays, num_type='fraction'): """Create a V-representation cdd.Matrix The suggestively named input lists of lists should have element lists of equal length and integer values. """ for pointlist in points: pointlist.insert(0, 1) for raylist in rays: raylist.insert(0, 0) mat = Matrix(points + rays, number_type=num_type) mat.rep_type = RepType.GENERATOR return mat
def poly_span_to_face(S): """ Returns the face matrix S^F of the span matrix S, that is, a matrix such that {x = S z, z >= 0, sum(z)=1} if and only if {S^F x <= s}. """ V = hstack([ones((S.shape[1], 1)), S.T]) # V-representation: first column is 0 for rays, 1 for vertices V_cdd = Matrix(V, number_type=NUMBER_TYPE) V_cdd.rep_type = RepType.GENERATOR P = Polyhedron(V_cdd) H = array(P.get_inequalities()) # H-representation: A x + b >= 0 b, A = H[:, 0], H[:, 1:] return (-A,b)
def poly_span_to_face(S): """ Returns the face matrix S^F of the span matrix S, that is, a matrix such that {x = S z, z >= 0, sum(z)=1} if and only if {S^F x <= s}. """ V = hstack([ones((S.shape[1], 1)), S.T]) # V-representation: first column is 0 for rays, 1 for vertices V_cdd = Matrix(V, number_type=NUMBER_TYPE) V_cdd.rep_type = RepType.GENERATOR P = Polyhedron(V_cdd) H = array(P.get_inequalities()) # H-representation: A x + b >= 0 b, A = H[:, 0], H[:, 1:] return (-A, b)
def get_coh_hrep_via_vreps(K, num_type='fraction'): """Compute a minimal H-representation for coherence See Procedure C.1 in my ISIPTA '13 paper “Characterizing coherence, correcting incoherence”. """ vrep = generate_asl_vrep(K, num_type) hreplist = [Polyhedron(vrep).get_inequalities()] for i in xrange(len(K)): vrep = generate_Sasl_vrep(K, i, num_type) hreplist.append(Polyhedron(vrep).get_inequalities()) constraints = ([list(t) for t in hrep[:]] for hrep in hreplist) constraintslist = list(chain.from_iterable(constraints)) hrep = Matrix(constraintslist, number_type=num_type) hrep.rep_type = RepType.INEQUALITY hrep.canonicalize() return hrep
def arbitrary_face_to_span(F, f): """ Compute the span matrix F^S of the face matrix F, that is, a matrix such that {F x <= f} if and only if {x = F^S z, z >= 0, sum(z)=1}. Works for both polytopes and cones. """ b, A = f.reshape((F.shape[0], 1)), -F # H-representation: A x + b >= 0 F_cdd = Matrix(hstack([b, A]), number_type=NUMBER_TYPE) F_cdd.rep_type = RepType.INEQUALITY P = Polyhedron(F_cdd) V = array(P.get_generators()) return (V[:, 1:].T, V[:, 0])
def arbitrary_face_to_span(F,f): """ Compute the span matrix F^S of the face matrix F, that is, a matrix such that {F x <= f} if and only if {x = F^S z, z >= 0, sum(z)=1}. Works for both polytopes and cones. """ b, A = f.reshape((F.shape[0],1)), -F # H-representation: A x + b >= 0 F_cdd = Matrix(hstack([b, A]), number_type=NUMBER_TYPE) F_cdd.rep_type = RepType.INEQUALITY P = Polyhedron(F_cdd) V = array(P.get_generators()) return (V[:, 1:].T, V[:, 0]);
def theta_k(circumbody, k=0, i=0): """ This is from the Section 4 of the paper [Sadraddini and Tedrake, 2020]. Inputs: * AH-polytope: ``circumbody`` * int ``k``: the number of columns added to the subspace of ``U``. For more information, look at the paper. *Default* is 0. Outputs: * 2D numpy array ``Theta``, which is defined in the paper """ circumbody_AH = pp.to_AH_polytope(circumbody) H_y = circumbody_AH.P.H q_y = H_y.shape[0] if k < 0: return np.eye(q_y) Y = circumbody_AH.T # First identify K=[H_y'^Y'+ ker(H_y')] S_1 = np.dot(np.linalg.pinv(H_y.T), Y.T) S_2 = spa.null_space(H_y.T) if S_2.shape[1] > 0: S = np.hstack((S_1, S_2)) else: S = S_1 # phiw>=0. Now with the augmentation S_complement = spa.null_space(S.T) circumbody.dim_complement = S_complement.shape[1] number_of_columns = min(k, S_complement.shape[1]) if k == 0: psi = S else: psi = np.hstack((S, S_complement[:, i:number_of_columns + i])) p_mat = Matrix(np.hstack((np.zeros((psi.shape[0], 1)), psi))) p_mat.rep_type = RepType.INEQUALITY poly = Polyhedron(p_mat) R = np.array(poly.get_generators()) r = R[:, 1:].T Theta = np.dot(psi, r) assert np.all(Theta > -1e-5) return Theta
def cone_span_to_face(S, eliminate_redundancies=False): """ Returns the face matrix S^F of the span matrix S, that is, a matrix such that {x = S z, z >= 0} if and only if {S^F x <= 0}. """ S = np.asarray(S).squeeze() V = hstack([zeros((S.shape[1], 1)), S.T]) # V-representation: first column is 0 for rays V_cdd = Matrix(V, number_type=NUMBER_TYPE) V_cdd.rep_type = RepType.GENERATOR P = Polyhedron(V_cdd) H_matrix = P.get_inequalities() if (eliminate_redundancies): try: H_matrix.canonicalize() except: print "RuntimeError: failed to canonicalize matrix" H = array(H_matrix) if (len(H.shape) < 2): # warnings.warn("[cone_span_to_face] H is a vector rather than a matrix. S:\n"+str(S)+"\nH:\n"+str(H)); # S += 1e-6*np.random.rand(S.shape[0], S.shape[1]); # V = hstack([zeros((S.shape[1], 1)), S.T]) # V_cdd = Matrix(V, number_type=NUMBER_TYPE) # V_cdd.rep_type = RepType.GENERATOR # P = Polyhedron(V_cdd) # H_matrix = P.get_inequalities(); # H = array(H_matrix); # if(len(H.shape)<2): raise ValueError( "[cone_span_to_face] Cddlib failed to convert cone span to face: H is a vector rather than a matrix. H: " + str(H)) if (H.shape[1] > 1): b = H[:, 0] A = H[:, 1:] else: b, A = H[:, 0], zeros((H.shape[0], S.shape[0])) for i in xrange(H.shape[0]): if b[i] != 0: raise NotConeSpan(S) return -A
def span_of_face(F): """ Compute the span matrix F^S of the face matrix F, that is, a matrix such that {F x <= 0} if and only if {x = F^S z, z >= 0}. """ b, A = zeros((F.shape[0], 1)), -F # H-representation: A x + b >= 0 F_cdd = Matrix(hstack([b, A]), number_type=NUMBER_TYPE) F_cdd.rep_type = RepType.INEQUALITY P = Polyhedron(F_cdd) V = array(P.get_generators()) for i in xrange(V.shape[0]): if V[i, 0] != 0: # 1 = vertex, 0 = ray raise NotConeFace(F) return V[:, 1:]
def arbitrary_span_to_face(S, rv): """ Returns the face matrix S^F of the span matrix S, that is, a matrix such that {x = S z, z >= 0} if and only if {S^F x <= f}. The vector rv specifies whether the corresponding column in S is a vertex (1) or a ray (0). """ V = hstack([rv.reshape((S.shape[1], 1)), S.T]) # V-representation: first column is 0 for rays V_cdd = Matrix(V, number_type=NUMBER_TYPE) V_cdd.rep_type = RepType.GENERATOR P = Polyhedron(V_cdd) H = array(P.get_inequalities()) b, A = H[:, 0], H[:, 1:] return (-A, b)
def arbitrary_span_to_face(S, rv): """ Returns the face matrix S^F of the span matrix S, that is, a matrix such that {x = S z, z >= 0} if and only if {S^F x <= f}. The vector rv specifies whether the corresponding column in S is a vertex (1) or a ray (0). """ V = hstack([rv.reshape((S.shape[1], 1)), S.T]) # V-representation: first column is 0 for rays V_cdd = Matrix(V, number_type=NUMBER_TYPE) V_cdd.rep_type = RepType.GENERATOR P = Polyhedron(V_cdd) H = array(P.get_inequalities()) b, A = H[:, 0], H[:, 1:] return (-A,b)
def cone_face_to_span(F): """ Compute the span matrix F^S of the face matrix F, that is, a matrix such that {F x <= 0} if and only if {x = F^S z, z >= 0}. """ b, A = zeros((F.shape[0], 1)), -F # H-representation: A x + b >= 0 F_cdd = Matrix(hstack([b, A]), number_type=NUMBER_TYPE) F_cdd.rep_type = RepType.INEQUALITY P = Polyhedron(F_cdd) V = array(P.get_generators()) for i in xrange(V.shape[0]): if V[i, 0] != 0: # 1 = vertex, 0 = ray raise NotConeFace(F) return V[:, 1:].T
def face_of_span(S): """ Returns the face matrix S^F of the span matrix S, that is, a matrix such that {x = S z, z >= 0} if and only if {S^F x <= 0}. """ V = hstack([zeros((S.shape[1], 1)), S.T]) # V-representation: first column is 0 for rays V_cdd = Matrix(V, number_type=NUMBER_TYPE) V_cdd.rep_type = RepType.GENERATOR P = Polyhedron(V_cdd) H = array(P.get_inequalities()) b, A = H[:, 0], H[:, 1:] for i in xrange(H.shape[0]): if b[i] != 0: raise NotConeSpan(S) return -A
def poly_face_to_span(F, f): """ Compute the span matrix F^S of the face matrix F, that is, a matrix such that {F x <= f} if and only if {x = F^S z, z >= 0, sum(z)=1}. """ b, A = f.reshape((F.shape[0], 1)), -F # H-representation: A x + b >= 0 F_cdd = Matrix(hstack([b, A]), number_type=NUMBER_TYPE) F_cdd.rep_type = RepType.INEQUALITY P = Polyhedron(F_cdd) V = array(P.get_generators()) if (V.shape[0] == 0): print "V.shape", V.shape, "F.shape", F.shape, "f.shape", f.shape raise ValueError("This polytope seems to have no vertices") for i in xrange(V.shape[0]): if V[i, 0] != 1: # 1 = vertex, 0 = ray raise NotPolyFace(F) return V[:, 1:].T
def visualize_2D(list_of_polytopes, a=1.5): """ Given a polytope in its H-representation, plot it """ p_list = [] x_all = np.empty((0, 2)) for polytope in list_of_polytopes: p_mat = Matrix(np.hstack((polytope.H, polytope.h))) poly = Polyhedron(p_mat) x = np.array(poly.get_generators())[:, 0:2] x = x[ConvexHull(x).vertices, :] x_all = np.vstack((x_all, x)) p = Polygon(x) p_list.append(p) p_patch = PatchCollection(p_list, color=[(np.random.random(),np.random.random(),np.tanh(np.random.random())) \ for polytope in list_of_polytopes],alpha=0.6) fig, ax = plt.subplots() ax.add_collection(p_patch) ax.set_xlim([np.min(x_all[:, 0]) * a, a * np.max(x_all[:, 0])]) ax.set_ylim([np.min(x_all[:, 1]) * a, a * np.max(x_all[:, 1])]) ax.grid(color=(0, 0, 0), linestyle='--', linewidth=0.3)
def maximize(data, mapping={}, objective=(0, {})): """Maximization using the CONEstrip algorithm .. todo:: document, test more and clean up """ E = feasible(data, mapping) if E == set(): raise ValueError("The linear program is infeasible.") #print("The linear program is infeasible.") #return 0 l = sum(len(A) for A in E) h = Vector(mapping) goal = (objective[0], Vector(objective[1])) #print(goal) coordinates = list(frozenset.union(*(A.domain() for A in E))) E = [[vector for vector in A] for A in E] mat = Matrix([[0] + l * [0]], number_type='fraction') mat.extend([[-h[x]] + [v[x] for A in E for v in A] for x in coordinates], linear=True) # cone-constraints mat.extend([[0] + [int(B == A and w == v) for B in E for w in B] for A in E for v in A]) # mu >= 0 mat.obj_type = LPObjType.MAX mat.obj_func = tuple([goal[0]] + [goal[1][v] for A in E for v in A]) # (constant, mu) #print(mat) lp = LinProg(mat) lp.solve() if lp.status == LPStatusType.OPTIMAL: #print(lp.primal_solution) return lp.obj_value elif lp.status == LPStatusType.UNDECIDED: status = "undecided" elif lp.status == LPStatusType.INCONSISTENT: status = "inconsistent" elif lp.status == LPStatusType.UNBOUNDED: status = "unbounded" else: status = "of unknown status" raise ValueError("The linear program is " + str(status) + '.')
def feasible(data, mapping=None): """Check feasibility using the CONEstrip algorithm .. todo:: document, test more and clean up """ D = set(Polytope(A) for A in data) if (mapping == None) or all(mapping[x] != 0 for x in mapping): h = None else: h = Vector(mapping) D.add(Polytope({-h})) coordinates = list(frozenset.union(*(A.domain() for A in D))) E = [[vector for vector in A] for A in D] #print(E) while (E != []): k = len(E) L = [len(A) for A in E] l = sum(L) mat = Matrix([[0] + l * [0] + k * [0]], number_type='fraction') mat.extend([[0] + [v[x] for A in E for v in A] + k * [0] for x in coordinates], linear=True) # cone-constraints mat.extend([[0] + [int(B == A and w == v) for B in E for w in B] + k * [0] for A in E for v in A]) # mu >= 0 mat.extend([[1] + l * [0] + [-int(B == A) for B in E] for A in E]) # tau <= 1 mat.extend([[0] + l * [0] + [int(B == A) for B in E] for A in E]) # tau >= 0 mat.extend([[-1] + l * [0] + k * [1]]) # (sum of tau_A) >= 1 mat.extend([[0] + [int(B == A and w == v) for B in E for w in B] + [-int(B == A) for B in E] for A in E for v in A]) # tau_A <= mu_A for all A if h != None: # mu_{-h} >= 1 mat.extend([[-1] + [int(A == [-h]) for A in E for w in A] + k * [0]]) mat.obj_type = LPObjType.MAX mat.obj_func = tuple([0] + l * [0] + k * [1]) # (constant, mu, tau) #print(mat) lp = LinProg(mat) lp.solve() if lp.status == LPStatusType.OPTIMAL: sol = lp.primal_solution # (constant, mu, tau) tau = sol[l:] #print(tau) mu = [sol[sum(L[0:n]):sum(L[0:n]) + L[n]] for n in range(0, k)] #print(mu) E = [E[n] for n in range(0, k) if tau[n] == 1] #print(E) if all(all(mu[n][m] == 0 for m in range(0, L[n])) for n in range(0, k) if tau[n] == 0): E = {Polytope(A) for A in E} #print(E) if h != None: E = E - {Polytope([-h])} #print(E) return E else: continue else: return set() else: return set()
def sample_knots(num_intervals: int, knot_bounds: Union[np.ndarray, None] = None, interval_sizes: Union[np.ndarray, None] = None, num_samples: int = 1) -> Union[np.ndarray, None]: """Sample knots given a set of rules. Args: num_intervals Number of intervals (number of knots minus 1). knot_bounds Bounds for the interior knots. Here we assume the domain span 0 to 1, bound for a knot should be between 0 and 1, e.g. ``[0.1, 0.2]``. ``knot_bounds`` should have number of interior knots of rows, and each row is a bound for corresponding knot, e.g. ``knot_bounds=np.array([[0.0, 0.2], [0.3, 0.4], [0.3, 1.0]])``, for when we have three interior knots. interval_sizes Bounds for the distances between knots. For the same reason, we assume elements in `interval_sizes` to be between 0 and 1. For example, ``interval_distances=np.array([[0.1, 0.2], [0.1, 0.3], [0.1, 0.5], [0.1, 0.5]])`` means that the distance between first (0) and second knot has to be between 0.1 and 0.2, etc. And the number of rows for ``interval_sizes`` has to be same with ``num_intervals``. num_samples Number of knots samples. Returns: np.ndarray: Return knots sample as array, with `num_samples` rows and number of knots columns. """ # rename variables k = num_intervals b = knot_bounds d = interval_sizes N = num_samples t0 = 0.0 tk = 1.0 # check input assert t0 <= tk assert k >= 2 if d is not None: assert d.shape == (k, 2) and sum(d[:, 0]) <= 1.0 and\ np.all(d >= 0.0) and np.all(d <= 1.0) else: d = np.repeat(np.array([[0.0, 1.0]]), k, axis=0) if b is not None: assert b.shape == (k - 1, 2) and\ np.all(b[:, 0] <= b[:, 1]) and\ np.all(b[:-1, 1] <= b[1:, 1]) and\ np.all(b >= 0.0) and np.all(b <= 1.0) else: b = np.repeat(np.array([[0.0, 1.0]]), k - 1, axis=0) d = d * (tk - t0) b = b * (tk - t0) + t0 d[0] += t0 d[-1] -= tk # find vertices of the polyhedron D = -col_diff_mat(k - 1) I = np.identity(k - 1) A1 = np.vstack((-D, D)) A2 = np.vstack((-I, I)) b1 = np.hstack((-d[:, 0], d[:, 1])) b2 = np.hstack((-b[:, 0], b[:, 1])) A = np.vstack((A1, A2)) b = np.hstack((b1, b2)) mat = np.insert(-A, 0, b, axis=1) mat = Matrix(mat) mat.rep_type = RepType.INEQUALITY poly = Polyhedron(mat) ext = poly.get_generators() vertices_and_rays = np.array(ext) if vertices_and_rays.size == 0: print('there is no feasible knots') return None if np.any(vertices_and_rays[:, 0] == 0.0): print('polyhedron is not closed, something is wrong.') return None else: vertices = vertices_and_rays[:, 1:] # sample from the convex combination of the vertices n = vertices.shape[0] s_simplex = sample_simplex(n, N=N) s = s_simplex.dot(vertices) s = np.insert(s, 0, t0, axis=1) s = np.insert(s, k, tk, axis=1) return s