Example #1
0
    def __init__(self, *args, **kwds):
        AbstractModel.__init__(self, *args, **kwds)
        self.processInputs = dict()
        self.processOutputs = dict()
        self.processLoans = dict()
        self.activeFlow_psditvo = None
        self.activeCurtailment_psditvo = None
        self.activeActivity_ptv = None
        self.activeCapacity_tv = None
        self.activeCapacityAvailable_pt = None

        self.commodityDStreamProcess = dict(
        )  # The downstream process of a commodity during a period
        self.commodityUStreamProcess = dict(
        )  # The upstream process of a commodity during a period
        self.ProcessInputsByOutput = dict()
        self.ProcessOutputsByInput = dict()
        self.processTechs = dict()
        self.processReservePeriods = dict()
        self.processVintages = dict()
        self.baseloadVintages = dict()
        self.curtailmentVintages = dict()
        self.storageVintages = dict()
        self.rampVintages = dict()
        self.inputsplitVintages = dict()
        self.outputsplitVintages = dict()
        self.ProcessByPeriodAndOutput = dict()
Example #2
0
	def __init__( self, *args, **kwds ):
		AbstractModel.__init__( self, *args, **kwds )
		self.helper_processInputs  = dict()
		self.helper_processOutputs = dict()
		self.helper_processVintages = dict()
		self.helper_processLoans = dict()
		self.helper_activeFlow_psditvo = None
		self.helper_activeActivity_ptv = None
		self.helper_activeCapacity_tv = None
		self.helper_activeCapacityAvailable_pt = None

		self.helper_commodityDStreamProcess  = dict() # The downstream process of a commodity during a period
		self.helper_commodityUStreamProcess  = dict() # The upstream process of a commodity during a period
		self.helper_ProcessInputsByOutput = dict()
		self.helper_ProcessOutputsByInput = dict()
Example #3
0
    def build_mip(self):
        """Build the model <b>object</b>."""
        self.model = AbstractModel()

        self.model.J = Set()
        self.model.K = Set(self.model.J)

        def jk_init(m):
            return [(j, k) for j in m.J for k in m.K[j]]

        self.model.JK = Set(initialize=jk_init, dimen=None)

        self.model.y_pred = Param()
        self.model.epsilon = Param()
        self.model.max_cost = Var()
        self.model.w = Param(self.model.J)
        self.model.a = Param(self.model.JK)
        self.model.c = Param(self.model.JK)
        self.model.u = Var(self.model.JK, within=Binary)

        # Make sure only one action is on at a time.
        def c1Rule(m, j):
            return (sum([m.u[j, k] for k in m.K[j]])) == 1

        # 2.b: Action sets must flip the prediction of a linear classifier.
        def c2Rule(m):
            return (sum((m.u[j, k] * m.a[j, k] * m.w[j])
                        for j, k in m.JK) >= -m.y_pred)

        # instantiate max cost
        def maxcost_rule(m, j, k):
            return m.max_cost >= (m.u[j, k] * m.c[j, k])

        # Set up objective for total sum.
        def obj_rule_percentile(m):
            return sum(m.u[j, k] * m.c[j, k] for j, k in m.JK)

        # Set up objective for max cost.
        def obj_rule_max(m):
            return (sum(m.epsilon * m.u[j, k] * m.c[j, k]
                        for j, k in m.JK) + (1 - m.epsilon) * m.max_cost)

        ##
        self.model.g = Objective(rule=obj_rule_max, sense=minimize)
        self.model.c1 = Constraint(self.model.J, rule=c1Rule)
        self.model.c2 = Constraint(rule=c2Rule)
        self.model.c3 = Constraint(self.model.JK, rule=maxcost_rule)
        self.built = True
Example #4
0
"""
Created on Thu Dec 19 16:12:21 2019

@author: Silvia
"""

from __future__ import division

from pyomo.opt import SolverFactory
from pyomo.core import AbstractModel
from pyomo.dataportal.DataPortal import DataPortal
from pyomo.environ import *
import pandas as pd
from datetime import datetime
############ Create abstract model ###########
model = AbstractModel()
data = DataPortal()

# ####################Define sets#####################

#Name of all the nodes (primary and secondary substations)
model.N = Set()
data.load(filename='nodes.csv', set=model.N)  #first row is not read

