Exemple #1
0
    def _get_var_offsets(self, objective, constraints):
        """Maps each variable to a horizontal offset.

        Parameters
        ----------
        objective : Expression
            The canonicalized objective.
        constraints : list
            The canonicalized constraints.

        Returns
        -------
        tuple
            (map of variable to offset, length of variable vector)
        """
        vars_ = lu.get_expr_vars(objective)
        for constr in constraints:
            vars_ += lu.get_expr_vars(constr.expr)
        var_offsets = OrderedDict()
        var_sizes = {}
        # Ensure the variables are always in the same
        # order for the same problem.
        var_names = list(set(vars_))
        var_names.sort(key=lambda (var_id, var_size): var_id)
        # Map var ids to offsets.
        vert_offset = 0
        for var_id, var_size in var_names:
            var_sizes[var_id] = var_size
            var_offsets[var_id] = vert_offset
            vert_offset += var_size[0]*var_size[1]

        return (var_offsets, var_sizes, vert_offset)
Exemple #2
0
    def _get_var_offsets(self, objective, constraints):
        """Maps each variable to a horizontal offset.

        Parameters
        ----------
        objective : Expression
            The canonicalized objective.
        constraints : list
            The canonicalized constraints.

        Returns
        -------
        tuple
            (map of variable to offset, length of variable vector)
        """
        vars_ = lu.get_expr_vars(objective)
        for constr in constraints:
            vars_ += lu.get_expr_vars(constr.expr)
        var_offsets = OrderedDict()
        var_sizes = {}
        # Ensure the variables are always in the same
        # order for the same problem.
        var_names = list(set(vars_))
        var_names.sort(key=lambda (var_id, var_size): var_id)
        # Map var ids to offsets.
        vert_offset = 0
        for var_id, var_size in var_names:
            var_sizes[var_id] = var_size
            var_offsets[var_id] = vert_offset
            vert_offset += var_size[0] * var_size[1]

        return (var_offsets, var_sizes, vert_offset)
Exemple #3
0
    def _get_var_offsets(self, objective, constraints, nonlinear=None):
        """Maps each variable to a horizontal offset.

        Parameters
        ----------
        objective : Expression
            The canonicalized objective.
        constraints : list
            The canonicalized constraints.
        nonlinear : list, optional
            Non-linear constraints for CVXOPT.

        Returns
        -------
        tuple
            (map of variable to offset, length of variable vector)
        """
        vars_ = lu.get_expr_vars(objective)
        for constr in constraints:
            vars_ += lu.get_expr_vars(constr.expr)

        # If CVXOPT is the solver, some of the variables are
        # in NonLinearConstraints.
        if nonlinear is not None:
            for constr in nonlinear:
                for nonlin_var in constr.variables():
                    vars_ += lu.get_expr_vars(nonlin_var)

        var_offsets = OrderedDict()
        var_sizes = {}
        # Ensure the variables are always in the same
        # order for the same problem.
        var_names = list(set(vars_))
        var_names.sort(key=lambda (var_id, var_size): var_id)
        # Map var ids to offsets.
        vert_offset = 0
        for var_id, var_size in var_names:
            var_sizes[var_id] = var_size
            var_offsets[var_id] = vert_offset
            vert_offset += var_size[0]*var_size[1]

        return (var_offsets, var_sizes, vert_offset)
Exemple #4
0
    def get_var_offsets(objective, constraints, nonlinear):
        """Maps each variable to a horizontal offset.

        Parameters
        ----------
        objective : LinOp
            The canonicalized objective.
        constraints : list
            The canonicalized constraints.
        nonlinear : list
            Non-linear constraints for CVXOPT.

        Returns
        -------
        tuple
            (map of variable to offset, length of variable vector)
        """
        vars_ = lu.get_expr_vars(objective)
        for constr in constraints:
            vars_ += lu.get_expr_vars(constr.expr)

        # If CVXOPT is the solver, some of the variables are
        # in NonLinearConstraints.
        for constr in nonlinear:
            for nonlin_var in constr.args:
                vars_ += lu.get_expr_vars(nonlin_var)

        var_offsets = OrderedDict()
        # Ensure the variables are always in the same
        # order for the same problem.
        var_names = list(set(vars_))
        var_names.sort(key=lambda id_and_shape: id_and_shape[0])
        # Map var ids to offsets and shape.
        var_shapes = {}
        vert_offset = 0
        for var_id, var_shape in var_names:
            var_shapes[var_id] = var_shape
            var_offsets[var_id] = vert_offset
            vert_offset += np.prod(var_shape, dtype=int)

        return (var_offsets, var_shapes, vert_offset)
