Ejemplo n.º 1
0
def inverterLoopTanh(numInverters, numSolutions="all", a=-5.0):
    epsilon = 1e-14
    start = time.time()
    vs = []
    for i in range(numInverters):
        vs.append(Variable("v" + str(i)))

    allConstraints = []

    # Store rambus oscillator constraints
    for i in range(numInverters):
        allConstraints.append(vs[i] >= -1)
        allConstraints.append(vs[i] <= 1)
        inputInd = i
        outputInd = (i + 1) % numInverters
        allConstraints.append(tanh(a * vs[inputInd]) - vs[outputInd] == 0.0)

    allSolutions = []
    while True:
        if numSolutions != "all" and len(allSolutions) == numSolutions:
            break

        # Store constraints pruning search space so that
        # old hyperrectangles are not considered
        excludingConstraints = []
        for solution in allSolutions:
            singleExcludingConstraints = []
            for i in range(numInverters):
                singleExcludingConstraints.append(vs[i] < solution[i][0])
                singleExcludingConstraints.append(vs[i] > solution[i][1])
            excludingConstraints.append(singleExcludingConstraints)

        # Add all the rambus oscillator constraints
        f_sat = logical_and(*allConstraints)
        # Add constraints so that old hyperrectangles are not considered
        if len(excludingConstraints) > 0:
            for constraints in excludingConstraints:
                f_sat = logical_and(f_sat, logical_or(*constraints))

        #print ("f_sat")
        #print (f_sat)
        result = CheckSatisfiability(f_sat, epsilon)
        #print (result)
        if result is None:
            break
        hyper = np.zeros((numInverters, 2))
        for i in range(numInverters):
            hyper[i, :] = [
                result[vs[i]].lb() - 2 * epsilon,
                result[vs[i]].ub() + 2 * epsilon
            ]

        #print ("hyper", hyper)
        allSolutions.append(hyper)

        print("num solutions found", len(allSolutions))

    end = time.time()
    print("time taken", end - start)
    return allSolutions
Ejemplo n.º 2
0
def inverterScMosfet(inputVoltage, numSolutions="all"):
    epsilon = 1e-14
    start = time.time()
    Vdd = 1.0
    sn = 3
    sp = 2 * sn

    outputVolt = Variable("outputVolt")
    iP = Variable("iP")
    iN = Variable("iN")

    allConstraints = []
    allConstraints.append(outputVolt >= 0.0)
    allConstraints.append(outputVolt <= Vdd)
    allConstraints.append(-iP - iN == 0)
    allConstraints += mvs_id("n", 0.0, inputVoltage, outputVolt, iN, sn)
    allConstraints += mvs_id("p", Vdd, inputVoltage, outputVolt, iP, sp)

    allSolutions = []
    while True:
        if numSolutions != "all" and len(allSolutions) == numSolutions:
            break

        # Store constraints pruning search space so that
        # old hyperrectangles are not considered
        excludingConstraints = []
        for solution in allSolutions:
            singleExcludingConstraints = []
            singleExcludingConstraints.append(outputVolt < solution[0][0])
            singleExcludingConstraints.append(outputVolt > solution[0][1])
            excludingConstraints.append(singleExcludingConstraints)

        #print ("allConstraints")
        #print (allConstraints)
        f_sat = logical_and(*allConstraints)
        if len(excludingConstraints) > 0:
            for constraints in excludingConstraints:
                f_sat = logical_and(f_sat, logical_or(*constraints))

        #print ("f_sat")
        #print (f_sat)
        result = CheckSatisfiability(f_sat, epsilon)
        #print (result)
        if result is None:
            break
        hyper = np.zeros((1, 2))
        hyper[0, :] = [
            result[outputVolt].lb() - 2 * epsilon,
            result[outputVolt].ub() + 2 * epsilon
        ]

        #print ("hyper", hyper)
        allSolutions.append(hyper)

        print("num solutions found", len(allSolutions))

    end = time.time()
    print("time taken", end - start)
    return allSolutions
Ejemplo n.º 3
0
def exampleFun(numSolutions="all"):
    start = time.time()
    epsilon = 1e-14
    lenV = 1
    x = Variable('x')

    allSolutions = []
    while True:
        if numSolutions != "all" and len(allSolutions) == numSolutions:
            break
        allConstraints = []
        allConstraints.append(2 * x * asin(cos(0.797) * sin(math.pi / x)) -
                              0.0331 * x >= 2 * math.pi - 2.097)
        allConstraints.append(x >= 3)
        allConstraints.append(x <= 64)
        excludingConstraints = []
        for solution in allSolutions:
            singleExcludingConstraints = []
            singleExcludingConstraints.append(x <= solution[0][0])
            singleExcludingConstraints.append(x >= solution[0][1])
            excludingConstraints.append(singleExcludingConstraints)

        #print ("allConstraints")
        #print (allConstraints)
        #print ("numConstraints", len(allConstraints))
        f_sat = logical_and(*allConstraints)
        if len(excludingConstraints) > 0:
            for constraints in excludingConstraints:
                f_sat = logical_and(f_sat, logical_or(*constraints))

        #print ("f_sat")
        #print (f_sat)
        result = CheckSatisfiability(f_sat, epsilon)
        #print (result)
        if result is None:
            break
        hyper = np.zeros((1, 2))
        hyper[0, :] = [
            result[x].lb() - 2 * epsilon, result[x].ub() + 2 * epsilon
        ]

        print("hyper", hyper)
        allSolutions.append(hyper)

        print("num solutions found", len(allSolutions))
    '''constraints = []
	x = Variable('x')
	#constraints.append(x >= 0.0)
	#constraints.append(x <= 64.0)
	constraints.append(2*math.pi - 2*x*asin(cos(0.797)*sin(math.pi/x)) == 2.097 - 0.0331*x)
	f_sat = logical_and(*constraints)
	result = CheckSatisfiability(f_sat, epsilon)
	print (result)'''
    end = time.time()
    print("time taken", end - start)
Ejemplo n.º 4
0
def inverterTanh(inputVoltage, a=-5.0, numSolutions="all"):
    epsilon = 1e-14
    start = time.time()

    outputVolt = Variable("outputVolt")

    allConstraints = []
    allConstraints.append(outputVolt >= -1.0)
    allConstraints.append(outputVolt <= 1.0)
    allConstraints.append(tanh(a * inputVoltage) - outputVolt == 0)

    allSolutions = []
    while True:
        if numSolutions != "all" and len(allSolutions) == numSolutions:
            break

        # Store constraints pruning search space so that
        # old hyperrectangles are not considered
        excludingConstraints = []
        for solution in allSolutions:
            singleExcludingConstraints = []
            singleExcludingConstraints.append(outputVolt < solution[0][0])
            singleExcludingConstraints.append(outputVolt > solution[0][1])
            excludingConstraints.append(singleExcludingConstraints)

        #print ("allConstraints")
        #print (allConstraints)
        f_sat = logical_and(*allConstraints)
        if len(excludingConstraints) > 0:
            for constraints in excludingConstraints:
                f_sat = logical_and(f_sat, logical_or(*constraints))

        #print ("f_sat")
        #print (f_sat)
        result = CheckSatisfiability(f_sat, epsilon)
        #print (result)
        if result is None:
            break
        hyper = np.zeros((1, 2))
        hyper[0, :] = [
            result[outputVolt].lb() - 2 * epsilon,
            result[outputVolt].ub() + 2 * epsilon
        ]

        #print ("hyper", hyper)
        allSolutions.append(hyper)

        print("num solutions found", len(allSolutions))

    end = time.time()
    print("time taken", end - start)
    return allSolutions
