# Problems¶

The `Problem`

class is the entry point to
specifying and solving optimization problems. Each
`cvxpy.problems.problem.Problem`

instance encapsulates an optimization
problem, i.e., an objective and a set of constraints, and the
`solve()`

method either solves the problem
encoded by the instance, returning the optimal value and setting variables
values to optimal points, or reports that the problem was in fact infeasible or
unbounded. You can construct a problem, solve it, and inspect both its value
and the values of its variables like so:

```
problem = Problem(Minimize(expression), constraints)
problem.solve()
if problem.status not in ["infeasible", "unbounded"]:
# Otherwise, problem.value is inf or -inf, respectively.
print "Optimal value: %s" % problem.value
for variable in problem.variables():
print "Variable %s: value %s" % (variable.name(), variable.value)
```

Problems are **immutable**, except through the specification of
`Parameter`

values. This means
that you **cannot** modify a problem’s objective or constraints after you have
created it. If you find yourself wanting to add a constraint to an existing
problem, you should instead create a new problem using, for example, the
following idiom:

```
problem = Problem(Minimize(expression), constraints)
problem = Problem(problem.objective, problem.constraints + new_constraints)
```

Most users need not know anything about the
`Problem`

class except how to instantiate it,
how to solve problem instances (`solve()`

),
and how to query the solver results
(`status`

and
`value`

).

Information about the size of a problem instance and statistics about the most
recent solve invocation are captured by the
`SizeMetrics`

and
`SolverStats`

classes, respectively, and can be
accessed via the `size_metrics()`

and
`solver_stats()`

properties of the
`Problem`

class.