#Allowed connections
model.links = Set(dimen=2)  #in the csv the values must be delimited by commas
data.load(filename='links.csv', set=model.links)

#Nodes are divided into two sets, as suggested in https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Sets.html:
# NodesOut[nodes] gives for each node all nodes that are connected to it via outgoing links
# NodesIn[nodes] gives for each node all nodes that are connected to it via ingoing links
Example #5
0
def CreateAbstractScenarioTreeModel():
    from pyomo.core import (AbstractModel, Set, Param, Boolean)

    model = AbstractModel()

    # all set/parameter values are strings, representing the
    # names of various entities/variables.

    model.Stages = Set(ordered=True)
    model.Nodes = Set(ordered=True)

    model.NodeStage = Param(model.Nodes,
                            within=model.Stages,
                            mutable=True)
    model.Children = Set(model.Nodes,
                         within=model.Nodes,
                         initialize=[],
                         ordered=True)
    model.ConditionalProbability = Param(model.Nodes,
                                         mutable=True)

    model.Scenarios = Set(ordered=True)
    model.ScenarioLeafNode = Param(model.Scenarios,
                                   within=model.Nodes,
                                   mutable=True)

    model.StageVariables = Set(model.Stages,
                               initialize=[],
                               ordered=True)

    model.NodeVariables = Set(model.Nodes,
                              initialize=[],
                              ordered=True)

    model.StageCost = Param(model.Stages,
                            mutable=True,
                            default=None)
    model.NodeCost = Param(model.Nodes,
                           mutable=True,
                           default=None)

    # DEPRECATED
    model.StageCostVariable = Param(model.Stages,
                                    mutable=True)

    # it is often the case that a subset of the stage variables are strictly "derived"
    # variables, in that their values are computable once the values of other variables
    # in that stage are known. it generally useful to know which variables these are,
    # as it is unnecessary to post non-anticipativity constraints for these variables.
    # further, attempting to force non-anticipativity - either implicitly or explicitly -
    # on these variables can cause issues with decomposition algorithms.
    model.StageDerivedVariables = Set(model.Stages,
                                      initialize=[],
                                      ordered=True)
    model.NodeDerivedVariables = Set(model.Nodes,
                                     initialize=[],
                                     ordered=True)

    # scenario data can be populated in one of two ways. the first is "scenario-based",
    # in which a single .dat file contains all of the data for each scenario. the .dat
    # file prefix must correspond to the scenario name. the second is "node-based",
    # in which a single .dat file contains only the data for each node in the scenario
    # tree. the node-based method is more compact, but the scenario-based method is
    # often more natural when parameter data is generated via simulation. the default
    # is scenario-based.
    model.ScenarioBasedData = Param(within=Boolean,
                                    default=True,
                                    mutable=True)

    # do we bundle, and if so, how?
    model.Bundling = Param(within=Boolean,
                           default=False,
                           mutable=True)

    # bundle names
    model.Bundles = Set(ordered=True)
    model.BundleScenarios = Set(model.Bundles,
                                ordered=True)

    return model
Example #6
0
# -----------------------------------------------------------------------------

from pyomo.core import AbstractModel, Set, Param, PositiveReals
from pyomo.core import NonNegativeIntegers, Binary, Var, summation
# -----------------------------------------------------------------------------
#                            MOTIVATION FROM WIFE
# -----------------------------------------------------------------------------

''' my husband is amazingly sexy! RAWR!! love, sara '''


# -----------------------------------------------------------------------------
#                               INITIATE MODEL
# -----------------------------------------------------------------------------

model = AbstractModel()

# -----------------------------------------------------------------------------
#                           DECLARE MODEL PARAMETERS
# -----------------------------------------------------------------------------

# Model Indices

model.STORES = Set()
model.PRODUCTS = Set()
model.VENDORS = Set()
model.PUTAWAY = Set()
model.PICKING = Set()
model.TIMES = Set()
model.PICKING = Set()
model.PUTAWAY = Set()
Example #7
0
#  This software is distributed under the 3-clause BSD License.
#  ___________________________________________________________________________

#
# Imports
#

from pyomo.core import AbstractModel, Set, Param, Var, PositiveReals, NonNegativeReals, NonNegativeIntegers, Constraint, Objective, minimize

infinity = float('inf')

#
# Model
#

model = AbstractModel()

model.FOOD = Set()