Exemple #5
0
    def presolve(objective, constr_map):
        """Eliminates unnecessary constraints and short circuits the solver
        if possible.

        Parameters
        ----------
        objective : LinOp
            The canonicalized objective.
        constr_map : dict
            A map of constraint type to a list of constraints.

        Returns
        -------
        bool
            Is the problem infeasible?
        """
        # Remove redundant constraints.
        for key, constraints in constr_map.items():
            ids = set()
            uniq_constr = []
            for c in constraints:
                if c.constr_id not in ids:
                    uniq_constr.append(c)
                    ids.add(c.constr_id)
            constr_map[key] = uniq_constr

        # If there are no constraints, the problem is unbounded
        # if any of the coefficients are non-zero.
        # If all the coefficients are zero then return the constant term
        # and set all variables to 0.
        if not any(constr_map.values()):
            str(objective)  # TODO

        # Remove constraints with no variables or parameters.
        for key in [s.EQ, s.LEQ]:
            new_constraints = []
            for constr in constr_map[key]:
                vars_ = lu.get_expr_vars(constr.expr)
                if len(vars_) == 0 and not lu.get_expr_params(constr.expr):
                    V, I, J, coeff = canonInterface.get_problem_matrix(
                        [constr])
                    is_pos, is_neg = intf.sign(coeff)
                    # For equality constraint, coeff must be zero.
                    # For inequality (i.e. <= 0) constraint,
                    # coeff must be negative.
                    if key == s.EQ and not (is_pos and is_neg) or \
                            key == s.LEQ and not is_neg:
                        return s.INFEASIBLE
                else:
                    new_constraints.append(constr)
            constr_map[key] = new_constraints

        return None
Exemple #6
0
 def test_get_vars(self):
     """Test getting vars from an expression.
     """
     shape = (5, 4)
     x = create_var(shape)
     y = create_var(shape)
     A = create_const(np.ones(shape), shape)
     # Expanding dict.
     add_expr = sum_expr([x, y, A])
     vars_ = get_expr_vars(add_expr)
     ref = [(x.data, shape), (y.data, shape)]
     self.assertCountEqual(vars_, ref)
Exemple #7
0
 def test_leq_constr(self):
     """Test creating a less than or equal constraint.
     """
     shape = (5, 5)
     x = create_var(shape)
     y = create_var(shape)
     lh_expr = sum_expr([x, y])
     value = np.ones(shape)
     rh_expr = create_const(value, shape)
     constr = create_leq(lh_expr, rh_expr)
     self.assertEqual(constr.shape, shape)
     vars_ = get_expr_vars(constr.expr)
     ref = [(x.data, shape), (y.data, shape)]
     self.assertCountEqual(vars_, ref)
Exemple #8
0
    def presolve(objective, constr_map, check_params=False):
        """Eliminates unnecessary constraints and short circuits the solver
        if possible.

        Parameters
        ----------
        objective : LinOp
            The canonicalized objective.
        constr_map : dict
            A map of constraint type to a list of constraints.
        check_params : bool, optional
            Should constraints with parameters be evaluated?

        Returns
        -------
        bool
            Is the problem infeasible?
        """
        # Remove redundant constraints.
        for key, constraints in constr_map.items():
            uniq_constr = unique(constraints,
                                 key=lambda c: c.constr_id)
            constr_map[key] = list(uniq_constr)

        # If there are no constraints, the problem is unbounded
        # if any of the coefficients are non-zero.
        # If all the coefficients are zero then return the constant term
        # and set all variables to 0.
        if not any(constr_map.values()):
            str(objective) # TODO

        # Remove constraints with no variables or parameters.
        for key in [s.EQ, s.LEQ]:
            new_constraints = []
            for constr in constr_map[key]:
                vars_ = lu.get_expr_vars(constr.expr)
                if len(vars_) == 0 and not lu.get_expr_params(constr.expr):
                    coeff = op2mat.get_constant_coeff(constr.expr)
                    sign = intf.sign(coeff)
                    # For equality constraint, coeff must be zero.
                    # For inequality (i.e. <= 0) constraint,
                    # coeff must be negative.
                    if key is s.EQ and not sign.is_zero() or \
                        key is s.LEQ and not sign.is_negative():
                        return s.INFEASIBLE
                else:
                    new_constraints.append(constr)
            constr_map[key] = new_constraints

        return None
