Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] View of /branches/ein16/synth/d2/obj_apply.py
ViewVC logotype

View of /branches/ein16/synth/d2/obj_apply.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4261 - (download) (as text) (annotate)
Mon Jul 25 20:14:18 2016 UTC (2 years, 11 months ago) by cchiw
File size: 14591 byte(s)
added cases to apply
import sys
import re
import os
from obj_ex import *
from obj_apply import *
from obj_ty import *
from obj_operator import *
from obj_field import *

class apply:
    def __init__(self, name, opr, lhs, rhs, oty, isrootlhs, isrootrhs):
        self.name=name
        self.opr=opr
        self.lhs=lhs
        self.rhs=rhs
        self.oty=oty
        self.isrootlhs=isrootlhs
        self.isrootrhs=isrootrhs
    def oprToStr(self):
        out=self.opr.name
        def g(t):
            if(t):
                return "x"
            else:
                op1 = self.lhs.opr
                return "_"+operator.toStr(op1,"x")
        out+=g(self.isrootlhs)+g(self.isrootrhs)
        return out
           

    def get_all_FieldTys(self):
        flds = ""
        lhs = self.lhs
        rhs = self.rhs
        if (lhs!=None):
            if (self.isrootlhs):
                flds+=lhs.fldty.name
            else :
                flds += apply.get_all_FieldTys(lhs)
        if (rhs!=None):
            if (self.isrootrhs):
                flds+= ","+rhs.fldty.name
            else :
                flds += apply.get_all_FieldTys(rhs)
        return flds

    def toStr(self, layer):
        if (self==None):
            return "None"
        s = (str(layer)+": opr:"+self.opr.name+" isrootlhs: "+str(self.isrootlhs)+" isrootrhs: "+str(self.isrootrhs)+" oty: "+str(self.oty.name))
        lhs = self.lhs
        rhs= self.rhs
        if(self.isrootlhs):
            if(lhs!=None):
                s+="\n"+str( layer)+"\tlhs:"+ field.toStr(lhs)
        else:
            s+= "\nnot a root: look to lhs"
            if (lhs!=None):
                s+="\n"+str( layer)+"lhs:"+apply.toStr(lhs, layer+1)
            else:
                s+="\n"+str( layer)+"lhs:None"
        if (self.isrootrhs):
            if(rhs!=None):
                s+="\n"+str( layer)+"\trhs:"+field.toStr(rhs)
        else:
            s+= "\nnot a root: look to rhs"
            if(rhs!=None):
                s+="\n"+str( layer)+"rhs:"+apply.toStr(rhs, layer+1)
            else:
                s+="\n"+str( layer)+"rhs:None"
        return s
    
    def checkDim(self):
        if (self.isroot):
            d1=self.lhs.fldty.ty.dim
            d2=self.rhs.fldty.ty.dim
            if (d1==d2):
                return d1
            else :
                raise "dimension is not the same"
        else :
            raise "not a root app"
    def get_arity(self):
        return self.opr.arity
    def get_unary(self):
        return self.lhs

    def get_binary(self):
        f=self.lhs
        g=self.rhs
 
        return (f,g)

    def get_types(self):
        #if (self.isroot):
        rtn=[]
        if(self.lhs!=None):
            rtn.append(self.lhs.fldty)
        if(self.rhs!=None):
            rtn.append(self.rhs.fldty)
        return rtn
            #else :
            #raise "not a root app"

    # single list
    def get_exps(self):
        rtn=[]
        if(self.lhs!=None):
            rtn.append(self.lhs)
        if(self.rhs!=None):
            rtn.append(self.rhs)
        return rtn


    def get_root_types(self):
        rtn=[]
        if (self.isroot):
            for i in [self.lhs, self.rhs]:
                rtn.append(i.fldty)
            return rtn
        else :
            for i in [self.lhs, self.rhs]:
                rtn=rtn+(apply.get_root_types(i))
            return rtn
    def get_root_app(self):
        if (self.isrootlhs):
            return self
        else :
            if(self.rhs== None):
                return (apply.get_root_app(self.lhs))
            else:
                raise "more expressions in root"

    def get_all_Fields(self):
        flds = []
        lhs = self.lhs
        rhs = self.rhs
        if (lhs!=None):
            if (self.isrootlhs):
                flds.append(lhs)
            else :
                flds = flds + apply.get_all_Fields(lhs)
        if (rhs!=None):
            if (self.isrootrhs):
                flds.append(rhs)
            else :
                flds = flds + apply.get_all_Fields(rhs)
        return flds


    

    def get_oty(self):
        return self.oty