model.cost = Param(model.FOOD, within=PositiveReals)

model.f_min = Param(model.FOOD, within=NonNegativeReals, default=0.0)

MAX_FOOD_SUPPLY = 20.0 # McDonald's doesn't stock infinite food
def f_max_validate (model, value, j):
    return model.f_max[j] > model.f_min[j]
model.f_max = Param(model.FOOD, validate=f_max_validate, default=MAX_FOOD_SUPPLY)

# Unneeded vars - they're in the .dat file, so we list them here
model.NUTR = Set()
model.n_min = Param(model.NUTR, within=NonNegativeReals, default=0.0)
Example #8
0
    def test_construct2(self):
        model = AbstractModel()
        model.a = Set(initialize=[1,2,3])
        model.A = Param(initialize=1)
        model.B = Param(model.a)
        model.x = Var(initialize=1, within=Reals, dense=True)
        model.y = Var(model.a, initialize=1, within=Reals, dense=True)
        model.obj = Objective(rule=lambda model: model.x+model.y[1])
        model.obj2 = Objective(model.a,rule=lambda model, i: i+model.x+model.y[1])
        model.con = Constraint(rule=rule1)
        model.con2 = Constraint(model.a, rule=rule2)
        instance = model.create_instance()
        expr = instance.x + 1

        OUTPUT = open(join(currdir, "display2.out"), "w")
        display(instance,ostream=OUTPUT)
        display(instance.obj,ostream=OUTPUT)
        display(instance.x,ostream=OUTPUT)
        display(instance.con,ostream=OUTPUT)
        OUTPUT.write(expr.to_string())
        model = AbstractModel()
        instance = model.create_instance()
        display(instance,ostream=OUTPUT)
        OUTPUT.close()
        try:
            display(None)
            self.fail("test_construct - expected TypeError")
        except TypeError:
            pass
        _out, _txt = join(currdir, "display2.out"), join(currdir, "display2.txt")
        self.assertTrue(cmp(_out, _txt),
                        msg="Files %s and %s differ" % (_out, _txt))
Example #9
0
# Farmer: rent out version has a scalar root node var
# note: this will minimize
#
# Imports
#

from pyomo.core import (AbstractModel, Set, Param, Var, sum_product,
                        PositiveReals, NonNegativeReals, Constraint, Objective,
                        Expression, minimize)

#
# Model
#

model = AbstractModel()

#
# Parameters
#

model.CROPS = Set()

model.TOTAL_ACREAGE = Param(within=PositiveReals)

model.PriceQuota = Param(model.CROPS, within=PositiveReals)

model.SubQuotaSellingPrice = Param(model.CROPS, within=PositiveReals)


def super_quota_selling_price_validate(model, value, i):
Example #10
0
    def test_construct(self):
        model = AbstractModel()
        model.a = Set(initialize=[1, 2, 3])
        model.A = Param(initialize=1)
        model.B = Param(model.a)
        model.x = Var(initialize=1, within=Reals, dense=False)
        model.y = Var(model.a, initialize=1, within=Reals, dense=False)
        model.obj = Objective(rule=lambda model: model.x + model.y[1])
        model.obj2 = Objective(model.a,
                               rule=lambda model, i: i + model.x + model.y[1])
        model.con = Constraint(rule=rule1)
        model.con2 = Constraint(model.a, rule=rule2)
        instance = model.create_instance()
        expr = instance.x + 1

        OUTPUT = open(currdir + "/display.out", "w")
        display(instance, ostream=OUTPUT)
        display(instance.obj, ostream=OUTPUT)
        display(instance.x, ostream=OUTPUT)
        display(instance.con, ostream=OUTPUT)
        OUTPUT.write(expr.to_string())
        model = AbstractModel()
        instance = model.create_instance()
        display(instance, ostream=OUTPUT)
        OUTPUT.close()
        try:
            display(None)
            self.fail("test_construct - expected TypeError")
        except TypeError:
            pass
        self.assertFileEqualsBaseline(currdir + "/display.out",
                                      currdir + "/display.txt")