Exemple #9
0
    def presolve(objective, constr_map, check_params=False):
        """Eliminates unnecessary constraints and short circuits the solver
        if possible.

        Parameters
        ----------
        objective : LinOp
            The canonicalized objective.
        constr_map : dict
            A map of constraint type to a list of constraints.
        check_params : bool, optional
            Should constraints with parameters be evaluated?

        Returns
        -------
        bool
            Is the problem infeasible?
        """
        # Remove redundant constraints.
        for key, constraints in constr_map.items():
            uniq_constr = unique(constraints, key=lambda c: c.constr_id)
            constr_map[key] = list(uniq_constr)

        # If there are no constraints, the problem is unbounded
        # if any of the coefficients are non-zero.
        # If all the coefficients are zero then return the constant term
        # and set all variables to 0.
        if not any(constr_map.values()):
            str(objective)  # TODO

        # Remove constraints with no variables or parameters.
        for key in [s.EQ, s.LEQ]:
            new_constraints = []
            for constr in constr_map[key]:
                vars_ = lu.get_expr_vars(constr.expr)
                if len(vars_) == 0 and not lu.get_expr_params(constr.expr):
                    coeff = op2mat.get_constant_coeff(constr.expr)
                    sign = intf.sign(coeff)
                    # For equality constraint, coeff must be zero.
                    # For inequality (i.e. <= 0) constraint,
                    # coeff must be negative.
                    if key is s.EQ and not sign.is_zero() or \
                        key is s.LEQ and not sign.is_negative():
                        return s.INFEASIBLE
                else:
                    new_constraints.append(constr)
            constr_map[key] = new_constraints

        return None
Exemple #10
0
 def test_eq_constr(self):
     """Test creating an equality constraint.
     """
     shape = (5, 5)
     x = create_var(shape)
     y = create_var(shape)
     lh_expr = sum_expr([x, y])
     value = np.ones(shape)
     rh_expr = create_const(value, shape)
     constr = create_eq(lh_expr, rh_expr)
     self.assertEqual(constr.shape, shape)
     vars_ = get_expr_vars(constr.expr)
     ref = [(x.data, shape), (y.data, shape)]
     if PY2:
         self.assertItemsEqual(vars_, ref)
     else:
         self.assertCountEqual(vars_, ref)
Exemple #11
0
    def format(self, eq_constr, leq_constr, dims, solver):
        """Formats SDP constraints as inequalities for the solver.

        Parameters
        ----------
        eq_constr : list
            A list of the equality constraints in the canonical problem.
        leq_constr : list
            A list of the inequality constraints in the canonical problem.
        dims : dict
            A dict with the dimensions of the conic constraints.
        solver : str
            The solver being called.
        """
        new_eq = self.__format[0]
        # If an equality constraint was introduced, update eq_constr and dims.
        if new_eq:
            eq_constr += new_eq
            dims[s.EQ_DIM] += self.size[0] * self.size[1]
        # Record the noncvx_var id.
        bool_id = lu.get_expr_vars(self.noncvx_var)[0][0]
        dims[self.CONSTR_TYPE].append(bool_id)
Exemple #12
0
    def format(self, eq_constr, leq_constr, dims, solver):
        """Formats SDP constraints as inequalities for the solver.

        Parameters
        ----------
        eq_constr : list
            A list of the equality constraints in the canonical problem.
        leq_constr : list
            A list of the inequality constraints in the canonical problem.
        dims : dict
            A dict with the dimensions of the conic constraints.
        solver : str
            The solver being called.
        """
        new_eq = self.__format[0]
        # If an equality constraint was introduced, update eq_constr and dims.
        if new_eq:
            eq_constr += new_eq
            dims[s.EQ_DIM] += self.size[0]*self.size[1]
        # Record the noncvx_var id.
        bool_id = lu.get_expr_vars(self.noncvx_var)[0][0]
        dims[self.CONSTR_TYPE].append(bool_id)