#------------------------------ helpers -----------------------------------------------------
#field dimension is the same as vector length
def checkNd(ityp1):
    if(fty.is_Vector(ityp1)):
        n1 = fty.get_vecLength(ityp1)
        dim1 = fty.get_dim(ityp1)
        return (n1==dim1)
    else:
        return (false,"needs vector")

def isDifferentiable(ityp):
    #print "isDifferentiabl-ityp",ityp
    dim = fty.get_dim(ityp)
    k=ityp.k
    return (k>0)

#type of field after operation is applied
def applyUnaryOp(op1,ityps):
    ityp1=ityps[0]
    print "itype1", ityp1
    k = ityp1.k
    dim = ityp1.dim
    ashape = ityp1.shape
    name =  "op1 "+op1.name+"("+ityp1.name+")"
    #print "apply unary op", name, ashape
    def same():
        return (true, ityp1)
    def err():
        return (false, name)
    def mkTyp(shape):
        (tf, rty1) = shapeToTyhelper(shape, dim)
        if(tf):
            rtn1 = fty.convertTy(rty1, k)
            return (true, rtn1)
        else:
            return err()

    def mkTyp_deductk(shape):
        if(k<1 and len(shape)>3):
             return err()
        else:
            (tf, rty1) = shapeToTyhelper(shape, dim)
            if(tf):
                rtn1 = fty.convertTy(rty1, k-1)
                return (true, rtn1)
            else:
                return err()
    if ((op_probe==op1) or (op_negation==op1) or (op_normalize==op1)):
        return same() #type unaffected by operation
    elif(op_norm==op1):            # apply op_norm
        return mkTyp([])
    elif(fty.is_Scalar(ityp1)):
        if(op_sqrt==op1):
            return same()
        elif(op_cosine==op1) or (op_sine==op1)or (op_tangent==op1):
            return same()
        elif(op_acosine==op1) or (op_asine==op1)or (op_atangent==op1):
            return same()
        elif (op_gradient==op1):
            if (dim==1):
                return mkTyp_deductk([])
            else:
                return mkTyp_deductk([dim])
        else:
            return err()
    elif(fty.is_Vector(ityp1)):
      
        [n1] = ashape
        if((op_slicev0==op1) or(op_slicev1 ==op1)):            # apply op_slice
            return mkTyp([])
        elif(not (n1==dim)):
            # since the rest are differentiation operators
            return err()
        elif(op_curl==op1):            # apply curl
            if((n1==2) and (dim==2)):
                return mkTyp_deductk([])
            elif((n1==3) and (dim==3)):
                return mkTyp_deductk([3])
            else:
                return err()
        elif(op_jacob==op1):            # apply op_jacob
            if(n1==2 and dim==2):
                return mkTyp_deductk([2,2])
            elif(n1==3 and dim==3):
                return mkTyp_deductk([3,3])
            else:
                return err()
        elif(op_divergence==op1):
            return mkTyp_deductk([])
        else:
            return err()
    elif(fty.is_Matrix(ityp1)):
        [n, m] = ashape
        if(op_slicem1 ==op1):            # apply op_slice [:,0]
            return mkTyp(fty.drop_last(ityp1))
        elif(op_slicem0==op1):            # apply op_slice [1,:]
            return mkTyp(fty.drop_first(ityp1))
        elif(n!=m):
            return err()
        elif(op_transpose==op1):            # apply op_tranpose
            return mkTyp([m, n])
        elif((op_trace==op1) or (op_det==op1)):
            if(dim==2 or dim==3):
                return mkTyp([])
            else:
                return err()
        else:
            return err()
    elif(fty.is_Ten3(ityp1)):
        if(op_slicet0==op1):            # apply op_slice [:,1,:]
            [a, _, c] = ashape
            return mkTyp([a,c])
        elif(op_slicet1 ==op1):            # apply op_slice [1,0,:]
            [_,_,c] = ashape
            return mkTyp([c])
        else:
            return err()
    else:
        return err()