Example #11
0
    def _create_using(self, model, **kwds):
        """
        Tranform a model to its Lagrangian dual.
        """

        # Optional naming schemes for dual variables and constraints
        constraint_suffix = kwds.pop("dual_constraint_suffix", "_constraint")
        variable_prefix = kwds.pop("dual_variable_prefix", "p_")

        # Optional naming schemes to pass to StandardForm
        sf_kwds = {}
        sf_kwds["slack_names"] = kwds.pop("slack_names", "auxiliary_slack")
        sf_kwds["excess_names"] = kwds.pop("excess_names", "auxiliary_excess")
        sf_kwds["lb_names"] = kwds.pop("lb_names", "_lower_bound")
        sf_kwds["ub_names"] = kwds.pop("ub_names", "_upper_bound")
        sf_kwds["pos_suffix"] = kwds.pop("pos_suffix", "_plus")
        sf_kwds["neg_suffix"] = kwds.pop("neg_suffix", "_minus")

        # Get the standard form model
        sf_transform = StandardForm()
        sf = sf_transform(model, **sf_kwds)

        # Roughly, parse the objectives and constraints to form A, b, and c of
        #
        # min  c'x
        # s.t. Ax  = b
        #       x >= 0
        #
        # and create a new model from them.

        # We use sparse matrix representations

        # {constraint_name: {variable_name: coefficient}}
        A = _sparse(lambda: _sparse(0))

        # {constraint_name: coefficient}
        b = _sparse(0)

        # {variable_name: coefficient}
        c = _sparse(0)

        # Walk constaints
        for (con_name, con_array) in sf.component_map(Constraint,
                                                      active=True).items():
            for con in (con_array[ndx] for ndx in con_array._index):
                # The qualified constraint name
                cname = "%s%s" % (variable_prefix, con.local_name)

                # Process the body of the constraint
                body_terms = process_canonical_repn(
                    generate_standard_repn(con.body))

                # Add a numeric constant to the 'b' vector, if present
                b[cname] -= body_terms.pop(None, 0)

                # Add variable coefficients to the 'A' matrix
                row = _sparse(0)
                for (vname, coef) in body_terms.items():
                    row["%s%s" % (vname, constraint_suffix)] += coef

                # Process the upper bound of the constraint. We rely on
                # StandardForm to produce equality constraints, thus
                # requiring us only to check the lower bounds.
                lower_terms = process_canonical_repn(
                    generate_standard_repn(con.lower))

                # Add a numeric constant to the 'b' matrix, if present
                b[cname] += lower_terms.pop(None, 0)

                # Add any variables to the 'A' matrix, if present
                for (vname, coef) in lower_terms.items():
                    row["%s%s" % (vname, constraint_suffix)] -= coef

                A[cname] = row

        # Walk objectives. Multiply all coefficients by the objective's 'sense'
        # to convert maximizing objectives to minimizing ones.
        for (obj_name, obj_array) in sf.component_map(Objective,
                                                      active=True).items():
            for obj in (obj_array[ndx] for ndx in obj_array._index):
                # The qualified objective name

                # Process the objective
                terms = process_canonical_repn(generate_standard_repn(
                    obj.expr))

                # Add coefficients
                for (name, coef) in terms.items():
                    c["%s%s" %
                      (name, constraint_suffix)] += coef * obj_array.sense

        # Form the dual
        dual = AbstractModel()

        # Make constraint index set
        constraint_set_init = []
        for (var_name, var_array) in sf.component_map(Var,
                                                      active=True).items():
            for var in (var_array[ndx] for ndx in var_array._index):
                constraint_set_init.append("%s%s" %
                                           (var.local_name, constraint_suffix))

        # Make variable index set
        variable_set_init = []
        dual_variable_roots = []
        for (con_name, con_array) in sf.component_map(Constraint,
                                                      active=True).items():
            for con in (con_array[ndx] for ndx in con_array._index):
                dual_variable_roots.append(con.local_name)
                variable_set_init.append("%s%s" %
                                         (variable_prefix, con.local_name))

        # Create the dual Set and Var objects
        dual.var_set = Set(initialize=variable_set_init)
        dual.con_set = Set(initialize=constraint_set_init)
        dual.vars = Var(dual.var_set)

        # Make the dual constraints
        def constraintRule(A, c, ndx, model):
            return sum(A[v][ndx] * model.vars[v] for v in model.var_set) <= \
                   c[ndx]

        dual.cons = Constraint(dual.con_set,
                               rule=partial(constraintRule, A, c))

        # Make the dual objective (maximizing)
        def objectiveRule(b, model):
            return sum(b[v] * model.vars[v] for v in model.var_set)

        dual.obj = Objective(rule=partial(objectiveRule, b), sense=maximize)

        return dual.create()