Ejemplo n.º 5
0
def calculate_port_flow_rate(dg, port_name):
    """Calculate the flow rate into a port based on the cross sectional
    area of the channel it flows into, the pressure and the density
    eqn from https://en.wikipedia.org/wiki/Hagen-Poiseuille_equation
    flow_rate = area * sqrt(2*pressure/density)
    Unit for flow rate is m^3/s

    :param str port_name: Name of the port
    :returns: Flow rate determined from port pressure and area of
              connected channels
    """
    areas = []
    port_pressure = retrieve(dg, port_name, 'pressure')
    port_density = retrieve(dg, port_name, 'density')
    port_flow_rate = retrieve(dg, port_name, 'flow_rate')
    # Calculate cross sectional area of all channels flowing into this port
    for port_out in dg.succ[port_name]:
        areas.append(
            retrieve(dg, (port_name, port_out), 'height') *
            retrieve(dg, (port_name, port_out), 'width'))
    # Add together all these areas if multiple exist
    if len(areas) == 1:
        total_area = areas[0]
    else:
        areas = [a + b for a, b in zip(areas, areas[1:])]
        total_area = logical_and(*areas)

    return (port_flow_rate**2 == (total_area**2) *
            ((2 * port_pressure) / port_density))
Ejemplo n.º 6
0
 def test_lorentz_cone(self):
     config = Config()
     config.use_local_optimization = True
     config.precision = 0.0001
     result = Minimize(
         x2,
         logical_and(-5 <= x0, x0 <= 5, -5 <= x1, x1 <= 5, 0 <= x2, x2 <= 5,
                     1 >= (x0 - 1)**2 + (x1 - 1)**2,
                     x2**2 >= x0**2 + x1**2), config)
     self.assertTrue(result)
     self.assertAlmostEqual(result[x2].mid(), 0.414212, places=3)
Ejemplo n.º 7
0
    def test_minimize_via_forall(self):
        # To minimize f(X) s.t. φ(x), this test encodes
        # the problem into a first-order logic formula.
        #
        #    ∃X. φ(X) ∧ [∀Y φ(Y) ⇒ (f(X) ≤ f(Y))]
        #
        # Here we use f(x) = sin(x)cos(x)
        #             φ(X) = (0 ≤ x) ∧ (x ≤ π)
        def f(x):
            return sin(x) * cos(x)

        def phi(x):
            return logical_and(0 <= x, x <= math.pi)

        problem = logical_and(
            phi(x),
            forall([y], logical_and(logical_imply(phi(y),
                                                  f(x) <= f(y)))))
        result = CheckSatisfiability(problem, 0.01)
        self.assertTrue(result)
        self.assertAlmostEqual(result[x].mid(), math.pi * 3 / 4, places=3)
Ejemplo n.º 8
0
    def test_logical(self):
        f1 = (x == 0)
        f2 = (y == 0)
        self.assertEqual(str(logical_not(f1)), "!((x = 0))")
        self.assertEqual(str(logical_imply(f1, f2)),
                         str(logical_or(logical_not(f1), f2)))
        self.assertEqual(
            str(logical_iff(f1, f2)),
            str(logical_and(logical_imply(f1, f2), logical_imply(f2, f1))))

        # Test single-operand logical statements
        self.assertEqual(str(logical_and(x >= 1)), "(x >= 1)")
        self.assertEqual(str(logical_or(x >= 1)), "(x >= 1)")
        # Test binary operand logical statements
        self.assertEqual(str(logical_and(x >= 1, x <= 2)),
                         "((x >= 1) and (x <= 2))")
        self.assertEqual(str(logical_or(x <= 1, x >= 2)),
                         "((x >= 2) or (x <= 1))")
        # Test multiple operand logical statements
        self.assertEqual(str(logical_and(x >= 1, x <= 2, y == 2)),
                         "((y = 2) and (x >= 1) and (x <= 2))")
        self.assertEqual(str(logical_or(x >= 1, x <= 2, y == 2)),
                         "((y = 2) or (x >= 1) or (x <= 2))")
Ejemplo n.º 9
0
    def test_02_Rosenbrock_Disk(self):
        (vars, domain) = make_domain([("x", -1.5, 1.5), ("y", -1.5, 1.5)])
        [x, y] = vars

        def objective(x, y):
            return (1 - x)**2 + 100 * (y - x**2)**2

        constraints = logical_and(domain, x**2 + y**2 < 2)

        sol = Minimize(objective(*vars), constraints, self.config)
        self.global_min = 0.0
        self.assertIsNotNone(sol)
        self.found_min = compute_min(objective, sol, vars)
        self.assertAlmostEqual(self.found_min,
                               self.global_min,
                               delta=self.config.precision * 2)
Ejemplo n.º 10
0
    def test_05_Simionescu(self):
        (vars, domain) = make_domain([("x", -1.25, 1.25), ("y", -1.25, 1.25)])
        [x, y] = vars

        def objective(x, y):
            return 0.1 * x * y

        constraints = logical_and(
            domain, x**2 + y**2 <= (1 + 0.2 * cos(8 * atan(x / y)))**2)

        sol = Minimize(objective(*vars), constraints, self.config)
        self.global_min = -0.072625
        self.assertIsNotNone(sol)
        self.found_min = compute_min(objective, sol, vars)
        self.assertAlmostEqual(self.found_min,
                               self.global_min,
                               delta=self.config.precision * 10)
Ejemplo n.º 11
0
    def test_03_Mishra_Bird(self):
        (vars, domain) = make_domain([("x", -10, 0.0), ("y", -6.5, 0.0)])
        [x, y] = vars

        def objective(x, y):
            return sin(y) * exp((1 - cos(x))**2) + cos(x) * exp(
                (1 - sin(y))**2) + (x - y)**2

        constraints = logical_and(domain, (x + 5)**2 + (y + 5)**2 < 25)

        sol = Minimize(objective(*vars), constraints, self.config)
        self.global_min = -106.7645367
        self.assertIsNotNone(sol)
        self.found_min = compute_min(objective, sol, vars)
        self.assertAlmostEqual(self.found_min,
                               self.global_min,
                               delta=self.config.precision * 2)
Ejemplo n.º 12
0
    def test_04_Townsend(self):
        (vars, domain) = make_domain([("x", -2.25, 2.5), ("y", -2.5, 1.75)])
        [x, y] = vars

        def objective(x, y):
            return -(cos((x - 0.1) * y))**2 - x * sin(3 * x + y)

        constraints = logical_and(
            domain, x**2 + y**2 <
            (2 * cos(atan2(x, y)) - 0.5 * cos(2 * atan2(x, y)) -
             0.25 * cos(3 * atan2(x, y)) - 0.125 * cos(4 * atan2(x, y)))**2 +
            (2 * sin(atan2(x, y)))**2)

        sol = Minimize(objective(*vars), constraints, self.config)
        self.global_min = -2.0239884
        self.assertIsNotNone(sol)
        self.found_min = compute_min(objective, sol, vars)
        self.assertAlmostEqual(self.found_min,
                               self.global_min,
                               delta=self.config.precision * 2)
Ejemplo n.º 13
0
    def invoke_backend(self, _show):
        """Combine all of the SMT expressions into one expression to sent to dReal
        solver to determine solvability

        :param bool show: If true then the full SMT formula that was created is
                          printed
        :returns: dReal model showing the values for each of the parameters
        """
        formula = logical_and(*self.exprs)
        # Prints the generated formula in full, remove serialize for shortened
        if _show:
            #  nx.draw(self.dg)
            #  plt.show()
            print(formula)
        # Return None if not solvable, returns a dict-like structure giving the
        # range of values for each Variable
        model = CheckSatisfiability(formula, 10)
        if model:
            return model
        else:
            return "No solution found"
Ejemplo n.º 14
0
def translate_output(dg, name):
    """Create SMT expressions for bounding the parameters of an output port
    to be within the constraints defined by the user

    :param str name: Name of the port to be constrained
    :returns: None -- no issues with translating the port parameters to SMT
    """
    exprs = []
    if dg.size(name) <= 0:
        raise ValueError("Port %s must have 1 or more connections" % name)
    # Currently don't support this, and I don't think it would be the case
    # in real circuits, an output port is considered the end of a branch
    if len(list(dg.succ[name])) != 0:
        raise ValueError("Cannot have channels out of output port %s" % name)

    # Since input is just a specialized node, call translate node
    [exprs.append(val) for val in translate_node(dg, name)]

    # Calculate flow rate for this port based on pressure and channels out
    # if not specified by user
    if not algorithms.retrieve(dg, name, 'min_flow_rate'):
        # The flow rate at this node is the sum of the flow rates of the
        # the channel coming in (I think, should be verified)
        total_flow_in = []
        for channel_in in dg.pred[name]:
            total_flow_in.append(dg.edges[(channel_in, name)]['flow_rate'])
        if len(total_flow_in) == 1:
            exprs.append(
                algorithms.retrieve(dg, name, 'flow_rate') == total_flow_in[0])
        else:
            total_flow_in_formulas = [
                a + b for a, b in zip(total_flow_in, total_flow_in[1:])
            ]
            exprs.append(
                algorithms.retrieve(dg, name, 'flow_rate') == logical_and(
                    *total_flow_in_formulas))
    return exprs