#type of field after operation is applied
def applyBinaryOp(op1,ityps):

    name =  "op1 "+op1.name
    print "inside bin app", name
    print "iypes:",len(ityps),"-", ityps

    ityp1=ityps[0]
    ityp2=ityps[1]
    ashape = fty.get_shape(ityp1)
    bshape = fty.get_shape(ityp2)
    name += "("+ityp1.name+","+ityp2.name+")"
    print "inside bin app", name
    (tf, fldty) = find_field(ityp1,ityp2) # assures same dimension for both fields
    if(not tf):
        return (false, "not the same dimension")
    k = fldty.k
    dim = fldty.dim
    def err():
        # type not supported
        return (false, name)
    def mkTyp(shape):
        if (len(shape)>3):
            return err()
        else:
            (tf, rty1) = shapeToTyhelper(shape, dim)
            if(tf):
                rtn1 = fty.convertTy(rty1, k)
                return (true, rtn1)
            else:
                # don't yet have a type to represent this type
                # i.e. odd shape such as [2, 3, 3]
                return err()

    def sameshape(ty3):
        if(ashape==bshape):
            return (true, ty3) #type unaffected by operation
        else:
            return err()
    if (op_add==op1) or (op_subtract==op1):
        return sameshape(fldty)
    elif(op_division==op1):
        if(fty.is_Scalar(ityp2)):
            return mkTyp(ashape)
        else:
            return err()
    elif(op_cross==op1):
        if(fty.is_Vector(ityp1) and fty.is_Vector(ityp2)):
            n1 = fty.get_vecLength(ityp1)
            n2 = fty.get_vecLength(ityp2)
            if((n1==n2) and (n1==2) and (dim==2)):
                return (true, fty.convertTy(ty_scalarF_d2,k))
            elif((n1==n2) and (n1==3) and (dim==3)):
                return (true, fldty)
            else:
                return err()
        return err()
    else:
        # rest of operators are non scalar
        if(fty.is_Scalar(ityp1) or fty.is_Scalar(ityp2)):
            if(op_scale==op1):
                return mkTyp(ashape+bshape)
            else:
                return err()
        else:
            if((op_modulate==op1)):
                return sameshape(fldty)
            elif(op_outer==op1):
                return mkTyp(ashape+bshape)
            elif(op_doubledot==op1):
                if(fty.is_Matrix(ityp1) and fty.is_Matrix(ityp2)):
                    if(ashape==bshape):
                        print "same shape"
                        return mkTyp([])
                    else:
                        print "not the same shape"
                        return err()
                else:
                    return err()
            elif(op_inner==op1):
                n1 = fty.get_last_ix(ityp1)
                n2 = fty.get_first_ix(ityp2)
                if(n1!=n2): #must have equal vector lengths
                    return err()
                shape1 = fty.drop_first(ityp1)
                shape2 = fty.drop_last(ityp2)
                return mkTyp(shape1+shape2)
            else:
                return err()