Example #12
0
def CreateAbstractScenarioTreeModel():
    from pyomo.core import (AbstractModel, Set, Param, Boolean)

    model = AbstractModel()

    # all set/parameter values are strings, representing the
    # names of various entities/variables.

    model.Stages = Set(ordered=True)
    model.Nodes = Set(ordered=True)

    model.NodeStage = Param(model.Nodes,
                            within=model.Stages,
                            mutable=True)
    model.Children = Set(model.Nodes,
                         within=model.Nodes,
                         initialize=[],
                         ordered=True)
    model.ConditionalProbability = Param(model.Nodes,
                                         mutable=True)

    model.Scenarios = Set(ordered=True)
    model.ScenarioLeafNode = Param(model.Scenarios,
                                   within=model.Nodes,
                                   mutable=True)

    model.StageVariables = Set(model.Stages,
                               initialize=[],
                               ordered=True)

    model.NodeVariables = Set(model.Nodes,
                              initialize=[],
                              ordered=True)

    model.StageCost = Param(model.Stages,
                            mutable=True,
                            default=None)
    model.NodeCost = Param(model.Nodes,
                           mutable=True,
                           default=None)

    # DEPRECATED
    model.StageCostVariable = Param(model.Stages,
                                    mutable=True)

    # it is often the case that a subset of the stage variables are strictly "derived"
    # variables, in that their values are computable once the values of other variables
    # in that stage are known. it generally useful to know which variables these are,
    # as it is unnecessary to post non-anticipativity constraints for these variables.
    # further, attempting to force non-anticipativity - either implicitly or explicitly -
    # on these variables can cause issues with decomposition algorithms.
    model.StageDerivedVariables = Set(model.Stages,
                                      initialize=[],
                                      ordered=True)
    model.NodeDerivedVariables = Set(model.Nodes,
                                     initialize=[],
                                     ordered=True)

    # scenario data can be populated in one of two ways. the first is "scenario-based",
    # in which a single .dat file contains all of the data for each scenario. the .dat
    # file prefix must correspond to the scenario name. the second is "node-based",
    # in which a single .dat file contains only the data for each node in the scenario
    # tree. the node-based method is more compact, but the scenario-based method is
    # often more natural when parameter data is generated via simulation. the default
    # is scenario-based.
    model.ScenarioBasedData = Param(within=Boolean,
                                    default=True,
                                    mutable=True)

    # do we bundle, and if so, how?
    model.Bundling = Param(within=Boolean,
                           default=False,
                           mutable=True)

    # bundle names
    model.Bundles = Set(ordered=True)
    model.BundleScenarios = Set(model.Bundles,
                                ordered=True)

    return model