Exemple #13
0
    def test_consistency(self):
        """Test that variables and constraints keep a consistent order.
        """
        import itertools
        num_solves = 4
        vars_lists = []
        ineqs_lists = []
        var_ids_order_created = []
        for k in range(num_solves):
            sum = 0
            constraints = []
            var_ids = []
            for i in range(100):
                var = Variable(name=str(i))
                var_ids.append(var.id)
                sum += var
                constraints.append(var >= i)
            var_ids_order_created.append(var_ids)
            obj = Minimize(sum)
            p = Problem(obj, constraints)
            objective, constr_map = p.canonicalize()
            all_ineq = itertools.chain(constr_map[s.EQ], constr_map[s.LEQ])
            var_offsets, var_sizes, x_length = p._get_var_offsets(objective, all_ineq)
            # Sort by offset.
            vars_ = sorted(var_offsets.items(), key=lambda (var_id, offset): offset)
            vars_ = [var_id for (var_id, offset) in vars_]
            vars_lists.append(vars_)
            ineqs_lists.append(constr_map[s.LEQ])

        # Verify order of variables is consistent.
        for i in range(num_solves):
            self.assertEqual(var_ids_order_created[i],
                vars_lists[i])
        for i in range(num_solves):
            for idx, constr in enumerate(ineqs_lists[i]):
                var_id, _ = lu.get_expr_vars(constr.expr)[0]
                self.assertEqual(var_ids_order_created[i][idx],
                    var_id)
Exemple #14
0
    def test_consistency(self):
        """Test that variables and constraints keep a consistent order.
        """
        import itertools
        num_solves = 4
        vars_lists = []
        ineqs_lists = []
        var_ids_order_created = []
        for k in range(num_solves):
            sum = 0
            constraints = []
            var_ids = []
            for i in range(100):
                var = Variable(name=str(i))
                var_ids.append(var.id)
                sum += var
                constraints.append(var >= i)
            var_ids_order_created.append(var_ids)
            obj = Minimize(sum)
            p = Problem(obj, constraints)
            objective, constr_map = p.canonicalize()
            all_ineq = itertools.chain(constr_map[s.EQ], constr_map[s.LEQ])
            var_offsets, var_sizes, x_length = p._get_var_offsets(
                objective, all_ineq)
            # Sort by offset.
            vars_ = sorted(var_offsets.items(),
                           key=lambda (var_id, offset): offset)
            vars_ = [var_id for (var_id, offset) in vars_]
            vars_lists.append(vars_)
            ineqs_lists.append(constr_map[s.LEQ])

        # Verify order of variables is consistent.
        for i in range(num_solves):
            self.assertEqual(var_ids_order_created[i], vars_lists[i])
        for i in range(num_solves):
            for idx, constr in enumerate(ineqs_lists[i]):
                var_id, _ = lu.get_expr_vars(constr.expr)[0]
                self.assertEqual(var_ids_order_created[i][idx], var_id)
Exemple #15
0
from cvxpy.lin_ops.tree_mat import mul, tmul, prune_constants
import cvxpy.problems.iterative as iterative
from cvxpy.problems.solvers.utilities import SOLVERS
from cvxpy.problems.problem_data.sym_data import SymData
import numpy as np
import numpy.linalg
import scipy.sparse as sp
import scipy.linalg as LA
import unittest
import faoInterface

# Convolution
x = Variable(3)
f = np.matrix(np.array([1, 2, 3])).T
g = np.array([0, 1, 0.5])
f_conv_g = np.array([0., 1., 2.5, 4., 1.5])
expr = conv(f, x).canonical_form[0]
vars_ = lu.get_expr_vars(expr)
dag = fao.tree_to_dag(expr, vars_)

input_arr = g
output_arr = np.zeros(5)
faoInterface.eval_FAO_DAG(dag, input_arr, output_arr)
# self.assertItemsAlmostEqual(output_arr, f_conv_g)