##################################################################################################
# apply unary and binary operator
def get_tshape(opr1, ishape):
    arity=opr1.arity
    if(arity==1):
        return applyUnaryOp(opr1,ishape)
    elif(arity==2):

        return applyBinaryOp(opr1, ishape)


# create apply, operator and field objects
# from an example opr number, type number, and input file
#Apply to two field expressions
def mkApply_fld(name, opr, ishape, inputfile, tshape1):
    arity=opr.arity
    # synthetic field-1
    k=2
    index1=0
    ity1  = ishape[index1]
    dim1  = fty.get_dim(ity1)
    def set_App(lhs, rhs):
        return apply(name, opr, lhs, rhs, tshape1, true, true)
    def set_fld(id, dim):
        return mk_Field(id, ishape, k, inputfile, dim)
    
    if (arity==1): # unary operator
        (F1, finfo1, coeff1) = set_fld(index1, dim1)
        z1 = set_App(F1, None)
        dim1  = fty.get_dim(ity1)
        return (z1, [coeff1], dim1, tshape1)
    elif (arity==2): # binary operator
        index2=1
        ity2  = ishape[index2]
        dim2  = fty.get_dim(ity2)
        (F, finfo1, coeff1) = set_fld(index1, dim1)
        (G, finfo2, coeff2) = set_fld(index2, dim2)
        z = set_App(F,G)
        coeffs = [coeff1,coeff2]
        (_, fldty) = find_field(ity1, ity2) # dimension for field involved
        dimn  = fty.get_dim(fldty)
        return (z, coeffs, dimn, tshape1)
    else:
        raise Exception ("arity is not supported: "+str(arity))

def mkApply_twice(name,opr_inner,opr_outer, ishape, inputfile, tshape1, tshape2):
    outer_arity = opr_outer.arity
    inner_arity = opr_inner.arity
    def set_innerApp(shape):
        return mkApply_fld(name, opr_inner, shape, inputfile, tshape1)
    def set_outerApp(lhs, rhs, shape):
        #return  mkApply_opr(name, opr_outer, lhs, rhs, shape)
        # apply(name, opr1,lhs, rhs, otypertn, false, true)
        return apply(name, opr_outer,lhs, rhs, tshape2, false, true)

    def set_field(id):
        k = 2
        ity =ishape[id]
        dim  = fty.get_dim(ity)
        return mk_Field(id, ishape, k, inputfile+"cat", dim)

    if (outer_arity==1): # both are unary operators
        (z1, coeffs, dim1, otype1) =  set_innerApp(ishape)
        z2 = set_outerApp(z1, None, [otype1])
        return (z2, coeffs, dim1)
    if (outer_arity==2 and inner_arity==1): # one is a unary operator
        # apply inner operator to first arg
        ishape1 = [ishape[0]]
        (z1, coeffs, dim1, otype1) =  set_innerApp(ishape1)
        # create second field
        id2 = 1
        (F2, finfo2, coeff2) = set_field(id2)
        # apply outer operator to otype and second arg
        ishape3 =  [otype1, ishape[1]]
        z2 = set_outerApp(z1, F2, ishape3)
        
        (_, fldty) = find_field(ishape[0], ishape[1]) # dimension for field involved
        dimn  = fty.get_dim(fldty)
        return (z2, coeffs, dimn)
    elif (outer_arity==2 and inner_arity==2): # binary operator
        # apply inner operator to first arg
        (z1, coeff1, dim1, otype1) = set_innerApp(ishape)
         # create third field
        id2 = 2
        (F2, finfo2, coeff2) = set_field(id2)
        ishape3 =[otype1, finfo2]
        z2 = set_outerApp(z1, F2, ishape3)
        coeffs = coeff1+[coeff2]
        (_, fldty) = find_field(ishape[0], ishape[1]) # dimension for field involved
        dimn  = fty.get_dim(fldty)
        return (z2, coeffs, dimn)
    else:
        raise Exception ("arity is not supported: "+str(outer_arity))

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0