Ejemplo n.º 15
0
def translate_ep_cross(dg, name, fluid_name='default'):
    """Create SMT expressions for an electrophoretic cross
    :param str name: the name of the junction node in the electrophoretic cross
    :returns: None -- no issues with translating channel parameters to SMT
    :raises: ValueError if the analyte_properties are not defined properly
             TypeError if the analyte_properties are not floats or ints
    """

    # work in progress
    exprs = []

    # Validate input
    if dg.size(name) != 4:
        raise ValueError("Electrophoretic Cross %s must have 4 connections" %
                         name)

    # Electrophoretic Cross is a type of node, so call translate node
    [exprs.append(val) for val in translate_node(dg, name)]

    # Because it's done in translate_tjunc
    ep_cross_node_name = name

    # figure out which nodes are for sample injection and which are for separation channel
    # assume single input node, 3 output nodes, one junction node
    # assume separation and tail channels are specified by user
    phases = nx.get_edge_attributes(dg, 'phase')
    for edge, phase in phases.items():
        # assuming only one separation channel, and only 1 tail channel
        if phase == 'separation':
            separation_channel_name = edge
            anode_node_name = edge[1]
        elif phase == 'tail':
            tail_channel_name = edge
            cathode_node_name = edge[
                edge[0] ==
                ep_cross_node_name]  # returns whichever tuple element is NOT the ep_cross node

    # is there a better way to do this?
    node_kinds = nx.get_node_attributes(dg, 'kind')
    for node, kind in node_kinds.items():
        if node not in separation_channel_name and node not in tail_channel_name:
            if kind == 'input':
                injection_channel_name = (node, ep_cross_node_name)
                injection_node_name = node  # necessary?
            elif kind == 'output':
                waste_channel_name = (ep_cross_node_name, node)
                waste_node_name = node  # necessary?

    # assert dimensions:
    # assert width and height of tail channel to be equal to separation channel
    exprs.append(
        algorithms.retrieve(dg, tail_channel_name, 'width') ==
        algorithms.retrieve(dg, separation_channel_name, 'width'))
    exprs.append(
        algorithms.retrieve(dg, tail_channel_name, 'height') ==
        algorithms.retrieve(dg, separation_channel_name, 'height'))

    # assert width and height of injection channel to be equal to waste channel
    exprs.append(
        algorithms.retrieve(dg, injection_channel_name, 'width') ==
        algorithms.retrieve(dg, waste_channel_name, 'width'))
    exprs.append(
        algorithms.retrieve(dg, injection_channel_name, 'height') ==
        algorithms.retrieve(dg, waste_channel_name, 'height'))

    # assert height of separation channel and injection channel are same
    exprs.append(
        algorithms.retrieve(dg, injection_channel_name, 'height') ==
        algorithms.retrieve(dg, separation_channel_name, 'height'))

    # electric field
    E = Variable('E')
    exprs.append(E < 1000000)
    exprs.append(E > 0)
    exprs.append(E == algorithms.calculate_electric_field(
        dg, anode_node_name, cathode_node_name))
    # only works if cathode is an input?  only works for paths that are true in directed graph

    # assume that the analyte parameters were included in the injection port
    # need to validate that the data exists?

    D = algorithms.retrieve(dg, injection_node_name, 'analyte_diffusivities')
    C0 = algorithms.retrieve(dg, injection_node_name,
                             'analyte_initial_concentrations')
    q = algorithms.retrieve(dg, injection_node_name, 'analyte_charges')
    r = algorithms.retrieve(dg, injection_node_name, 'analyte_radii')

    analyte_properties = {
        'analyte_diffusivities': D,
        'analyte_initial_concentrations': C0,
        'analyte_charges': q,
        'analyte_radii': r
    }

    for property_name, values in analyte_properties.items():
        # check if something is defined, otherwise should be set to false
        if not values:
            raise ValueError(
                'No values defined for %s in electrophoretic cross node %s' %
                (property_name, ep_cross_node_name))

        # make sure all the values are either ints or floats
        if not all(isinstance(x, (int, float)) for x in values):
            raise TypeError(
                "%s values in electrophoretic cross node '%s' must be numbers"
                % (property_name, ep_cross_node_name))

    # n = number of analytes
    n = len(D)
    for property_name, values in analyte_properties.items():
        # check that they all have the same number of values
        n_to_check = len(values)

        if not (n_to_check == n):
            raise ValueError(
                "Expecting %s values, and found %s for %s in node: '%s'" %
                (n, n_to_check, property_name, ep_cross_node_name))

    delta = algorithms.retrieve(dg, separation_channel_name,
                                'min_sampling_rate')
    x_detector = algorithms.retrieve(dg, separation_channel_name, 'x_detector')

    # These are currently set as parameters to the node function
    # all are constants, numbers between 0 and 1
    # brief descriptions:
    # lower c, more discernable concentration peaks
    # higher p, any given conc. peak must be higher (closer to max conc.)
    # qf is arbitrary, rule of thumb qf = 0.9 (called q in Stephen Chou's paper)
    c = algorithms.retrieve(dg, ep_cross_node_name, 'c')
    p = algorithms.retrieve(dg, ep_cross_node_name, 'p')
    qf = algorithms.retrieve(dg, ep_cross_node_name, 'qf')

    mu = []
    v = []
    t_peak = []
    t_min = []
    W = algorithms.retrieve(dg, injection_channel_name, 'width')

    # for each analyte
    for i in range(0, n):
        # calculate mobility
        mu.append(Variable('mu_' + str(i)))
        exprs.append(mu[i] < 10000000000)
        exprs.append(mu[i] > 0)
        exprs.append(mu[i] == algorithms.calculate_mobility(
            dg, separation_channel_name, q[i], r[i]))

        # calculate velocity
        v.append(Variable('v_' + str(i)))
        #  exprs.append(v[i] < 1)
        exprs.append(v[i] > 0)
        exprs.append(v[i] == algorithms.calculate_charged_particle_velocity(
            dg, mu[i], E))

        # calculate t_peak, initialize variables for t_min
        t_peak.append(Variable('t_peak_' + str(i)))
        t_min.append(Variable('t_min_' + str(i)))
        exprs.append(t_peak[i] < 1000000)
        exprs.append(t_peak[i] > 0)
        exprs.append(t_min[i] < 1000000)
        exprs.append(t_min[i] > 0)
        exprs.append(t_peak[i] == x_detector / v[i])

    # detector position is somewhere along the separation channel
    # assume x_detector ranges from 0 to length of channel
    # to get absolute position of detector, add x_detector to ep_cross_node position
    exprs.append(x_detector <= algorithms.retrieve(dg, separation_channel_name,
                                                   'length'))

    # C_negligible is the minimum concentration level
    # i.e. smallest concentration peak should be > C_negligible
    C_negligible = Variable('C_negligible')
    C_floor = Variable('C_floor')
    sigma0 = Variable('sigma0')

    # TODO: This equation for sigma0 is for round, should add rectangular as well
    # definition of sigma0 for round channels (sigma0 ~ r_channel/2.355)
    exprs.append(sigma0 == W / (2 * 2.355))
    exprs.append(C_floor == (min(C0) /
                             (sigma0 +
                              (2 * max(D) * x_detector / v[n - 1])**0.5)))
    exprs.append(C_negligible == p * C_floor)

    diff = []
    for i in range(0, n - 1):

        # constrain that time difference between peaks is large enough to be detected
        exprs.append(t_peak[i] + delta < t_min[i])
        exprs.append(t_peak[i] + delta < t_min[i + 1])

        # constrain t_min to be where derivative of concentration is 0
        # if two adjacent peaks are close enough in height, then instead of using
        # the differential eqn, can approximate Fi(tmin) = Fi+1(tmin)
        # where i is the current analyte, and i+1 is the next analyte
        # and F = C(x_detector), C is concentration
        # quantify closeness of heights of peaks using the variable diff
        diff.append(Variable('diff_' + str(i)))
        exprs.append(diff[i] == C0[i] / C0[i + 1] * (D[i + 1] * mu[i] /
                                                     (D[i] * mu[i + 1]))**0.5)

        # if 0.1 < diff < 10, then use expression Fi(tmin) = Fi+1(tmin)
        # otherwise use expression dFi/dt (tmin) + dFi+1/dt (tmin) = 0
        t_min_constraint_expression = if_then_else(
            logical_and(0.1 < diff[i], diff[i] < 10),
            algorithms.calculate_concentration(dg, C0[i], D[i], W, v[i],
                                               x_detector, t_min[i]) -
            algorithms.calculate_concentration(dg, C0[i + 1], D[i + 1], W,
                                               v[i + 1], x_detector, t_min[i]),
            (algorithms.calculate_concentration(
                dg, C0[i + 1], D[i + 1], W, v[i + 1], x_detector,
                t_min[i])).Differentiate(t_min[i]) +
            (algorithms.calculate_concentration(
                dg, C0[i + 1], D[i + 1], W, v[i + 1], x_detector,
                t_min[i])).Differentiate(t_min[i]))

        exprs.append(t_min_constraint_expression == 0)

        # an alternate way to define C_negligible is:
        # C_negligible < p * min(Fi(t_peaki))
        # this requires computing the concentration again, which is inefficient
        # Wrote this expression just in case; this is the more exact expression
        #  for C_negligible, in case the simpler one does not work for square
        #  channels
        # I don't know how to use the min function in dreal, so I figured an
        #  equivalent but less efficient way to do it is just to ensure it is
        #  less than Fi(t_peaki), for every i
        #  exprs.append(C_negligible < p * algorithms.calculate_concentration(dg, C0[i], D[i], W, v[i], x_detector, t_peak[i]))

        # F(tmin, i)/(F(tmax, i)) <= c
        # F(tmin, i)/F(tpeak, j) ~ ( Fi(tmin,i) + Fi+1(tmin, i) + (n-2)(1-q)/(n-3) ) / Fj(tpeak,j)
        exprs.append(
            (algorithms.calculate_concentration(dg, C0[i], D[i], W, v[i],
                                                x_detector, t_min[i]) +
             algorithms.calculate_concentration(dg, C0[i + 1], D[i + 1], W, v[
                 i + 1], x_detector, t_min[i]) + (n - 2) * (1 - qf) /
             (n - 3) * C_negligible) / (algorithms.calculate_concentration(
                 dg, C0[i], D[i], W, v[i], x_detector, t_peak[i])) <= c)

        # F(tmin, i)/(F(tmax, i+1)) <= c
        exprs.append(
            (algorithms.calculate_concentration(dg, C0[i], D[i], W, v[i],
                                                x_detector, t_min[i]) +
             algorithms.calculate_concentration(dg, C0[i + 1], D[i + 1], W, v[
                 i + 1], x_detector, t_min[i]) + (n - 2) * (1 - qf) /
             (n - 3) * C_negligible) /
            (algorithms.calculate_concentration(dg, C0[i + 1], D[i + 1], W, v[
                i + 1], x_detector, t_peak[i + 1])) <= c)

    # Call translate on output - waste node
    [
        exprs.append(val) for val in translation_strats[algorithms.retrieve(
            dg, waste_node_name, 'kind')](dg, waste_node_name)
    ]
    # Call translate on output - anode
    [
        exprs.append(val) for val in translation_strats[algorithms.retrieve(
            dg, anode_node_name, 'kind')](dg, anode_node_name)
    ]

    return exprs
