def is_quasiconcave(self): """Is the expression quasiconcave? """ # Verifies the DQCP composition rule. if self.is_concave(): return True if type(self) == cvxtypes.minimum(): return all(arg.is_quasiconcave() for arg in self.args) non_const = self._non_const_idx() if self.is_scalar() and len(non_const) == 1 and self.is_incr(non_const[0]): return self.args[non_const[0]].is_quasiconcave() if self.is_scalar() and len(non_const) == 1 and self.is_decr(non_const[0]): return self.args[non_const[0]].is_quasiconvex() if self.is_atom_quasiconcave(): for idx, arg in enumerate(self.args): if not (arg.is_affine() or (arg.is_concave() and self.is_incr(idx)) or (arg.is_convex() and self.is_decr(idx))): return False return True return False
def is_quasiconcave(self) -> bool: """Is the expression quasiconcave? """ from cvxpy.atoms.min import min as min_atom # Verifies the DQCP composition rule. if self.is_concave(): return True if type(self) in (cvxtypes.minimum(), min_atom): return all(arg.is_quasiconcave() for arg in self.args) non_const = self._non_const_idx() if self._is_real() and self.is_incr(non_const[0]): return self.args[non_const[0]].is_quasiconcave() if self._is_real() and self.is_decr(non_const[0]): return self.args[non_const[0]].is_quasiconvex() if self.is_atom_quasiconcave(): for idx, arg in enumerate(self.args): if not (arg.is_affine() or (arg.is_concave() and self.is_incr(idx)) or (arg.is_convex() and self.is_decr(idx))): return False return True return False