input_arr = np.array(range(5))
output_arr = np.zeros(3)
toep = LA.toeplitz(np.array([1, 0, 0]), np.array([1, 2, 3, 0, 0]))
faoInterface.eval_FAO_DAG(dag, input_arr, output_arr, forward=False)
print output_arr
print toep
Exemple #16
0
    def test_fao_mul(self):
        """Test the mul method.
        """
        n = 2
        ones = np.ones(n)
        # Matrix-vector multiplication.
        x = Variable(n)
        A = np.matrix("1 2; 3 4").A
        expr = (A * x).canonical_form[0]

        input_arr = np.ones(n)
        output_arr = np.zeros(n)
        vars_ = lu.get_expr_vars(expr)
        dag = fao.tree_to_dag(expr, vars_)
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr)
        assert (output_arr == A.dot(ones)).all()

        input_arr = np.ones(n)
        output_arr = np.zeros(n)
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr, forward=False)
        assert (output_arr == A.T.dot(ones)).all()

        n = 2
        m = 3
        ones = np.ones((m, n))
        # Matrix-matrix multiplication.
        x = Variable(m, n)
        A = np.matrix("1 2 3; 4 5 6").A

        expr = (A * x).canonical_form[0]
        input_arr = np.ones(m * n)
        output_arr = np.zeros(n * n)
        vars_ = lu.get_expr_vars(expr)
        dag = fao.tree_to_dag(expr, vars_)
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr)
        assert (output_arr == A.dot(ones).flatten(order='F')).all()

        ones = np.ones((n, n))
        input_arr = np.ones(n * n)
        output_arr = np.zeros(m * n)
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr, forward=False)
        assert (output_arr == A.T.dot(ones).flatten(order='F')).all()

        # Addition
        n = 2
        x = Variable(n, n)
        y = Variable(n, n)
        expr = (y + x).canonical_form[0]

        input_arr = np.array(range(2 * n * n))
        output_arr = np.zeros(n * n)
        vars_ = lu.get_expr_vars(expr)
        dag = fao.tree_to_dag(expr, vars_)
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr)
        assert (output_arr == np.array([0 + 4, 1 + 5, 2 + 6, 3 + 7])).all()

        input_arr = np.array(range(n * n))
        output_arr = np.zeros(2 * n * n)
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr, forward=False)
        assert (output_arr == np.hstack([input_arr, input_arr])).all()

        # Negation
        x = Variable(3, 2)
        expr = (-x).canonical_form[0]
        vars_ = lu.get_expr_vars(expr)
        dag = fao.tree_to_dag(expr, vars_)
        input_arr = np.arange(6)
        output_arr = np.zeros(3 * 2)
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr)
        assert (output_arr == -input_arr).all()

        input_arr = np.arange(6)
        output_arr = np.zeros(3 * 2)
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr, forward=False)
        assert (output_arr == -input_arr).all()

        # Convolution
        x = Variable(3)
        f = np.matrix(np.array([1, 2, 3])).T
        g = np.array([0, 1, 0.5])
        f_conv_g = np.array([0., 1., 2.5, 4., 1.5])
        expr = conv(f, x).canonical_form[0]
        vars_ = lu.get_expr_vars(expr)
        dag = fao.tree_to_dag(expr, vars_)

        input_arr = g
        output_arr = np.zeros(5)
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr)
        self.assertItemsAlmostEqual(output_arr, f_conv_g)

        input_arr = np.array(range(5))
        output_arr = np.zeros(3)
        toep = LA.toeplitz(np.array([1, 0, 0]), np.array([1, 2, 3, 0, 0]))
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr, forward=False)
        print output_arr
        print toep
        self.assertItemsAlmostEqual(output_arr, toep.dot(input_arr))
Exemple #17
0
from cvxpy.problems.solvers.utilities import SOLVERS
from cvxpy.problems.problem_data.sym_data import SymData
import numpy as np
import numpy.linalg
import scipy.sparse as sp
import scipy.linalg as LA
import unittest
import faoInterface