Ejemplo n.º 16
0
def translate_node(dg, name):
    """Create SMT expressions for bounding the parameters of an node
    to be within the constraints defined by the user

    :param name: Name of the node to be constrained
    :returns: None -- no issues with translating the port parameters to SMT
    """
    exprs = []
    # Pressure at a node is the sum of the pressures flowing into it
    output_pressures = []
    for node_name in dg.pred[name]:
        # This returns the nodes with channels that flowing into this node
        # pressure calculated based on P=QR
        # Could modify equation based on
        # https://www.dolomite-microfluidics.com/wp-content/uploads/
        # Droplet_Junction_Chip_characterisation_-_application_note.pdf
        output_pressures.append(
            algorithms.channel_output_pressure(dg, (node_name, name)))
    if len(dg.pred[name]) == 1:
        exprs.append(
            algorithms.retrieve(dg, name, 'pressure') == output_pressures[0])
    elif len(dg.pred[name]) > 1:
        output_pressure_formulas = [
            a + b for a, b in zip(output_pressures, output_pressures[1:])
        ]
        exprs.append(
            algorithms.retrieve(dg, name, 'pressure') == logical_and(
                *output_pressure_formulas))

    if algorithms.retrieve(dg, name, 'min_x'):
        exprs.append(
            algorithms.retrieve(dg, name, 'x') == algorithms.retrieve(
                dg, name, 'min_x'))
    else:
        exprs.append(algorithms.retrieve(dg, name, 'x') >= 0)
    if algorithms.retrieve(dg, name, 'min_y'):
        exprs.append(
            algorithms.retrieve(dg, name, 'y') == algorithms.retrieve(
                dg, name, 'min_y'))
    else:
        exprs.append(algorithms.retrieve(dg, name, 'y') >= 0)
    # If parameters are provided by the user, then set the
    # their Variable equal to that value, otherwise make it greater than 0
    if algorithms.retrieve(dg, name, 'min_pressure'):
        # If min_pressure has a value then a user defined value was provided
        # and this variable is set equal to this value, else simply set its
        # value to be >0, same for viscosity, pressure, flow_rate, X, Y and density
        exprs.append(
            algorithms.retrieve(dg, name, 'pressure') == algorithms.retrieve(
                dg, name, 'min_pressure'))
    else:
        exprs.append(algorithms.retrieve(dg, name, 'pressure') >
                     0.000001)  # Force pressure to be greater than 1uPa
        exprs.append(algorithms.retrieve(dg, name, 'pressure') <
                     1000000)  # Force pressure to be less than 1MPa
    if algorithms.retrieve(dg, name, 'min_flow_rate'):
        exprs.append(
            algorithms.retrieve(dg, name, 'flow_rate') == algorithms.retrieve(
                dg, name, 'min_flow_rate'))
    else:
        exprs.append(
            algorithms.retrieve(dg, name, 'flow_rate') >
            0.000000000001)  # Force flow rate to be greater than 1nL/s
        exprs.append(algorithms.retrieve(dg, name, 'flow_rate') <
                     0.001)  # Force flow rate to be less than 1L/s
    if algorithms.retrieve(dg, name, 'min_viscosity'):
        exprs.append(
            algorithms.retrieve(dg, name, 'viscosity') == algorithms.retrieve(
                dg, name, 'min_viscosity'))
    else:
        exprs.append(algorithms.retrieve(dg, name, 'viscosity') >
                     0.0001)  # Liquid helium is 0.000158
        exprs.append(algorithms.retrieve(dg, name, 'viscosity') <
                     100)  # Force viscosity to be less than 100Pa*s

    if algorithms.retrieve(dg, name, 'min_density'):
        exprs.append(
            algorithms.retrieve(dg, name, 'density') == algorithms.retrieve(
                dg, name, 'min_density'))
    else:
        exprs.append(algorithms.retrieve(dg, name, 'density') >
                     500)  # No liquid should be below this density
        exprs.append(algorithms.retrieve(dg, name, 'density') <
                     2000)  # Force density for be less than 2000kg/m^3

    densities = []
    for node_in in dg.pred[name]:
        densities.append(algorithms.retrieve(dg, node_in, 'density'))

    # If they are all equal, then set this node to be that density if there is a value
    # TODO: Create case for when different densities come in
    if densities and densities[1:] == densities[:-1]:
        exprs.append(
            algorithms.retrieve(dg, name, 'density') == algorithms.retrieve(
                dg,
                list(dg.pred[name].keys())[0], 'density'))
    # To recursively traverse, call on all successor channels
    for node_out in dg.succ[name]:
        [
            exprs.append(val)
            for val in translation_strats[algorithms.retrieve(
                dg, (name, node_out), 'kind')](dg, (name, node_out))
        ]
    return exprs