Example #13
0
class _RecourseBuilderPyomo(_RecourseBase):
    def __init__(self,
                 action_set,
                 coefficients,
                 intercept=0.0,
                 x=None,
                 **kwargs):
        self.built = False
        super().__init__(action_set=action_set,
                         coefficients=coefficients,
                         intercept=intercept,
                         x=x,
                         **kwargs)
        return self

    def _check_mip_build_info(self, build_info):
        ## TODO
        return True

    def _get_mip_build_info(self,
                            cost_function_type='percentile',
                            validate=True):
        build_info, indices = super()._get_mip_build_info(
            cost_function_type=cost_function_type, validate=validate)

        ## pyomo-specific processing
        c = []
        a = []
        for name in self.action_set._names:
            c.append(build_info.get(name, {'costs': []})['costs'])
            a.append(build_info.get(name, {'actions': []})['actions'])

        output_build_info = {}
        output_build_info['a'] = a
        output_build_info['c'] = c
        output_build_info['epsilon'] = min(indices['cost_df']) / sum(
            indices['cost_ub'])

        return output_build_info, indices

    def build_mip(self):
        """Build the model <b>object</b>."""
        self.model = AbstractModel()

        self.model.J = Set()
        self.model.K = Set(self.model.J)

        def jk_init(m):
            return [(j, k) for j in m.J for k in m.K[j]]

        self.model.JK = Set(initialize=jk_init, dimen=None)

        self.model.y_pred = Param()
        self.model.epsilon = Param()
        self.model.max_cost = Var()
        self.model.w = Param(self.model.J)
        self.model.a = Param(self.model.JK)
        self.model.c = Param(self.model.JK)
        self.model.u = Var(self.model.JK, within=Binary)

        # Make sure only one action is on at a time.
        def c1Rule(m, j):
            return (sum([m.u[j, k] for k in m.K[j]])) == 1

        # 2.b: Action sets must flip the prediction of a linear classifier.
        def c2Rule(m):
            return (sum((m.u[j, k] * m.a[j, k] * m.w[j])
                        for j, k in m.JK) >= -m.y_pred)

        # instantiate max cost
        def maxcost_rule(m, j, k):
            return m.max_cost >= (m.u[j, k] * m.c[j, k])

        # Set up objective for total sum.
        def obj_rule_percentile(m):
            return sum(m.u[j, k] * m.c[j, k] for j, k in m.JK)

        # Set up objective for max cost.
        def obj_rule_max(m):
            return (sum(m.epsilon * m.u[j, k] * m.c[j, k]
                        for j, k in m.JK) + (1 - m.epsilon) * m.max_cost)

        ##
        self.model.g = Objective(rule=obj_rule_max, sense=minimize)
        self.model.c1 = Constraint(self.model.J, rule=c1Rule)
        self.model.c2 = Constraint(rule=c2Rule)
        self.model.c3 = Constraint(self.model.JK, rule=maxcost_rule)
        self.built = True

    def instantiate_mip(self):
        build_info, indices = self._get_mip_build_info()
        if not self.built:
            self.build_mip()

        a = build_info['a']
        a_tuples = {}
        for i in range(len(a)):
            a_tuples[(i, 0)] = 0
            for j in range(len(a[i])):
                a_tuples[(i, j)] = a[i][j]

        c = build_info['c']
        c_tuples = {}
        for i in range(len(c)):
            c_tuples[(i, 0)] = 0
            for j in range(len(c[i])):
                c_tuples[(i, j)] = c[i][j]

        u_tuples = {}
        for i in range(len(c)):
            u_tuples[(i, 0)] = True
            for j in range(len(c[i])):
                u_tuples[(i, j)] = False

        epsilon = min(indices['cost_df']) / sum(indices['cost_ub'])
        data = {
            None: {
                'J': {
                    None: list(range(len(a)))
                },
                'K': {i: list(range(len(a[i]) or 1))
                      for i in range(len(a))},
                'a': a_tuples,
                'c': c_tuples,
                'u': u_tuples,
                'w': {i: coef
                      for i, coef in enumerate(self.coefficients)},
                'y_pred': {
                    None: self.score()
                },
                'epsilon': {
                    None: epsilon
                },
                'max_cost': {
                    None: -1000
                }
            }
        }

        instance = self.model.create_instance(data)
        return instance

    def fit(self):
        instance = self.instantiate_mip()
        opt = SolverFactory('cbc')
        start = time.time()
        opt.solve(instance)
        end = time.time() - start

        ## add check
        output = {}
        for i in instance.JK:
            output[i] = {
                'a': instance.a[i],
                'u': instance.u[i](),
                'c': instance.c[i]
            }
        output_df = pd.DataFrame(output).loc[lambda df: df['u'] == 1]
        final_output = {}
        final_output['total_cost'] = instance.max_cost()
        final_output['actions'] = output_df['a'].values
        final_output['costs'] = output_df['c'].values
        final_output['runtime'] = end
        return output
Example #14
0
# -*- coding: utf-8 -*-
"""
Created on Thu Dec 19 16:12:21 2019

@author: Silvia
"""
from __future__ import division

from pyomo.opt import SolverFactory
from pyomo.core import AbstractModel
from pyomo.dataportal.DataPortal import DataPortal
from pyomo.environ import *
import pandas as pd
from datetime import datetime
############ Create abstract model ###########
model = AbstractModel()
data = DataPortal()

#Parameter for multi cables analysis
model.Cable_Types = Param()

# ####################Define sets#####################

#Name of all the nodes (primary and secondary substations)
model.N = Set()
data.load(filename='nodes.csv', set=model.N)  #first row is not read

#Node corresponding to primary substation
model.PS = Set(within=model.N)
data.load(filename='PS.csv', set=model.PS)
#Allowed connections