# Convolution
x = Variable(3)
f = np.matrix(np.array([1, 2, 3])).T
g = np.array([0, 1, 0.5])
f_conv_g = np.array([ 0., 1., 2.5,  4., 1.5])
expr = conv(f, x).canonical_form[0]
vars_ = lu.get_expr_vars(expr)
dag = fao.tree_to_dag(expr, vars_)

input_arr = g
output_arr = np.zeros(5)
faoInterface.eval_FAO_DAG(dag, input_arr, output_arr)
# self.assertItemsAlmostEqual(output_arr, f_conv_g)

input_arr = np.array(range(5))
output_arr = np.zeros(3)
toep = LA.toeplitz(np.array([1,0,0]),
                   np.array([1, 2, 3, 0, 0]))
faoInterface.eval_FAO_DAG(dag, input_arr, output_arr, forward=False)
print output_arr
print toep
Exemple #18
0
    def test_fao_mul(self):
        """Test the mul method.
        """
        n = 2
        ones = np.ones(n)
        # Matrix-vector multiplication.
        x = Variable(n)
        A = np.matrix("1 2; 3 4").A
        expr = (A*x).canonical_form[0]

        input_arr = np.ones(n)
        output_arr = np.zeros(n)
        vars_ = lu.get_expr_vars(expr)
        dag = fao.tree_to_dag(expr, vars_)
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr)
        assert (output_arr == A.dot(ones)).all()

        input_arr = np.ones(n)
        output_arr = np.zeros(n)
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr, forward=False)
        assert (output_arr == A.T.dot(ones)).all()

        n = 2
        m = 3
        ones = np.ones((m,n))
        # Matrix-matrix multiplication.
        x = Variable(m,n)
        A = np.matrix("1 2 3; 4 5 6").A

        expr = (A*x).canonical_form[0]
        input_arr = np.ones(m*n)
        output_arr = np.zeros(n*n)
        vars_ = lu.get_expr_vars(expr)
        dag = fao.tree_to_dag(expr, vars_)
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr)
        assert (output_arr == A.dot(ones).flatten(order='F')).all()

        ones = np.ones((n,n))
        input_arr = np.ones(n*n)
        output_arr = np.zeros(m*n)
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr, forward=False)
        assert (output_arr == A.T.dot(ones).flatten(order='F')).all()

        # Addition
        n = 2
        x = Variable(n, n)
        y = Variable(n, n)
        expr = (y + x).canonical_form[0]

        input_arr = np.array(range(2*n*n))
        output_arr = np.zeros(n*n)
        vars_ = lu.get_expr_vars(expr)
        dag = fao.tree_to_dag(expr, vars_)
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr)
        assert (output_arr == np.array([0 + 4, 1 + 5, 2 + 6, 3 + 7])).all()

        input_arr = np.array(range(n*n))
        output_arr = np.zeros(2*n*n)
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr, forward=False)
        assert (output_arr == np.hstack([input_arr, input_arr])).all()

        # Negation
        x = Variable(3,2)
        expr = (-x).canonical_form[0]
        vars_ = lu.get_expr_vars(expr)
        dag = fao.tree_to_dag(expr, vars_)
        input_arr = np.arange(6)
        output_arr = np.zeros(3*2)
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr)
        assert (output_arr == -input_arr).all()

        input_arr = np.arange(6)
        output_arr = np.zeros(3*2)
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr, forward=False)
        assert (output_arr == -input_arr).all()

        # Convolution
        x = Variable(3)
        f = np.matrix(np.array([1, 2, 3])).T
        g = np.array([0, 1, 0.5])
        f_conv_g = np.array([ 0., 1., 2.5,  4., 1.5])
        expr = conv(f, x).canonical_form[0]
        vars_ = lu.get_expr_vars(expr)
        dag = fao.tree_to_dag(expr, vars_)

        input_arr = g
        output_arr = np.zeros(5)
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr)
        self.assertItemsAlmostEqual(output_arr, f_conv_g)

        input_arr = np.array(range(5))
        output_arr = np.zeros(3)
        toep = LA.toeplitz(np.array([1,0,0]),
                           np.array([1, 2, 3, 0, 0]))
        faoInterface.eval_FAO_DAG(dag, input_arr, output_arr, forward=False)
        print output_arr
        print toep
        self.assertItemsAlmostEqual(output_arr, toep.dot(input_arr))