Ejemplo n.º 17
0
 def test_minimize3(self):
     result = Minimize(x, logical_and(0 <= x, x <= 1, 0 <= p, p <= 1,
                                      p <= x), 0.00001)
     self.assertTrue(result)
     self.assertAlmostEqual(result[x].mid(), 0, places=2)
     self.assertAlmostEqual(result[p].mid(), 0, places=2)
Ejemplo n.º 18
0
    def run_and(self, ident, val) -> None:
        a = val.exp_a['dreal_exp']
        b = val.exp_b['dreal_exp']

        ident['dreal_exp'] = dreal.logical_and(a, b)
Ejemplo n.º 19
0
def pFet(Vtp, Vdd, Kp, Sp, src, gate, drain, tI):
	constraints = []
	if type(src) == Variable or type(gate) == Variable:
		constraints.append(logical_or(logical_and(src < drain, gate - drain >= Vtp, tI == 0.0),
										logical_and(src < drain, gate - drain <= Vtp, src - drain <= gate - drain - Vtp, tI == -0.5*Sp*Kp*(gate - drain - Vtp)*(gate - drain - Vtp)),
										logical_and(src < drain, gate - drain <= Vtp, src - drain >= gate - drain - Vtp, tI == -Sp*Kp*(gate - drain - Vtp - (src - drain)/2.0)*(src - drain)),
										logical_and(src >= drain, gate - src >= Vtp, tI == 0.0),
										logical_and(src >= drain, gate - src <= Vtp, drain - src <= gate - src - Vtp, tI == 0.5*Sp*Kp*(gate - src - Vtp)*(gate - src - Vtp)),
										logical_and(src >= drain, gate - src <= Vtp, drain - src >= gate - src - Vtp, tI == Sp*Kp*(gate - src - Vtp - (drain - src)/2.0)*(drain - src))))
	else:
		if gate - src >= Vtp:
			constraints.append(logical_or(logical_and(src < drain, gate - drain >= Vtp, tI == 0.0),
											logical_and(src < drain, gate - drain <= Vtp, src - drain <= gate - drain - Vtp, tI == -0.5*Sp*Kp*(gate - drain - Vtp)*(gate - drain - Vtp)),
											logical_and(src < drain, gate - drain <= Vtp, src - drain >= gate - drain - Vtp, tI == -Sp*Kp*(gate - drain - Vtp - (src - drain)/2.0)*(src - drain)),
											logical_and(src >= drain, tI == 0.0)))
		else:
			constraints.append(logical_or(logical_and(src < drain, gate - drain >= Vtp, tI == 0.0),
											logical_and(src < drain, gate - drain <= Vtp, src - drain <= gate - drain - Vtp, tI == -0.5*Sp*Kp*(gate - drain - Vtp)*(gate - drain - Vtp)),
											logical_and(src < drain, gate - drain <= Vtp, src - drain >= gate - drain - Vtp, tI == -Sp*Kp*(gate - drain - Vtp - (src - drain)/2.0)*(src - drain)),
											logical_and(src >= drain, drain - src <= gate - src - Vtp, tI == 0.5*Sp*Kp*(gate - src - Vtp)*(gate - src - Vtp)),
											logical_and(src >= drain, drain - src >= gate - src - Vtp, tI == Sp*Kp*(gate - src - Vtp - (drain - src)/2.0)*(drain - src))))
	
	return constraints
Ejemplo n.º 20
0
def nFet(Vtn, Vdd, Kn, Sn, src, gate, drain, tI):
	constraints = []
	if type(src) == Variable or type(gate) == Variable:
		constraints.append(logical_or(logical_and(src > drain, gate - drain <= Vtn, tI == 0.0),
										logical_and(src > drain, gate - drain >= Vtn, src - drain >= gate - drain - Vtn, tI == -0.5*Sn*Kn*(gate - drain - Vtn)*(gate - drain - Vtn)),
										logical_and(src > drain, gate - drain >= Vtn, src - drain <= gate - drain - Vtn, tI == -Sn*Kn*(gate - drain - Vtn - (src - drain)/2.0)*(src - drain)),
										logical_and(src <= drain, gate - src <= Vtn, tI == 0.0),
										logical_and(src <= drain, gate - src >= Vtn, drain - src >= gate - src - Vtn, tI == 0.5*Sn*Kn*(gate - src - Vtn)*(gate - src - Vtn)),
										logical_and(src <= drain, gate - src >= Vtn, drain - src <= gate - src - Vtn, tI == Sn*Kn*(gate - src - Vtn - (drain - src)/2.0)*(drain - src))))
	else:
		if gate - src <= Vtn:
			constraints.append(logical_or(logical_and(src > drain, gate - drain <= Vtn, tI == 0.0),
											logical_and(src > drain, gate - drain >= Vtn, src - drain >= gate - drain - Vtn, tI == -0.5*Sn*Kn*(gate - drain - Vtn)*(gate - drain - Vtn)),
											logical_and(src > drain, gate - drain >= Vtn, src - drain <= gate - drain - Vtn, tI == -Sn*Kn*(gate - drain - Vtn - (src - drain)/2.0)*(src - drain)),
											logical_and(src <= drain, tI == 0.0)))
		else:
			constraints.append(logical_or(logical_and(src > drain, gate - drain <= Vtn, tI == 0.0),
											logical_and(src > drain, gate - drain >= Vtn, src - drain >= gate - drain - Vtn, tI == -0.5*Sn*Kn*(gate - drain - Vtn)*(gate - drain - Vtn)),
											logical_and(src > drain, gate - drain >= Vtn, src - drain <= gate - drain - Vtn, tI == -Sn*Kn*(gate - drain - Vtn - (src - drain)/2.0)*(src - drain)),
											logical_and(src <= drain, drain - src >= gate - src - Vtn, tI == 0.5*Sn*Kn*(gate - src - Vtn)*(gate - src - Vtn)),
											logical_and(src <= drain, drain - src <= gate - src - Vtn, tI == Sn*Kn*(gate - src - Vtn - (drain - src)/2.0)*(drain - src))))
	
	return constraints
Ejemplo n.º 21
0
from dreal.symbolic import Variable, logical_and, sin, cos
from dreal.api import CheckSatisfiability, Minimize

x = Variable("x")
y = Variable("y")
z = Variable("z")

f_sat = logical_and(0 <= x, x <= 10, 0 <= y, y <= 10, 0 <= z, z <= 10,
                    sin(x) + cos(y) == z)

result = CheckSatisfiability(f_sat, 0.001)
print(result)
Ejemplo n.º 22
0
def mvs_id(fetType, Vs, Vg, Vd, I, shape):
    params = model_params(fetType)
    version = params['version']
    mType = params['mType']
    W = params['W']
    Lgdr = params['Lgdr']
    dLg = params['dLg']
    Cg = params['Cg']
    etov = params['etov']
    delta = params['delta']
    n0 = params['n0']
    Rs0 = params['Rs0']
    Rd0 = params['Rd0']
    Cif = params['Cif']
    Cof = params['Cof']
    vxo = params['vxo'] * 1e7
    mu = params['mu']
    beta = params['beta']
    Tjun = params['Tjun']
    phib = params['phib']
    gamma = params['gamma']
    Vt0 = params['Vt0']
    alpha = params['alpha']
    mc = params['mc']
    CTM_select = params['CTM_select']
    CC = params['CC']
    nd = params['nd']
    zeta = params['zeta']

    # SMALL_VALUE
    SMALL_VALUE = 1e-10
    # LARGE_VALUE
    LARGE_VALUE = 40

    if mType == 1.0:
        Vb = 0.0
        Vdsi = Variable("Vdsin")
        Vgsi = Variable("Vgsin")
        Vbsi = Variable("Vbsin")
        n = Variable("nn")
        nphit = Variable("nphitn")
        phibVbs = Variable("phibVbsn")
        Vtpcorr = Variable("Vtpcorrn")
        eVgpre = Variable("eVgpren")
        FFpre = Variable("FFpren")
        ab = Variable("abn")
        Vcorr = Variable("Vcorrn")
        Vgscorr = Variable("Vgscorrn")
        Vbscorr = Variable("Vbscorrn")
        phibVbscorr = Variable("phibVbscorrn")
        Vt0bs = Variable("Vt0bsn")
        phibVbsi = Variable("phibVbsin")
        Vt0bs0 = Variable("Vt0bs0n")
        Vtp = Variable("Vtpn")
        Vtp0 = Variable("Vtp0n")
        eVg = Variable("eVgn")
        FF = Variable("FFn")
        eVg0 = Variable("eVg0n")
        FF0 = Variable("FF0n")
        Qref = Variable("Qrefn")
        eta = Variable("etan")
        Qinv_corr = Variable("Qinv_corrn")
        Vdsat = Variable("Vdsatn")
        VdsiVdsat = Variable("VdsiVdsatn")
        powVal = Variable("powValn")
        Fsat = Variable("Fsatn")

    else:
        Vb = 1.8
        Vdsi = Variable("Vdsip")
        Vgsi = Variable("Vgsip")
        Vbsi = Variable("Vbsip")
        n = Variable("np")
        nphit = Variable("nphitp")
        phibVbs = Variable("phibVbsp")
        Vtpcorr = Variable("Vtpcorrp")
        eVgpre = Variable("eVgprep")
        FFpre = Variable("FFprep")
        ab = Variable("abp")
        Vcorr = Variable("Vcorrp")
        Vgscorr = Variable("Vgscorrp")
        Vbscorr = Variable("Vbscorrp")
        phibVbscorr = Variable("phibVbscorrp")
        Vt0bs = Variable("Vt0bsp")
        phibVbsi = Variable("phibVbsip")
        Vt0bs0 = Variable("Vt0bs0p")
        Vtp = Variable("Vtpp")
        Vtp0 = Variable("Vtp0p")
        eVg = Variable("eVgp")
        FF = Variable("FFp")
        eVg0 = Variable("eVg0p")
        FF0 = Variable("FF0p")
        Qref = Variable("Qrefp")
        eta = Variable("etap")
        Qinv_corr = Variable("Qinv_corrp")
        Vdsat = Variable("Vdsatp")
        VdsiVdsat = Variable("VdsiVdsatp")
        powVal = Variable("powValp")
        Fsat = Variable("Fsatp")

    constraints = []

    if mType == 1:
        constraints.append(
            logical_or(logical_and(Vs <= Vd, Vdsi == mType * (Vd - Vs)),
                       logical_and(Vs > Vd, Vdsi == mType * (Vs - Vd))))
        constraints.append(
            logical_or(logical_and(Vs <= Vd, Vgsi == mType * (Vg - Vs)),
                       logical_and(Vs > Vd, Vgsi == mType * (Vg - Vd))))
        constraints.append(
            logical_or(logical_and(Vs <= Vd, Vbsi == mType * (Vb - Vs)),
                       logical_and(Vs > Vd, Vbsi == mType * (Vb - Vd))))

    else:
        constraints.append(
            logical_or(logical_and(Vd <= Vs, Vdsi == mType * (Vd - Vs)),
                       logical_and(Vd > Vs, Vdsi == mType * (Vs - Vd))))
        constraints.append(
            logical_or(logical_and(Vd <= Vs, Vgsi == mType * (Vg - Vs)),
                       logical_and(Vd > Vs, Vgsi == mType * (Vg - Vd))))
        constraints.append(
            logical_or(logical_and(Vd <= Vs, Vbsi == mType * (Vb - Vs)),
                       logical_and(Vd > Vs, Vbsi == mType * (Vb - Vd))))

    Cofs = 0 * (0.345e-12 / etov) * dLg / 2.0 + Cof
    # s-terminal outer fringing cap [F/cm]
    Cofd = 0 * (0.345e-12 / etov) * dLg / 2.0 + Cof
    # d-terminal outer fringing cap [F/cm]
    Leff = Lgdr - dLg
    # Effective channel length [cm]. After subtracting overlap lengths on s and d side
    kB = 8.617e-5
    # Boltzmann constant [eV/K]
    phit = kB * Tjun
    # Thermal voltage, kT/q [V]
    me = (9.1e-31) * mc
    # Carrier mass [Kg]

    constraints.append(n == n0 + nd * Vdsi)
    constraints.append(nphit == n * phit)
    aphit = alpha * phit

    constraints.append(phibVbs == dabs(phib - Vbsi))
    constraints.append(Vtpcorr == Vt0 + gamma * (sqrt(phibVbs) - sqrt(phib)) -
                       Vdsi * delta)
    constraints.append(eVgpre == exp((Vgsi - Vtpcorr) / (aphit * 1.5)))
    constraints.append(FFpre == 1.0 / (1.0 + eVgpre))
    constraints.append(ab == 2 * (1 - 0.99 * FFpre) * phit)
    constraints.append(Vcorr == (1.0 + 2.0 * delta) * (ab / 2.0) *
                       (exp(-Vdsi / ab)))
    constraints.append(Vgscorr == Vgsi + Vcorr)
    constraints.append(Vbscorr == Vbsi + Vcorr)
    constraints.append(phibVbscorr == dabs(phib - Vbscorr))
    constraints.append(Vt0bs == Vt0 + gamma * (sqrt(phibVbscorr) - sqrt(phib)))
    constraints.append(phibVbsi == dabs(phib - Vbsi))
    constraints.append(Vt0bs0 == Vt0 + gamma * (sqrt(phibVbsi) - sqrt(phib)))
    constraints.append(Vtp == Vt0bs - Vdsi * delta - 0.5 * aphit)
    constraints.append(Vtp0 == Vt0bs0 - Vdsi * delta - 0.5 * aphit)
    constraints.append(eVg == exp((Vgscorr - Vtp) / (aphit)))
    constraints.append(FF == 1.0 / (1.0 + eVg))
    constraints.append(eVg0 == exp((Vgsi - Vtp0) / (aphit)))
    constraints.append(Qref == Cg * nphit)
    constraints.append(eta == (Vgscorr - (Vt0bs - Vdsi * delta - FF * aphit)) /
                       (nphit))
    constraints.append(Qinv_corr == Qref * log(1.0 + exp(eta)))
    vx0 = vxo
    Vdsats = vx0 * Leff / mu
    constraints.append(Vdsat == Vdsats * (1.0 - FF) + phit * FF)
    constraints.append(VdsiVdsat == Vdsi / Vdsat)
    constraints.append(powVal == pow(VdsiVdsat, beta))
    constraints.append(Fsat == VdsiVdsat / (pow((1 + powVal), (1.0 / beta))))
    if mType == 1:
        constraints.append(
            logical_or(
                logical_and(Vs <= Vd,
                            I == Qinv_corr * vx0 * Fsat * W * mType * shape),
                logical_and(
                    Vs > Vd,
                    I == Qinv_corr * vx0 * Fsat * W * mType * -1.0 * shape)))
    else:
        constraints.append(
            logical_or(
                logical_and(Vd <= Vs,
                            I == Qinv_corr * vx0 * Fsat * W * mType * shape),
                logical_and(
                    Vd > Vs,
                    I == Qinv_corr * vx0 * Fsat * W * mType * -1.0 * shape)))

    return constraints
Ejemplo n.º 23
0
def rambusOscillatorTanh(numStages, g_cc=0.5, numSolutions="all", a=-5.0):
    epsilon = 1e-14
    start = time.time()
    g_fwd = 1.0
    lenV = numStages * 2
    vs = []
    vfwds = []
    vccs = []
    for i in range(lenV):
        vs.append(Variable("v" + str(i)))
        vfwds.append(Variable("vfwd" + str(i)))
        vccs.append(Variable("vcc" + str(i)))

    allConstraints = []

    # Store rambus oscillator constraints
    for i in range(lenV):
        allConstraints.append(vs[i] >= -1)
        allConstraints.append(vs[i] <= 1)
        fwdInd = (i - 1) % lenV
        ccInd = (i + lenV // 2) % lenV
        allConstraints.append(vfwds[i] == tanh(a * vs[fwdInd]))
        allConstraints.append(vccs[i] == tanh(a * vs[ccInd]))
        allConstraints.append(g_fwd * vfwds[i] + (-g_fwd - g_cc) * vs[i] +
                              g_cc * vccs[i] == 0)

    allSolutions = []
    while True:
        if numSolutions != "all" and len(allSolutions) == numSolutions:
            break

        # Store constraints pruning search space so that
        # old hyperrectangles are not considered
        excludingConstraints = []
        for solution in allSolutions:
            singleExcludingConstraints = []
            for i in range(lenV):
                singleExcludingConstraints.append(vs[i] < solution[i][0])
                singleExcludingConstraints.append(vs[i] > solution[i][1])
            excludingConstraints.append(singleExcludingConstraints)

        # Add all the rambus oscillator constraints
        f_sat = logical_and(*allConstraints)
        # Add constraints so that old hyperrectangles are not considered
        if len(excludingConstraints) > 0:
            for constraints in excludingConstraints:
                f_sat = logical_and(f_sat, logical_or(*constraints))

        #print ("f_sat")
        #print (f_sat)
        result = CheckSatisfiability(f_sat, epsilon)
        #print (result)
        if result is None:
            break
        hyper = np.zeros((lenV, 2))
        for i in range(lenV):
            hyper[i, :] = [
                result[vs[i]].lb() - 2 * epsilon,
                result[vs[i]].ub() + 2 * epsilon
            ]

        #print ("hyper", hyper)
        allSolutions.append(hyper)

        print("num solutions found", len(allSolutions))

    end = time.time()
    print("time taken", end - start)
    return allSolutions
Ejemplo n.º 24
0
 def phi(x):
     return logical_and(0 <= x, x <= math.pi)
Ejemplo n.º 25
0
# -*- coding: utf-8 -*-
from dreal.symbolic import Variable, logical_and, sin, cos
from dreal.symbolic import logical_imply, forall
from dreal.api import CheckSatisfiability, Minimize
from dreal.util import Box
import math
import unittest

x = Variable("x")
y = Variable("y")
z = Variable("z")

f_sat = logical_and(0 <= x, x <= 10, 0 <= y, y <= 10, 0 <= z, z <= 10,
                    sin(x) + cos(y) == z)

f_unsat = logical_and(3 <= x, x <= 4, 4 <= y, y <= 5, 5 <= z, z <= 6,
                      sin(x) + cos(y) == z)

objective = 2 * x * x + 6 * x + 5
constraint = logical_and(-10 <= x, x <= 10)


class ApiTest(unittest.TestCase):
    def test_delta_sat(self):
        result = CheckSatisfiability(f_sat, 0.001)
        self.assertEqual(type(result), Box)

        b = Box([x, y, z])
        result = CheckSatisfiability(f_sat, 0.001, b)
        self.assertEqual(result, True)
        self.assertTrue(b[x].diam() < 0.1)
Ejemplo n.º 26
0
def schmittTriggerScMosfet(inputVoltage, numSolutions="all"):
    epsilon = 1e-14
    start = time.time()

    lenV = 3
    Vdd = 1.0
    sn = 3
    sp = 2 * sn

    vs = []
    tIs = []
    nIs = []

    for i in range(lenV):
        vs.append(Variable("v" + str(i)))
        nIs.append(Variable("nI" + str(i)))

    for i in range(lenV * 2):
        tIs.append(Variable("tI" + str(i)))

    allConstraints = []
    for i in range(lenV):
        allConstraints.append(vs[i] >= 0.0)
        allConstraints.append(vs[i] <= Vdd)
    allConstraints += mvs_id('n', 0.0, inputVoltage, vs[1], tIs[0], sn)
    allConstraints += mvs_id('n', vs[1], inputVoltage, vs[0], tIs[1], sn)
    allConstraints += mvs_id('n', vs[1], vs[0], Vdd, tIs[2], sn)
    allConstraints += mvs_id('p', Vdd, inputVoltage, vs[2], tIs[3], sp)
    allConstraints += mvs_id('p', vs[2], inputVoltage, vs[0], tIs[4], sp)
    allConstraints += mvs_id('p', vs[2], vs[0], 0.0, tIs[5], sp)
    allConstraints.append(nIs[0] == -tIs[4] - tIs[1])
    allConstraints.append(nIs[1] == -tIs[0] + tIs[1] + tIs[2])
    allConstraints.append(nIs[2] == -tIs[3] + tIs[5] + tIs[4])
    for i in range(lenV):
        allConstraints.append(nIs[i] == 0.0)

    allSolutions = []
    while True:
        if numSolutions != "all" and len(allSolutions) == numSolutions:
            break

        # Store constraints pruning search space so that
        # old hyperrectangles are not considered
        excludingConstraints = []
        for solution in allSolutions:
            singleExcludingConstraints = []
            for i in range(lenV):
                singleExcludingConstraints.append(vs[i] < solution[i][0])
                singleExcludingConstraints.append(vs[i] > solution[i][1])
            excludingConstraints.append(singleExcludingConstraints)

        #print ("allConstraints")
        #print (allConstraints)
        f_sat = logical_and(*allConstraints)
        if len(excludingConstraints) > 0:
            for constraints in excludingConstraints:
                f_sat = logical_and(f_sat, logical_or(*constraints))

        #print ("f_sat")
        #print (f_sat)
        result = CheckSatisfiability(f_sat, epsilon)
        #print (result)
        if result is None:
            break
        hyper = np.zeros((lenV, 2))
        for i in range(lenV):
            hyper[i, :] = [
                result[vs[i]].lb() - 2 * epsilon,
                result[vs[i]].ub() + 2 * epsilon
            ]

        #print ("hyper", hyper)
        allSolutions.append(hyper)

        print("num solutions found", len(allSolutions))

    end = time.time()
    print("time taken", end - start)
    return allSolutions
Ejemplo n.º 27
0
def rambusOscillatorLcMosfet(numStages, numSolutions = "all", g_cc = 0.5, Vtp = -0.4, Vtn = 0.4, Vdd = 1.8, Kn = 270*1e-6, Kp = -90*1e-6, Sn = 3.0):
	epsilon = 1e-14
	start = time.time()
	#print ("Vtp", Vtp, "Vtn", Vtn, "Vdd", Vdd, "Kn", Kn, "Kp", Kp, "Sn", Sn)
	g_fwd = 1.0
	lenV = numStages*2
	Sp = 2*Sn

	vs = []
	ifwdNs = []
	ifwdPs = []
	iccNs = []
	iccPs = []
	for i in range(lenV):
		vs.append(Variable("v" + str(i)))
		ifwdNs.append(Variable("ifwdN" + str(i)))
		ifwdPs.append(Variable("ifwdP" + str(i)))
		iccNs.append(Variable("iccN" + str(i)))
		iccPs.append(Variable("iccP" + str(i)))

	allConstraints = []	
	for i in range(lenV):
		allConstraints.append(vs[i] >= 0.0)
		allConstraints.append(vs[i] <= Vdd)
		allConstraints.append(g_fwd*(-ifwdNs[i]-ifwdPs[i]) + g_cc*(-iccNs[i]-iccPs[i]) == 0)
		fwdInd = (i-1)%lenV
		ccInd = (i+lenV//2)%lenV
		fwdConstraints = nFet(Vtn, Vdd, Kn, Sn, 0.0, vs[fwdInd], vs[i], ifwdNs[i])
		fwdConstraints += pFet(Vtp, Vdd, Kp, Sp, Vdd, vs[fwdInd], vs[i], ifwdPs[i])
		ccConstraints = nFet(Vtn, Vdd, Kn, Sn, 0.0, vs[ccInd], vs[i], iccNs[i])
		ccConstraints += pFet(Vtp, Vdd, Kp, Sp, Vdd, vs[ccInd], vs[i], iccPs[i])
		allConstraints += fwdConstraints + ccConstraints

	allSolutions = []
	while True:
		if numSolutions != "all" and len(allSolutions) == numSolutions:
			break
		
		# Store constraints pruning search space so that
		# old hyperrectangles are not considered
		excludingConstraints = []
		for solution in allSolutions:
			singleExcludingConstraints = []
			for i in range(lenV):
				singleExcludingConstraints.append(vs[i] < solution[i][0])
				singleExcludingConstraints.append(vs[i] > solution[i][1])
			excludingConstraints.append(singleExcludingConstraints)
		
		#print ("allConstraints")
		#print (allConstraints)
		f_sat = logical_and(*allConstraints)
		if len(excludingConstraints) > 0:
			for constraints in excludingConstraints:
				f_sat = logical_and(f_sat, logical_or(*constraints))
		
		#print ("f_sat")
		#print (f_sat)
		result = CheckSatisfiability(f_sat, epsilon)
		#print (result)
		if result is None:
			break
		hyper = np.zeros((lenV,2))
		for i in range(lenV):
			hyper[i,:] = [result[vs[i]].lb() - 1000*epsilon, result[vs[i]].ub() + 1000*epsilon]

		#print ("hyper", hyper)
		allSolutions.append(hyper)

		print ("num solutions found", len(allSolutions))


	end = time.time()
	print ("time taken", end - start)
	return allSolutions
Ejemplo n.º 28
0
def inverterLoopLcMosfet(numInverters, numSolutions = "all", Vtp = -0.4, Vtn = 0.4, Vdd = 1.8, Kn = 270*1e-6, Kp = -90*1e-6, Sn = 3.0):
	epsilon = 1e-14
	start = time.time()
	#print ("Vtp", Vtp, "Vtn", Vtn, "Vdd", Vdd, "Kn", Kn, "Kp", Kp, "Sn", Sn)
	Sp = 2*Sn

	vs = []
	iNs = []
	iPs = []

	for i in range(numInverters):
		vs.append(Variable("v" + str(i)))
		iNs.append(Variable("iN" + str(i)))
		iPs.append(Variable("iP" + str(i)))

	allConstraints = []	
	for i in range(numInverters):
		allConstraints.append(vs[i] >= 0.0)
		allConstraints.append(vs[i] <= Vdd)
		allConstraints.append(-iNs[i]-iPs[i] == 0)
		inputInd = i
		outputInd = (i+1)%numInverters
		allConstraints += nFet(Vtn, Vdd, Kn, Sn, 0.0, vs[inputInd], vs[outputInd], iNs[i])
		allConstraints += pFet(Vtp, Vdd, Kp, Sp, Vdd, vs[inputInd], vs[outputInd], iPs[i])

	allSolutions = []
	while True:
		if numSolutions != "all" and len(allSolutions) == numSolutions:
			break
		
		# Store constraints pruning search space so that
		# old hyperrectangles are not considered
		excludingConstraints = []
		for solution in allSolutions:
			singleExcludingConstraints = []
			for i in range(numInverters):
				singleExcludingConstraints.append(vs[i] < solution[i][0])
				singleExcludingConstraints.append(vs[i] > solution[i][1])
			excludingConstraints.append(singleExcludingConstraints)
		
		#print ("allConstraints")
		#print (allConstraints)
		f_sat = logical_and(*allConstraints)
		if len(excludingConstraints) > 0:
			for constraints in excludingConstraints:
				f_sat = logical_and(f_sat, logical_or(*constraints))
		
		#print ("f_sat")
		#print (f_sat)
		result = CheckSatisfiability(f_sat, epsilon)
		#print (result)
		if result is None:
			break
		hyper = np.zeros((numInverters,2))
		for i in range(numInverters):
			hyper[i,:] = [result[vs[i]].lb() - 1000*epsilon, result[vs[i]].ub() + 1000*epsilon]

		#print ("hyper", hyper)
		allSolutions.append(hyper)

		print ("num solutions found", len(allSolutions))


	end = time.time()
	print ("time taken", end - start)
	return allSolutions
Ejemplo n.º 29
0
def schmittTriggerLcMosfet(inputVoltage, Vtp = -0.4, Vtn = 0.4, Vdd = 1.8, Kn = 270*1e-6, Kp = -90*1e-6, Sn = 3.0, numSolutions = "all"):
	epsilon = 1e-14
	start = time.time()
	#print ("Vtp", Vtp, "Vtn", Vtn, "Vdd", Vdd, "Kn", Kn, "Kp", Kp, "Sn", Sn)
	Sp = Sn *2.0

	lenV = 3

	vs = []
	tIs = []
	nIs = []

	for i in range(lenV):
		vs.append(Variable("v" + str(i)))
		nIs.append(Variable("nI" + str(i)))
	
	for i in range(lenV*2):
		tIs.append(Variable("tI" + str(i)))

	allConstraints = []	
	for i in range(lenV):
		allConstraints.append(vs[i] >= 0.0)
		allConstraints.append(vs[i] <= 1.8)
	allConstraints += nFetLeak(Vtn, Vdd, Kn, Sn, 0.0, inputVoltage, vs[1], tIs[0])
	allConstraints += nFetLeak(Vtn, Vdd, Kn, Sn, vs[1], inputVoltage, vs[0], tIs[1])
	allConstraints += nFetLeak(Vtn, Vdd, Kn, Sn, vs[1], vs[0], Vdd, tIs[2])
	allConstraints += pFetLeak(Vtp, Vdd, Kp, Sp, Vdd, inputVoltage, vs[2], tIs[3])
	allConstraints += pFetLeak(Vtp, Vdd, Kp, Sp, vs[2], inputVoltage, vs[0], tIs[4])
	allConstraints += pFetLeak(Vtp, Vdd, Kp, Sp, vs[2], vs[0], 0.0, tIs[5])
	allConstraints.append(nIs[0] == -tIs[4] - tIs[1])
	allConstraints.append(nIs[1] == -tIs[0] + tIs[1] + tIs[2])
	allConstraints.append(nIs[2] == -tIs[3] + tIs[5] + tIs[4])
	for i in range(lenV):
		allConstraints.append(nIs[i] == 0.0)

	allSolutions = []
	while True:
		if numSolutions != "all" and len(allSolutions) == numSolutions:
			break
		
		# Store constraints pruning search space so that
		# old hyperrectangles are not considered
		excludingConstraints = []
		for solution in allSolutions:
			singleExcludingConstraints = []
			for i in range(lenV):
				singleExcludingConstraints.append(vs[i] < solution[i][0])
				singleExcludingConstraints.append(vs[i] > solution[i][1])
			excludingConstraints.append(singleExcludingConstraints)
		
		#print ("allConstraints")
		#print (allConstraints)
		#print ("numConstraints", len(allConstraints))

		f_sat = logical_and(*allConstraints)
		if len(excludingConstraints) > 0:
			for constraints in excludingConstraints:
				f_sat = logical_and(f_sat, logical_or(*constraints))
		
		#print ("f_sat")
		#print (f_sat)
		result = CheckSatisfiability(f_sat, epsilon)
		#print (result)
		if result is None:
			break
		hyper = np.zeros((lenV,2))
		for i in range(lenV):
			hyper[i,:] = [result[vs[i]].lb() - 1000*epsilon, result[vs[i]].ub() + 1000*epsilon]

		#print ("hyper", hyper)
		allSolutions.append(hyper)

		print ("num solutions found", len(allSolutions))


	end = time.time()
	print ("time taken", end - start)
	return allSolutions
Ejemplo n.º 30
0
 def reducer(vars_bounds, item):
     (var, bound) = make_bound(*item)
     vars = vars_bounds[0]
     bounds = vars_bounds[1]
     return (vars + [var], logical_and(bounds, bound))