universidad autÓnoma metropolitana148.206.53.84/tesiuami/uami10759.pdf1-1 1 introducción el...

170
UNIVERSIDAD AUTÓNOMA METROPOLITANA UNIDAD IZTAPALAPA DIVISIÓN DE CIENCIAS BÁSICAS E INGENIERIA LICENCIATURA EN COMPUTACIÓN PROYECTO DE INVESTIGACION I - II Presenta: Alma Delia García Arreguín Asesor: Ing. Jorge Lozano Moreno PROGRAMACIÓN AUTOMÁTICA DE CURSOS

Upload: dodang

Post on 29-Sep-2018

212 views

Category:

Documents


0 download

TRANSCRIPT

UNIVERSIDAD AUTÓNOMA METROPOLITANA

UNIDAD IZTAPALAPA

DIVISIÓN DE CIENCIAS BÁSICAS E INGENIERIALICENCIATURA EN COMPUTACIÓN

PROYECTO DE INVESTIGACION I - II

Presenta: Alma Delia García Arreguín

Asesor: Ing. Jorge Lozano Moreno

PROGRAMACIÓN AUTOMÁTICA DECURSOS

UNIVERSIDAD AUTÓNOMA METROPOLITANAUNIDAD IZTAPALAPALICENCIATURA EN COMPUTACIÓNP R E S E N T E

En cumplimiento con los requisitos que establece la legislación de estaUniversidad para el Procedimiento de Titulación, por medio de lapresente autorizo la terminación efectiva del proyecto de investigaciónI y II, cuyo título es:

“Programación automática de cursos”

para los fines que Alma Delia García Arreguín con matrícula 89326849 convenga

A t e n t a m e n t e“CASA ABIERTA AL TIEMPO”México D.F.

Asesor: Ing. Jorge Lozano Moreno

Indice

Agradecimientos1. Descripción del problema de la programación de cursos 1-1

Introducción 1-1Contexto del problema de la programación de cursos 1-1Descripción del problema modelo 1-3Políticas y lineamientos de la programación 1-7

2. Marco teórico 2-1Introducción 2-1Sobre la complejidad del problema de horarios 2-3Relaciones y clases de equivalencia 2-9

Propiedades de las relaciones 2-9Reconocimiento por computador: matrices de ceros y unos 2-9Relaciones de equivalencia y particiones 2-11

Introducción a la teoría de grafos 2-12Representación de grafos dirigidos 2-15Representación de relaciones y clases de equivalencia con grafos 2-17Problema de los caminos más cortos con un solo origen 2-17Problema de los caminos más cortos entre todos los pares 2-19Recuperación de los caminos 2-21

3. Solución funcional 3-1Introducción 3-1Desarrollo 3-1

4. Solución por procedimiento 4-1Introducción 4-1Definición del modelo de solución para la programación de cursos 4-3

Requerimientos de información para realizar la programación decursos

4-3

Restricciones del modelo 4-6Restricciones de procesamiento 4-7

Procesos previos a la programación de cursos 4-7Ordenación de cursos 4-7Rutas mínimas entre localidades 4-8Tablas de contadores de personal en capacitación 4-10

Parametrización del modelo de la programación de cursos 4-11Definición de acuerdos y lineamientos 4-11Definición del calendario para el proyecto 4-13

Proceso de programación de cursos 4-14Generación de grupos propuestos 4-18Generación de grupos 4-23Asignación de recursos 4-26

Apéndice A. Parámetros del sistema A-1Apéndice B. Pseudocódigo B-1Apéndice C. Diccionario de datos C-1Bibliografía D-1

Agradecimientos

En primer lugar agradezco a Dios por haberme guiado, por darme la fuerza, la fé y lacapacidad para lograr llegar al final

Agradezco a mi familia por su apoyo. Especialmente agradezco a mis hermanos Aurey Saúl por los sacrificios que hicieron para darme los elementos materiales yemocionales para seguir adelante.

Agradezco a mi asesor Jorge Lozano por su mano amiga.

Agradezco a Héctor Lozano por la oportunidad de enfrentarme al mundo real

Gracias a mis amigos y compañeros que estuvieron conmigo en las buenas y en lasmalas durante el camino (Genaro, Rosalba, Veronica, Rosa, Jesús, Adriana, Moises,Delfino, Alejandro, Pedro, Lizbeth, Roberto, Ma. Eugenia, Americo)

Gracias a Laura Medina, por regresarme al camino cuando ya me había perdido

1-1

111Introducción

El problema de la programación de cursos consiste principalmente en el proceso decrear combinaciones de cursos o materias y horas o fechas de manera que seaprovechen los recursos materiales (aulas, laboratorios, equipo, etc) y humanos(instructores, profesores) de la manera más óptima para satisfacer las necesidades decapacitación o formación demandantes.

Para realizar la planeación se consideran varios factores como son: los cursos que sevan a impartir, el período de tiempo en que se programarán, la duración de loscursos, el número de inscritos máximo y mínimo para un grupo, las instalaciones querequiere el curso, la disponibilidad de los instructores o profesores candidatos paraimpartir los cursos, etc.

A continuación se describe la programación de materias que se efectúa en unainstitución educativa con el fin de ubicar el contexto del problema y los factores quelo afectan. Posteriormente se describe el problema de planeación de cursos que seabordo para la presentación del proyecto terminal.

Contexto del problema de la programación de cursos

En una organización educativa, como es el caso de las universidades, por ejemplo, laplaneación de cursos se realiza con el fin de contar con un plan calendarizado dematerias que se impartirán en un ciclo escolar (trimestre, semestre) y cada uno de losfactores implicados se consideran de diferentes formas. Algunos de estos factores sonfijos es decir, son parte descriptiva de las materias o forman parte de las normas ypolíticas que rigen la estructura de la organización, y por tanto solo requieren unproceso de adaptación a la nuevas condiciones de la programación. Por ejemplo, ladistribución de horas de teoría y horas de laboratorio por semana es parte descriptivade cada materia; el período de programación (trimestre o semestre) es parte de laspolíticas de la institución para organizar los ciclos escolares.

Las materias que se abren dependen de los niveles existentes en el período dado,estos niveles corresponden a los niveles de la población estudiantil regular. Para unauniversidad en la que el período de programación es por semestre y se tiene solo unperíodo de admisión, las materias que se abren se podrían clasificar de la siguientemanera. Si es período de admisión se abren las materias que corresponden con elprimer semestre y con los semestres impares (3o, 5o, etc.). Si no es período de admisiónse abren las materias correspondientes a los semestres pares (2o, 4o, etc.). Otra forma

Descripción del problema de laprogramación de cursos

Descripción del problema de la programación de cursos

1-2

de seleccionar los cursos a programar puede ser considerando el número desolicitudes de inscripción, de esta manera aunque de acuerdo al ciclo normal no sedeba impartir una materia ésta se abre a solicitud de la población demandante.

Los horarios que se forman para cada materia se distribuye considerando sudescripción que indica el número de horas de teoría y el número de horas delaboratorio. Los horarios deben ser compatibles con las demás materias de un mismonivel de modo que se eviten los traslapes de tiempo entre los horarios de éstas.

El cupo de los grupos que se abren para cada materia puede, en muchas ocasiones,ser también una descripción fija del curso o de la materia, es decir un valor máximo yun valor mínimo predeterminados, o puede determinarse de acuerdo con el númerode solicitudes de inscripción y el número de grupos que se abrirán de modo que sesatisfaga la demanda. A su vez el número de grupos abiertos para una materiadepende en gran medida del número de profesores disponibles para impartir lamateria.

Para la asignación de aulas a los grupos se considera el tipo de aula (laboratorio,audiovisual, auditorio, salón de clase), la capacidad máxima de auditorio y el equipocon el que se integra de manera que se cumplan las necesidades materiales para laimpartir el curso.

La disponibilidad de los participantes a los cursos no se considera. Este es un factorindividual y ajeno a la programación de cursos. El problema de ajustar las materias alhorario individual del alumno es un problema que se deja a éste último, él es quien seencarga en lo posible de ajustar su programa de manera que no existan traslapesentre las materias. También pueden formarse grupos en los que se integre unprograma completo con los cursos correspondientes a un nivel y el alumno solo eligealguno de éstos programas y se olvida de formarlo individualmente.

La disponibilidad de los profesores es factor determinante que se toma en cuenta. Laasignación de profesores a los grupos debe considerar que profesores imparten elcurso, el horario en el que están disponibles y sobre todo que al asignar un profesoréste no se asigne simultáneamente a dos grupos diferentes.

Otro factor importante en la programación de cursos son los costos de los programas.En una organización educativa los costos implicados en los programas no seconsideran explícitamente en su elaboración puesto que son relativamente fijos y noafectan a los planes. Los costos que integran sueldos de profesores, colegiatura dealumnos, gastos por el uso de instalaciones, materiales y equipo, etc, sonconsiderados por la institución para la asignación de su presupuesto pero muy pocasveces influyen de manera directa en la programación de los horarios y materias.

Descripción del problema de la programación de cursos

1-3

Descripción del problema modelo

La programación de los cursos que se considera como proyecto terminal essubstancialmente diferente en lo que respecta a los factores que la afectan puestoque además de los mencionados para las organizaciones educativas comunesexisten otros más, complejos y variantes, que impactan de manera directa unprograma. El objetivo principal de la programación en la organización modelo, aligual que en cualquier otra organización educativa, es tener un plan anticipado decursos para un período determinado que satisfaga en un alto porcentaje la demandade capacitación. Sin embargo una diferencia importante es que en la programaciónque nos ocupa también es un objetivo el que los planes generados incurran en costosmínimos.

La organización para la que se modela el problema de la planeación de cursos es uninstituto tecnológico dedicado a dar capacitación y formación al personal de susclientes. Un cliente puede ser cualquier otra organización productora de bienes y/oservicios que mantenga políticas de capacitación para su personal.

El problema se centra en un cliente en particular con características dentro de suorganización que impactan de manera importante la programación de los cursos.1

Antes de continuar con la descripción de la programación de cursos se mencionaránalgunas características de la estructura y organización de OCM que influyen en laprogramación de los proyectos de capacitación.

El personal de OCM son de dos tipos, personal sindicalizado y personal de confianza.Los puestos del personal de confianza se agrupan en niveles y los puestos del personalsindicalizado en categorías. Tanto las categorías como los niveles tienen un valor dejerarquía que les proporciona un orden de prioridad. Las categorías se agrupan a suvez en especialidades y los niveles en unidades de negocio (figura 1.1). Cadaespecialidad o unidad de negocio tiene identificados sus períodos críticos de trabajoes decir, los períodos en los que la carga de actividades es mayor. En estos períodoscríticos el personal no puede ausentarse de sus labores para asistir a capacitación.

Por otro lado OCM, dada su magnitud nacional, se estructura por campus. Loscampus existentes son nueve y cada uno agrupa a diferentes estados federativos. Encada estado federativo, de acuerdo a las localidades de éstos, OCM mantiene unadivisión por centros de trabajo. Cada centro de trabajo pertenece a una localidadespecifica y son los lugares en los que labora y administra el personal. (Figura 1.2)

1 Para mayor claridad de la descripción llamaremos al instituto tecnológico modelo ITM y a la organizacióncliente modelo OCM.

Descripción del problema de la programación de cursos

1-4

Recursos humanosde OCM

Personalsindicalizado

Personalconfianza

catego-ria A

catego-ria B

catego-ria C

catego-ria D

Nivel A Nivel B Nivel C Nivel D

Especialidad A Especialidad BUnidad denegocio A

Unidad denegocio B

Figura 1.1 Clasificación de los recursos de OCM

OCM

Campus A Campus B Campus C Campus I. . .

Estadosfederativos

Localidades

Centrosde trabajo

Fig. 1.2 División geográfica y departamental de OCM

Descripción del problema de la programación de cursos

1-5

La OCM mantiene diferentes planes de carrera que su personal debe seguirdependiendo de su nivel o categoría. Estos planes pretenden mantener el perfil deconocimientos indicado para los diferentes puestos y brindar un apoyo deascendencia sobre la línea de éstos. Además existen ciertos cursos básicos parapersonal de confianza y otros para personal sindicalizado los cuales todo recursohumano debe tomarlos. Para cada recurso humano se lleva un registro de su historialcurricular, éste se forma por los cursos acreditados y por los cursos que de acuerdo alos conocimientos y habilidades de su puesto acredita de manera implícita.

Además de los planes de estudio, OCM realiza periódicamente una detección de lasnecesidades de capacitación entre el personal y ejecuta proyectos con el fin desatisfacer éstas necesidades. La detección de necesidades se realiza para que elpersonal solicite los cursos que de acuerdo a sus actividades le sean necesarios paraun mejor desempeño personal e individual. Por otra parte también se ejecutanproyectos dirigidos a especialidades, categorías o niveles para manteneractualizados los conocimientos del personal en cada puesto y mejorar de estamanera su desempeño general.

Los proyectos de capacitación que se llevan a cabo determinan de acuerdo a susobjetivos y a las solicitudes de cursos del personal, los cursos que se impartirán; elperíodo de tiempo en que se lleva a cabo el proyecto, esto es la fecha de inicio y lafecha de finalización del proyecto, hacia quién va dirigido el proyecto y los lugaresen los que se efectuará la capacitación, es decir en que campus se ejecutara elproyecto.

Cada solicitud del personal generada por detección de necesidades orequerimientos de actualización pasa por un análisis previo a la programación de loscursos que determina su aceptación. Este análisis verifica si el empleado solicitantecuenta con los conocimientos prerrequisitos del curso que solicita. Los prerrequisitos aun curso se pueden satisfacer, como se menciono anteriormente, de manera explícitatomando los cursos previos o de manera implícita cuando las actividades que sedesempeñan en un puesto brinda los conocimientos requeridos. Cumpliendo estascondiciones es como se acepta una solicitud, o puede, en caso contrario, generarselas solicitudes correspondientes para satisfacer primero los cursos prerrequisitos alcurso de solicitud.

El análisis que se lleva cabo para la clasificación de las solicitudes no se abarca en elmódulo que ocupa al proyecto terminal. Sin embargo se menciona porque el estadoen que este análisis deja a una solicitud si afecta a la programación y debeconsiderarse puesto que indica, entre otras cosas, que una solicitud es aceptada ono, que un proyecto no ha sido programado, está en ejecución o se cancelo, etc.

El ITM emplea recursos de diferentes fuentes para satisfacer los requerimientos de losproyectos de capacitación. ITM tiene recursos propios, utiliza recursos del cliente yemplea también recursos externos. Los recursos propios son instructores, equipo yplanteles administrados directamente por ITM; los recursos del cliente son planteles yequipo propiedad del cliente que presta a ITM para la capacitación. Los recursosexternos son solicitados a diferentes proveedores de capacitación.

Descripción del problema de la programación de cursos

1-6

OCM tiene entre su propio personal a los instructores de capacitación, algunos losdeja a disposición completa para el ITM es decir, es personal administrado por OCMpero que labora siempre con ITM. Estos instructores se clasifican como instructorescomisionados permanentes. Otro tipo de instructores de OCM son los que además dela capacitación se encargan de dar mantenimiento a los planes y cursos susactividades dentro de OCM son éstas exclusivamente. Por último existen un tercer tipode instructores éstos son personal cuyas actividades no son exclusivamente lacapacitación sino que pertenecen a otras áreas y que se solicitan sus servicios decapacitación solo de manera auxiliar. Este tipo de instructores se clasifican comoinstructores comisionados auxiliares. Todos los instructores comisionados reciben pagosadicionales por los cursos impartidos, el pago adicional es un porcentaje de comisiónespecificado como política por OCM.

Una vez detectados los cursos que comprende un proyecto de capacitación, losempleados a los que se impartirán y los lugares en los que se aplicará el proyecto, selleva a cabo la creación de grupos para cada curso, con participantes; fechas deinicio y fin; especificación del plantel o lugar en donde se impartirá el curso; horariode entrada y salida; instalaciones, aulas, laboratorios; equipo y materiales de apoyo,maquetas, computadoras, proyectores; e instructor asignado para impartir el curso. Laprogramación de un proyecto de capacitación se efectúa de maneraindependiente en cada campus al cual se va a aplicar.

Los grupos generados pueden estar en diferentes estados. Pueden ser gruposcompletos, con el cupo máximo de inscritos y con todos los recursos asignados; opueden ser grupos con faltante para alguno de sus requerimientos, grupos nocompletos, con faltante de equipo, faltante de instructor o con faltante deinstalaciones. El hecho de que se permita que los grupos generados tengan algúnfaltante de recursos se establece porque se pretende que después de laprogramación los campus puedan negociar con sus recursos para satisfacer todas lasnecesidades. Este mercadeo permitirá que se formen grupos completosintercambiando recursos.

Como OCM es muy grande es común que el personal viaje a diferentes localidadespara asistir a capacitación, al igual que los equipos pueden algunas veces sertransportados. Los costos de transportación y hospedaje del personal y costos detransporte de equipo deben minimizarse cuando se genera un programa para unproyecto. De igual manera cuando se emplean recursos de proveedores se debenelegir aquellos que ofrezcan costos mínimos y de mayor calidad.

Todo el proceso descrito se desarrolla de manera manual, el tiempo para crear unprograma es relativamente grande y no se aprovechan de manera adecuada todoslos recursos tanto materiales como humanos. Lo que se pretende para la presentacióndel proyecto terminal es automatizar el proceso descrito para la programación decursos. Se pretende, en forma automática, formar grupos con participantes,instructores, instalaciones y equipos de manera que exista un programa decapacitación especifico para cada proyecto y que éste se genere en un tiempoconsiderable. Además se deben distribuir los recursos de manera que los costos de losprogramas sean mínimos.

Descripción del problema de la programación de cursos

1-7

Debido a los costos que se manejan en los diferentes proyectos de capacitación serequiere medir el costo - beneficio de cada asignación de participantes, instructores,instalaciones y equipos a los diferentes grupos que se crean. Para ello se intentamodelar en funciones matemáticas los diferentes criterios cuantificables queinvolucran las asignaciones de recursos a los grupos para lograr un programa óptimode acuerdo a las prioridades de cada factor involucrado.

Políticas y lineamientos de la programación.

OCM mantiene ciertas reglas, procedimientos y políticas referentes a su estructuraorganizacional que impactan de manera directa la forma en la que se establece unprograma de capacitación. Esto es principalmente lo que marca la diferencia de laprogramación de los cursos entre la organización modelo y las organizacioneseducativas comunes. Los lineamientos establecen políticas para la asignación delpersonal a los grupos, fechas en la que no se debe dar capacitación, porcentajes depersonal que puede asistir a capacitación simultáneamente, etc. A continuación sedescriben los lineamientos que aparecen regularmente y que se toman enconsideración para el modelo del problema.

Generalmente los grupos para personal de confianza y personal sindicalizado segeneran de manera separada. Los recursos humanos no pueden programarse acapacitación en los períodos críticos de su especialidad o unidad de negocio.

Si dos recursos humanos solicitan un mismo curso y pertenecen a un mismo centro detrabajo, el recurso de mayor categoría o nivel deberá ser programado primero, si sonde la misma categoría o nivel el de mayor antigüedad deberá ser programadoprimero. Pueden asistir al curso simultáneamente pero no quebrantar la condiciónanterior.

En un centro de trabajo no puede asistir a capacitación simultáneamente más de undeterminado número de participantes. Esto se establece para evitar que quede sinactividad un centro de trabajo completo porque su personal se encuentre encapacitación. Lo mismo sucede con el total de los recursos humanos es decir, no sepuede exceder un porcentaje permitido de personal para asistir a capacitación.

Existen lineamientos en donde se especifica los días en los que no se debe darcapacitación. Este lineamiento incluye la determinación de incluir o excluir los fines desemana como días hábiles para la capacitación.

Algunas veces los recursos para los proyectos deben ser totalmente solicitados aproveedores, o puede establecerse que se cubra la capacitación solo con recursospropios o combinación de recursos de proveedores y propios.

Estas restricciones afectan a los proyectos de capacitación de manera variabledependiendo de las necesidades y requerimientos del proyecto. El modelo debepermitir la flexibilidad suficiente para programar los proyectos siguiendo las normasestablecidas.

2-1

222Introducción

El proceso propuesto para la programación de cursos comienza con la detección desolicitudes de capacitación del personal del cliente para un proyecto específico. Enun campus las solicitudes de capacitación se clasifican por tipo de personaldividiendo de esta manera el conjunto de solicitudes total en dos conjuntos: unconjunto de solicitudes de personal de confianza y un conjunto de solicitudes depersonal sindicalizado. Cada conjunto de solicitudes se programa de maneraseparada.

Posteriormente el conjunto de solicitudes de un tipo de personal se clasifica porcursos, (ver figura 2.1).

So lic itudes decapa c itac ión de lpe rsona l de un

c a m p u s

So l ic itudes depersona l

conf ianza

so lic itudes depersona l

s indical izad o

So lic itudescurso 1

S olic itu d e scurso 1

S olic itu d e scurso 2

S olic itude scurso 2

Figura 2.1 Ciclo de clasificación de las solicitudes de capacitación

En la figura 2.2 se muestra el proceso de programación para un curso. En la gráfica loscírculos de la izquierda representan a los recursos humanos que solicitan un curso y loscírculos de la derecha representan a los grupos propuestos para el curso. La línea queune a un recurso humano con un grupo propuesto significa que el recurso humanopuede ser inscrito al grupo sugerido puesto que sus períodos de disponibilidadcoinciden con la fechas en la que se dará el curso en el grupo. Esta línea tiene un

Marco teórico

Marco teórico

2-2

valor de asignación asociado. Las solicitudes de los recursos humanos para un cursose ordenan por centro de trabajo, categoría o nivel y antigüedad y se asignan a losgrupos eligiendo al grupo cuyo costo de asignación (costo - beneficio) sea óptimo(mínimo). De la misma manera se asignan los instructores, equipos e instalaciones parala impartir los cursos.

La relación recurso humano - grupo se establece cuando un recurso humano estádisponible en la fechas en las que se impartirá el curso solicitado en el grupopropuesto. Si esta relación se da se crea el valor de la asignación estimandodiferentes factores, entre ellos los costos de transportación de la localidad dondelabora el recurso humano a la localidad del plantel en donde se propone el grupo.Esto mismo sucede con la asignación de instructores. Para elegir el camino óptimo deuna localidad a otra para transportar a los participantes e instructores se utiliza unafunción que asigna valores a las rutas estimando costos de transportación, tiempo detransportación y calidad o comodidad del medio de transportació1ºn. Utilizandoalgoritmos de rutas mínimas se elige entre todas las opciones la ruta óptima.

Centro detrabajo 1

Centro detrabajo 2

Centro detrabajo 3

Grupo 3curso 1

Grupo 2curso 1

Grupo 1curso 1

Figura 2.2 Asignación participante grupo

Las clasificaciones del conjunto de solicitudes que se realiza para disminuir lamagnitud del problema se pueden visualizar como particiones y relaciones delconjunto total de solicitudes. Las asignaciones de recursos a grupos y la solución derutas óptimas de transportación involucran algoritmos y teoría de grafos. Paracomprender los conceptos utilizados en la solución del problema se presenta en estasección una revisión sencilla teórica sobre las relaciones y la teoría de grafos. Ademásse presenta un artículo que define la complejidad del problema de horarios deacuerdo con la teoría de análisis de algoritmos.

Marco teórico

2-3

Sobre la complejidad del problema de horarios1

En esta sección se expone el análisis del problema de horarios en forma técnica deacuerdo con la teoría de análisis de algoritmos. Este análisis muestra la complejidad yclasificación del problema de horarios.

El problema de horarios que se analiza es un modelo matemático del problema dehorarios de una institución educativa (primaria, universidad). El problema presentadoes en realidad mucho más simple puesto que ignora varios factores que juegan unpapel importante en la práctica. Sin embargo se muestra que incluso con lasrestricciones adicionales el modelo es un problema NP-completo.

Definición: (Problema de horarios, TT), dados los siguientes datos:

1. (conjunto finito de horas a la semana)

2. Una colección T1,T2,...Tn, donde Ti ⊆ H (hay n profesores y Τi es el conjunto dehoras en las que el i-ésimo profesor está disponible)

3. Un conjunto C1,C2,...,Cm donde, Cj ⊆ Η (hay m clases y Cj es el conjunto dehoras en las que la j-ésima clase se impartirá)

4. Una matriz R de nxm enteros no negativos, Rij es el número de horas en las que eli-ésimo profesor imparte la j-ésima clase.

El problema es determinar si existe una fórmula tal que:

f(i,j,h): 1,...,n X 1,...,m X H → 0,1 donde f(i,j,h)=1 si y sólo sí el profesor i imparte laclase j durante la hora h de modo que se cumpla lo siguiente:

a) f(i,j,h) = 1 ⇒ h ∈ (Ti ∩ Cj). Tanto la clase como el profesor están disponibles

b) ∑ f(i,j,h) = Rij para todo 1 ≤ i ≤ n y 1 ≤ j ≤ m. El profesor i da la clase j Rij horas ah ∈ H la semana

n

c) ∑ f(i,j,h) ≤ 1 , para todo 1≤ j ≤ m y h ∈ H. (una clase no puede tener asignado i

= 1 mas de un profesor.

m

d) ∑ f(i,j,h) ≤ 1, para todo 1≤ i ≤ n y h ∈ H (un profesor no puede impartir dosj = 1 clases simultáneamente).

1 SIAM J. Compt Vol. 5 No. 4. Diciembre de 1976. “ON THE COMPLEXITY OF TIMETABLE AND MULTICOMMODOTYFLOW PROBLEMS”. S.Even, A.Itai y A.Shamir

Marco teórico

2-4

Un profesor i es llamado k-profesor si Τi = k. Se dice que el profesor está saturado si

m

∑ Τi = Rijj = 1

esto es que durante todas las horas en las que está disponible imparte alguna clase.

Definición: El problema de horarios restringido RTT es un problema de horarios con lassiguientes restricciones:

1. Η = 3

2. Cj = H para toda 1≤ j ≤ m (las clases están siempre disponibles)

3. Cada profesor es 2-profr o 3-profr, es decir que los profesores están disponiblesdurante 2 ó 3 horas (sólo un tipo de disponibilidad a la vez)

4. Rij = 0 ó 1 para todo 1≤ i ≤ n y 1≤ j ≤ m

Tanto el problema TT como RTT están en la clase NP(no determinísticos polinomiales).Se desea mostrar que RTT es NP-completo y con ello mostrar que TT también es NP-completo. Se recuerda que 3-SAT (satisfacibilidad de una forma normal conjuntivacon tres literales por cláusula) es NP-completo y se define como sigue:

1. Un conjunto de literales X=x1,x2,...,xl,x'1,x'2,..,x'l

2. Una familia de cláusulas D1, D2, D3,..., Dk tales que para cada 1≤ j ≤ k, Dj = 3 yDj ⊆ X

El problema es determinar cuando existe una asignación de valores de verdad paralas literales, de modo que:

(a) exactamente una de las xi y x'i es verdadera mientras la otra es falsa

(b) en cada cláusula Dj hay por lo menos una literal con valor verdadero

Teorema: 3-SAT α RΤΤ

Demostración. La demostración se obtiene exponiendo una reducciónpolinomialmente limitada de 3-SAT a RTT. En la construcción ciertas clasesdesempeñan el papel de las ocurrencias de las literales xi o x'i en las expresiones; elorden en el cual algún 2-profr da esa clase indica el valor de verdad de las literales.Todas las otras clases y profesores son usados en orden para garantizar que estaasignación de valores de verdad satisface las condiciones a y b (de 3-SAT), y quetoda ocurrencia de una literal tiene el mismo valor de verdad.

Marco teórico

2-5

Sea pi el número de ocurrencias de las variable xi en una expresión es decir

k

pi = ∑ Dj ∩ xi,x'i. j = 1

Para cada xi se construye un conjunto de 5 • pi clases, las cuales se denotarán porCab(i), donde 1 ≤ a ≤ pi y 1 ≤ b ≤ 5 (se omite el superíndice i cuando todas las clasesutilizadas en la construcción se refieren al mismo i). Para simplificar la exposición seutilizará una representación gráfica de las clases y los profesores. En la representacióngráfica los vértices denotan combinaciones clase-hora, los renglones representan lashoras y las columnas representan las clases (figura 2.3). Las horas son h1, h2, y h3. Un 2-profr está disponible durante las horas h1 y h2 y está propuesto para dar una vez laclase Ca1b1 y una vez la clase Ca2b2 lo cual se representa en la figura 2.4. Lasdiagonales muestran sólo dos formas de programar el horario para este profesor. Un 3-profr puede dar las clases Ca1b1, Ca2b2 y Ca3b3, denotado por una línea con tres flechasen las columnas correspondientes a esas clases como se muestra en la figura 2.5. Paracada 1≤ q ≤ pi se añaden dos nuevas clases C'q1 y C"q1 con la estructura mostrada enla figura 2.6. Se describen tres profesores en la estructura; dos son 2-profr, y uno es 3-profr. Entonces los 3 profesores deben dar clases durante h1, los vértices (h1,Cq1),(h1,C'q1) y (h1,C"q1) deben utilizarse para construir el horario.

h1

h2

h3. . .

. . .

. . .

C11 C12 C13 C14 C15 C21 C22 Cpi4 Cpi5

Figura 2.3

Se tiene que elegir utilizar exactamente uno de los vértices (h2, Cq1) y (h3,Cq1), dejandouno disponible. La estructura queda como sigue: se toma el vértice (h1,Cq1) y uno delos vértices (h2,Cq1) y (h3,Cq1) y se borra (h1, Cq1) del diagrama.

Marco teórico

2-6

h1

h2

h3

Ca1b1 Ca2b2

h1

h2

h3

Cq1 C’q1 C”q1

h1

h2

h3

Ca1b1 Ca3b3Ca2b2

Figura 2.4 Figura 2.5 Figura 2,6

Considerando la estructura de profesores descrita en la figura 2.7, se intenta asignar,consistentemente, valores de verdad a todas las ocurrencias de xi y x'i en lasexpresiones.

h1

h2

h3

C11 C12 C13 C14 C15 C21 C22 C23 C24 C25 C31

. . .

Figura 2.7

Hay un 3-profr asignado a las clases Cpi4, C11 y C13; así la forma de estructura de lafigura 2.7 es circular. Consideramos ahora los pi 2-profr disponibles durante h1 y h2,donde el q-ésimo de tales profesores es asignado a las clases Cq3 y Cq4. Todos estosprofesores deben asignarse de la misma manera; esto es, cualquiera de ellos dará laclase Cq3 durante h1 y Cq4 durante h2, o dará la clase Cq3 durante h2 y Cq4 durante h1.Se supone que se tiene un programa que no satisface esta condición. Entonces debehaber un q tal que el q-ésimo profr. de la clase Cq3 durante h2 y Cq4 durante h1,mientras que el (q+1)-ésimo profesor da la clase C(q+1),3 durante h1 y C(q+1),4 durante h2.En este caso, el 3-profr quien debe dar la clase Cq4, C(q+1),1 y C(q+1),3 no puedeprogramarse durante h1 lo cual lleva a una contradicción.

Así obtenemos, independientemente para cada i, un programa uniforme para todoslos 2-profesores disponibles durante h1 y h2. El orden en el que los profesores dan laclase Cq3 y Cq4 en la i-ésima estructura se debe interpretar como los valores deverdad de la variable xi en el problema original 3-SAT.

Marco teórico

2-7

Se añaden algunos 3-profesores más, vinculando las diferentes i-estructuras en ordenpara garantizar que en cada expresión Dj por lo menos una literal sea verdadera.Para cada expresión Dj = ξ1, ξ2, ξ3 se asigna un 3-profr. en la siguiente forma. El esasignado a una clase para cada una de las tres literales. Si ξ1 = xi y ésta es la q-ésimaocurrencia de la variable, entonces la clase correspondiente es Cq2(i), mientras que si ξ1 = x'i la clase correspondiente es Cq5(i) .Las clases correspondiente a ξ2 y ξ3 se definenanálogamente.

Esto completa la definición del problema RTT. El número total de clases definidas es 21•⋅k y el número total de profesores es 22 •⋅k (15 •⋅k 2-profesores y 7 • ⋅k 3-profesores).Afirmamos que el problema dado 3-SAT tiene una solución positiva si y sólo sí elproblema RTT construido tiene una respuesta positiva.

Primero. Se asume que el problema 3-SAT tiene una respuesta positiva. Usamos ahoralos valores de verdad de la literales para exponer un programa de la construcción delproblema RTT, y así probar que esta solución también es positiva.Si xi es verdaderaentonces para cada 1≤ q ≤ pi el q-ésimo 2-profr es programado para dar la clase Cq3(i)

durante h1 y Cq4(i) durante h2. Inversamente, si xi es falsa entonces para cada 1 ≤ q ≤ pi

el q-ésimo 2-profr es programado para dar la clase Cq3(i) durante h2 Cq4(i) y durante h1.

En cada expresión Dj hay por lo menos una literal con valor cierto; se asume que es ξ.Si ξ = xi y ésta es la q-ésima ocurrencia de esta variable, entonces el 2-profr esprogramado para dar la clase Cq2 durante h3 y Cq3 durante h2.

Cq’1,1 Cq’1,2 Cq’1,3 Cq’1,4 Cq’1,5 Cq1 Cq2 Cq3 Cq4 Cq5 Cq+1,1

Figura 2.8

En la figura 2.8 el programa asignado para cada 2-profr discutida, se muestra por unalínea sólida gruesa, la opción evitada se muestra con líneas segmentadas. La líneasólida delgada indica que la opción no ha sido elegida todavía. Los 3-profrs dan laclase C(q-1),4, Cq1 y Cq3, utilizando h1 para la clase C(q-1),4, h2 para la clase Cq1 y h3 parala clase Cq3. (Esto se muestra por los dobles círculos en el vértice). Finalmente el 3-profrcorrespondiente a Dj da la clase Cq2 durante h2.

Se mostrará que los restantes se pueden programar en las horas h1 y h3 para dar otrasdos clases. La hora h1 nunca es ocupada por algún otro profesor en clases del tipo Ca2

y Ca5. Si ξ'=xr es otra literal en Dj y es falsa, entonces la clase correspondiente Ca2

Marco teórico

2-8

debe darse durante la hora h2 por un 2-profr y h3 queda disponible. También si ξ'=x'r yes falsa, entonces la clase Ca5 debe darse durante h2 por un 2-profr y nuevamente h3

queda disponible. Finalmente, si las literales restantes en Dj son verdaderas, entoncespara alguna de ellas, no se sigue el proyecto usado para . Por ejemplo, si ξ'=xr esverdadero y ésta es la a-ésima ocurrencia de la variable, entonces el 2-profr da laclase Ca2 durante h2 y Ca3 durante h3. El 3-profr da la clase C(a-1),4 durante h1, Ca1

durante h3 y Ca3 durante h2. (Como se muestra en la figura 2.9). Así h3 quedadisponible para dar la clase Ca2 y el programa de el 3-profr correspondiente a Dj esflexible.

Ca’1,1 Ca’1,2 Ca’1,3 Ca’1,4 Ca’1,5 Ca1 Ca2 Ca3 Ca4 Ca5 Ca+1,1

Figura 2.9

Segundo. Suponemos que la respuesta a la construcción del problema RTT es positivay se asume que se tiene un programa aceptable. Si en la estructura de xi los 2-profrasignados para impartir la clase Cq3 y Cq4 las dan durante h1 y h2 respectivamente,entonces xi es verdadero y si dan la clase Cq3 durante h2 y Cq4 durante h1, xi es falsa.Resta mostrar que cada expresión Dj = ξ1, ξ2, ξ3 contiene por lo menos una literalverdadera. Si ξ ∈ Dj y es falsa, entonces la hora h2 es utilizada para impartir las clasescorrespondientes (Ca2 si ξ = xi y Ca5 si ξ = x'i) por un 2-profr y las clases adyacentes (Ca3 siξ = xi y Ca4 si ξ = x'i). Si todas las literales son falsas, los 3-profrs correspondientes a Dj nopueden tener una asignación para dar las tres clases, entonces no puede utilizar lahora h2.

Dado que el problema 3-SAT α RTT por transitividad todo RTT es NP-Duro, y RTT ∈ NP porlo tanto RTT es NP-completo.

Marco teórico

2-9

Relaciones y clases de equivalencia

Propiedades de las relaciones

Definición: Si A y B son conjuntos, una relación de A a B es cualquier subconjunto de Ax B. Los subconjuntos de A x A se denominan relaciones en A.

Definición: Una relación R en un conjunto A se denomina reflexiva si para todo x ∈ A,(x,x) ∈ R. Se dice que R es reflexiva si cada elemento x de A esta relacionado consigomismo.

Definición: La relación R en un conjunto A se llama simétrica si (x,y) ∈ R ⇒ (y,x) ∈ Rpara x,y ∈ A.

Definición: Para un conjunto A, una relación R en A se llama transitiva si (x,y), (y,z) ∈ R⇒(x,z) ∈ R (De modo que si x <<está relacionado con>> y e y <<está relacionadocon>> z, se desea <<relacionar>> x con z, representando y el papel de<<intermediario>>).

Definición: Una relación de equivalencia R en un conjunto A es una relación reflexiva,simétrica y transitiva.

Reconocimiento por computador: matrices de ceros y unos.

A continuación se tratan las formas de representar las relaciones de conjuntos finitospara poder identificar las propiedades de la sección anterior.

Al igual que en la composición de funciones las relaciones se pueden combinar en lassiguientes circunstancias.

Definición: Si A, B, C son conjuntos con R1 ⊆ A x B y R2 ⊆ B x C, la relación compuesta R1

° R2 es una relación de A a C definida por R1 ° R2 = (x,y) | x ∈ A, z ∈ C y tal que existe y∈ B con (x,y) ∈ R1, (y,z) ∈ R2.

Aquí se debe tener cuidado, pues la composición de dos relaciones se escribe enorden opuesto al de la composición de funciones.

Ejemplo. Sea A el conjunto de empleados de un centro de computación, sea B unconjunto de lenguajes de programación de alto nivel, y C, una lista de proyectos p1,p2, ..., p8 a los cuales se debe asignar personal del conjunto A. Considérese R1 ⊆ A x B,donde un par ordenado de la forma (L.Aldama, Pascal), indica que el empleado L.Aldama es un experto en pascal (y quizás en otros lenguajes de programación). Larelación R2 ⊆ B x C consta de los pares ordenados (Pascal, p2), donde pascal seconsidera un lenguaje esencial para trabajar en el proyecto p2. En la relacióncompuesta R1 ° R2 se halla L.Aldama, p2) Si ningún otro par ordenado en R2 tiene p2

como segunda componente, se sabría que si L.Aldama se asignó a p2 fue sólo por suconocimiento de Pascal. (Aquí R1 ° R2 se utilizó para efectuar un proceso de

Marco teórico

2-10

pareamiento entre empleados y proyectos, basado en el conocimiento de lenguajesde programación específicos).

Definición: Dados un conjunto A y una relación R en A, se definen las potencias de Ren forma recursiva por: a) R1= R; b)para n ∈ Z+, Rn+1=R ° Rn.Obsérvese que para n ∈ Z+, Rn es una relación en A

Una matriz m x n de unos y ceros, S=(sij)mxn es una matriz rectangular de números conm filas y n columnas, sonde sij, 1 ≤ i ≤ m, 1 ≤ j ≤ n denota el registro en la i-ésima fila y j-ésima columna de S y cada registro es 0 ó 1. Para este tipo de matriz también sepuede escribir matriz-(0,1)).

Cuando se opera con estas matrices, se utilizan las operaciones estándar de suma ymultiplicación de matrices, pero con la estipulación de que 1+1 = 1. (de ahí que lasuma se denomine boleana).

Definición. Sean S = (sij)mxn, T = (tij)mxn dos matrices (0,1). Se dice que S precede a, o esmenor que, T, y se escribe S ≤ T, si sij ≤ tij, 1≤ i ≤ m, 1≤ j ≤ n.

Definición. Para n ∈ Z+, In = (δij)nxn es la matriz-(0,1) de n x n, en la que

1, si i = jδij =

0, si i ≠ j.

Definición. Sea A = (aij)mxn una matriz -(0,1). La traspuesta de A, que se escribe Atr, es lamatriz (a*ji)nxm, donde para 1≤ j ≤ n, 1≤ i ≤ m, a*ji = aij.

Teorema. Dado un conjunto A con A = n y una relación R en A, denótese por M lamatriz de la relación asociada a R. Por tanto,

a) R es reflexiva si, y sólo si, In ≤ M.

b) R es simétrica si, y sólo si M = Mtr.

c) R es transitiva si, y sólo si, M ⋅ M = M2 ≤ M.

d) R es antisimétrica si, y sólo si, M ∩ Mtr ≤ In. (La matriz M ∩ Mtr se forma operandoen los registros correspondientes de M y Mtr según las reglas: 0 ∩ 0 = 0 ∩ 1 = 1 ∩0 = 0, 1 ∩ 1 = 1).

La matriz de la relación es un instrumento útil para el reconocimiento por computadorde ciertas propiedades de las relaciones. Esta matriz al almacenar la informaciónsegún se describe aquí, es un ejemplo de estructura de datos.

Marco teórico

2-11

Relaciones de equivalencia y particiones.

Según se definió antes, una relación R en un conjunto A es una relación deequivalencia si es reflexiva, simétrica y transitiva.

Definición. Dados un conjunto A y conjunto de índices, I, sea ∅ ≠ Ai ⊆ A, para cada i ∈I. Entonces Aii∈ I es una partición de A si

a) A = ∪ Ai y b) Ai Aj = , para i,j ∈ I, i ≠ j.i∈I

Cada conjunto Ai se llama celda o bloque de la partición.

Definición. Sea R una relación de equivalencia en un conjunto A. Para cualquier x ∈A, la clase de equivalencia de x, denotada por [x], se define mediante [x] = y ∈ A yR x.

Teorema. Si R es una relación de equivalencia en un conjunto A y x, y ∈ A, entonces:a) x ∈ [x]; b) x R y si, y sólo si, [x] = [y], y c) [x] = [y] o [x] ∩ [y] = ∅.

Teorema. Si A es un conjunto, entonces

a) Cualquier relación de equivalencia R en A origina una partición de A.

b) Cualquier partición de A origina una relación de equivalencia R en A.

Marco teórico

2-12

Introducción a la teoría de grafos.

A menudo, cuando se utiliza un mapa de carreteras interesa observar cómo ir de unpueblo a otro por las carreteras indicadas en el mismo. En consecuencia, se tienendos conjuntos distintos de objetos: pueblos y carreteras. Estos conjuntos de objetos sepueden utilizar para definir una relación. Si V denota el conjunto de pueblos y A elconjunto de carreteras, se puede definir una relación R en V por a R b, si existe unsistema de carreteras que una a y b. Si son carreteras de doble sentido, y existe a R bse tiene también b R a. Si todas las carreteras consideradas son de doble sentido, setiene una relación simétrica.

Una forma de representar cualquier relación es listando sus elementos como paresordenados. Sin embargo, aquí es más conveniente utilizar una representación comola figura 2.10. Esta figura ilustra las formas posibles de viajar por seis pueblos utilizandolas ocho carreteras indicadas y muestra que hay al menos un sistema de carreterasque comunica dos pueblos (iguales o distintos) cualesquiera. Esta representacióngráfica es mucho más fácil de manejar que los 36 pares ordenados de la relación R.

ab

c

d

e

f

Figura 2.10

Al mismo tiempo, la figura 2.10 sería apropiada para representar seis centros decomunicación, interpretando las ocho <<carreteras>> como enlaces decomunicación. Si cada enlace comunica dos direcciones, podría preocupar lavulnerabilidad del centro a, por factores como averías de equipo o ataquesenemigos.

Sin el centro a, ni b ni c podrían comunicarse con d, e o f.

Por estas observaciones, se consideran los siguientes conceptos:

Definición. Sea V un conjunto no vacío y A ⊆ V x V. Entonces, el par (V,A) sedenomina grafo dirigido (en V), o digrafo (en V), donde V es el conjunto de vértices onodos, mientras que A es un conjunto de aristas. Se escribe G = (V,A) para denotardicho grafo.

Marco teórico

2-13

a

b

c

d

e

Figura 2.11

La figura 2.11 muestra un ejemplo de grafo dirigido en V = a,b,c,d,e con A = (a,a),(a,b), (a,d), (b,c). La dirección de una arista se indica colocando un flecha condirección en ella, según se muestra. Para cualquier arista, como (b,c), se dice que laarista es incidente con los vértices b, c; b es adyacente a c , mientras que c esadyacente desde b. Además, b se denomina origen o fuente de la arista, mientrasque c es el término, o vértice final. La arista (a,a) es un ejemplo de lazo; el vértice eno es incidente con ninguna arista y se denomina vértice aislado.

b

a

cd

a

b

cd

a) b)

Figura 2.12

Cuando no importa la dirección de una arista, el grafo se denomina no dirigido,como en la figura 2.12 a). Este grafo es una manera más compacta de describir elgrafo dirigido de la figura 2.12 b). En un grafo no dirigido hay aristas no dirigidas comoa,b, b,c, a,c, c,d, de la figura 2.12 a). Una arista como a,b significa (a,b),(b,a). Aunque, (a,b) = (b,a) sólo cuando a = b, se tiene a,b = b,a para cualquier a,b. Por último, se escribe a,a para denotar un lazo en un grafo no dirigido; a,a seconsidera igual que (a,a).

En general, cuando no se especifica si un grafo G es o no dirigido, se supone que esno dirigido. Si no contiene lazos, se denomina grafo sin lazos.

Marco teórico

2-14

Definición. Sea G = (V,A) un grafo no dirigido. Para x,y ∈ V, se dice que hay uncamino en G de x a y, si existe una sucesión no vacía finita de aristas distintas de A,como x,x1, x1,x2, ..., xn-1, xn xn,y. Cuando x = y, el camino se denomina ciclo. Elnúmero de aristas de un camino (ciclo) se denomina longitud del camino (ciclo).

a

b

d

c

e

f

Figura 2.13

En la figura 2.13, a,b, b,c, y c,f proporciona un camino de a a f. También, loproporciona la sucesión a,b, b,c, c,e, e,d, d,c, c,f. Sin embargo, aquí se hapasado dos veces por el vértice c. Cuando un camino entre dos vértices sólo pasauna vez por cualquiera de ellos, el camino se denomina simple. Esto se aplicatambién a un ciclo, excepto que el primero y el último vértice es el mismo. En la figura2.13, a,b, b,d, d,a, es un ciclo simple, mientras que a,b, b,d, d,c, c,e, e,d,d,a es un ciclo no simple.

Para un grafo dirigido se utilizan los términos caminos dirigidos y ciclos dirigidos.

Definición. Si G es un grafo dirigido en V, se dice que G es fuertemente conectado sipara toda x, y ∈ V, x ≠ y hay un camino de aristas dirigidas de x a y . En la figura 2.14el grafo dirigido de V=1,2,3,4 es fuertemente conectado y no tiene lazos.

4

1 2

3

Figura 2.14

Marco teórico

2-15

Un grafo G en un conjunto de vértices V da lugar a una relación R en V, donde x R y,si (x,y) es una arista de G. En consecuencia, hay una matriz-(0,1) para G y como estamatriz de relación resulta de las adyacencias de los pares de vértices, se denominamatriz de adyacencias para G, y matriz de relación para R.

Representaciones de grafos dirigidos

Para representar un grafo dirigido se pueden emplear varias estructuras de datos; laselección apropiada depende de las operaciones que se aplicarán a los vértices y alos arcos del grafo. Una representación común para un grafo dirigido G = (V,A) es lamatriz de adyacencia. Supóngase que V = 1,2, ..., n. La matriz de adyacencia paraG es una matriz A de dimensión n x n, de elementos booleanos, donde A[i,j] esverdadero si, y sólo si, existe un arco que vaya del vértice i al j. Con frecuencia seexhibirán matrices de adyacencias con 1 para verdadero y 0 para falso; las matricesde adyacencias pueden incluso aplicarse de esa forma. En la representación conuna matriz de adyacencia, el tiempo de acceso requerido a un elemento esindependiente del tamaño de V y A. Así, la representación con matriz de adyacenciaes útil en los algoritmos para grafos, en los cuales suele ser necesario si un arco dadoestá presente.

Algo muy relacionado con esto es la representación con matriz de adyacenciaetiquetada de un grafo dirigido, donde A[i,j] es la etiqueta del arco que va delvértice i al vértice j. Si no existe un arco de i a j, debe emplearse como entrada paraA[i,j] un valor que no pueda ser una etiqueta válida.

La figura 2.16 muestra la matriz de adyacencia etiquetada para el grafo dirigido de lafigura 2.15. Aquí, el tipo de etiqueta es un carácter, y un espacio representa laausencia de un arco.

A B

C D

a

a

a

a

b b bb

Figura 2.15

Marco teórico

2-16

A B C D A a b B a a C b a D b a

Figura 2.16

La principal desventaja de usar una matriz de adyacencia para representar un grafodirigido es que requiere un espacio Ω (n2) a un si el grafo dirigido tiene menos de n2

arcos. Sólo leer o examinar la matriz puede llevar un tiempo O(n2) arcos, lo cualinvalidaría los algoritmos O(n) para la manipulación de grafos dirigidos con O(n)arcos.

Para evitar esta desventaja, se puede utilizar otra representación común para ungrafo dirigido G = (V,A) llamada representación con lista de adyacencia. La lista deadyacencia para un vértice i es una lista, en algún orden, de todos los vérticesadyacentes a i. Se puede representar G por medio de una matriz PRINCIPIO, dondePRINCIPIO[i] es un apuntador a la lista de adyacencia del vértice i. La representacióncon lista de adyacencia de un grafo dirigido requiere un espacio proporcional a lasuma del número de vértices más el número de arcos; se usa bastante cuando elnúmero de arcos es mucho menor que n2. Sin embargo, una desventaja potencial dela representación con lista de adyacencia es que puede llevar un tiempo O(n)determinar si existe un arco del vértice i al vértice j, ya que puede haber O(n) vérticesen lista de adyacencia para el vértice y.

A

B

C

D

B

D

B

C

C

Figura 2.17

La figura 2.17 muestra una representación con lista de adyacencia para el grafodirigido de la figura 2.15 donde se usan listas enlazadas sencillas. Si los arcos tieneetiquetas, éstas podrían incluirse en las celdas de la lista ligada.

Marco teórico

2-17

Representación de relaciones y clases de equivalencia con grafos

En general, si R es una relación en un conjunto finito C, entonces R es reflexiva si, ysólo si, su grafo dirigido contiene un bucle en cada vértice (elemento C). Véase figura2.18

Una relación R en un conjunto finito C es simétrica si, y sólo si, su grafo dirigido sólocontiene lazos y aristas no dirigidas (figura 2.19).

En la figura 2.20 el grafo dirigido indica que una relación en un conjunto C serátransitiva si, y sólo si, su grafo dirigido cumple las siguientes condiciones: paracualquier x,y ∈ C, si existe un camino (dirigido) de x a y en el grafo asociado,entonces también hay una arista (x,y).

12

3

1

2

3

12

3

Figura 2.18 Figura 2.19 Figura 2.20

En general, una relación en un conjunto finito A es de equivalencia si, y sólo si, sugrafo asociado esta formado por la unión disjunta de grafos completos con lazos encada vértice.

Problema de los caminos más cortos con un solo origen.

A continuación se considera el problema común de búsqueda de caminos en grafosdirigidos. Supóngase un grafo dirigido G = (V,A) en el cual cada arco tiene unaetiqueta no negativa, y donde un vértice se especifica como origen. El problema esdeterminar el costo del camino más corto del origen a todos los demás vértices de V,donde la longitud de un camino es la suma de los costos de los arcos del camino.Esto se conoce con el nombre de problema de los caminos más cortos con un soloorigen. Obsérvese que se hablará de caminos con <<longitud>> aun cuando loscostos representan algo diferente, como el tiempo.

Sea G un mapa de vuelos en el cual cada vértice representa una ciudad, y cadaarco v → w, una ruta aérea de la ciudad v a la ciudad w. La etiqueta del arco v →w es el tiempo que se requiere para volar de v a w. La solución del problema de loscaminos más cortos con un solo origen para este grafo dirigido determinaría el tiempode viaje mínimo para ir de cierta ciudad a todas las demás del mapa.

Marco teórico

2-18

Para resolver este problema se manejara una técnica <<exhaustiva>> conocidacomo algoritmo de Dijkstra, que opera a partir de un conjunto S de vértices cuyadistancia más corta desde el origen ya es conocida. En principio, S contiene sólo elvértice de origen. En cada paso, se agrega algún vértice restante v a S, cuyadistancia desde el origen es la más corta posible. Suponiendo que todos los arcostienen costo no negativo, siempre es posible encontrar un camino más corto entre elorigen y v que pasa sólo a través de los vértices de S, y que se llama especial. Encada paso del algoritmo, se utiliza una matriz D para registrar la longitud del caminoespecial más corto a cada vértice. Una vez que S incluye todos los vértices, todos loscaminos son especiales, así que D contendrá la distancia más corta del origen acada vértice.

PROCEDIMIENTO Dijkstra COMIENZA (1) S ← 1 (2) PARA i ← 2 HASTA n HAZ (3) D[i] ← C[1,j] asigna valor inicial D (4) PARA i ← 1 HASTA n - 1 HAZ COMIENZA (5) elige un vértice w en V - S tal que D[w] sea un mínimo (6) agrega w a S (7) PARA cada vértice v en V - S HAZ (8) D[v] ← mín(D[v],D[w] + C[w,v]) TERMINA TERMINA Dijkstra

Figura 2.21

El algoritmo se da en la figura 2.21, donde se supone que existe un grafo dirigido G =(V,A) en el que V = 1,2 ..., n y el vértice 1 es el origen. C es una matriz bidimensionalde costos, donde C[i,j] es el costo de ir del vértice i al vértice j por el arco i → j. Si noexiste el arco i→j, se supone que C[i,j] es α, un valor mucho mayor que cualquiercosto real. En cada paso, D[i] contiene la longitud del camino especial más cortoactual para el vértice i.

Aplíquese Dijkstra al grafo dirigido de la figura 2.22. La secuencia de valores D despuésde cada iteración se muestra en la figura 2.23

2A

B C

D

E F

1

1

35

6

4

5

1

Figura 2.22

Marco teórico

2-19

Ieración S w D[B] D[C] D[D] D[E] D[F]Inicial A - ∞ 5 2 6 ∞

1 A,D D ∞ 5 2 6 32 A,D,F F ∞ 4 2 6 33 A,D,F,C C ∞ 4 2 6 34 A,D,F,C,E E 7 4 2 6 35 A,D,F,C,E,B B 7 4 2 6 3

Figura 2.23

Para reconstruir el camino más corto del origen de cada vértice, se agrega otramatriz P de vértices, tal que P[v] contenga el vértice inmediato anterior a v en elcamino más corto. Se asigna a p[v] valor inicial a para toda v ≠ a. La matriz P puedeactualizarse después de la línea (8) de Dijkstra. Si D[w] + C[w,v] < D[v] en la línea (8),después se hace P[v] ← w. Al termino de Dijkstra, el camino a cada vértice puedeencontrarse regresando por los vértices predecesores de la matriz P.

Problema de los caminos más cortos entre todos los pares.

Supóngase que se tiene un grafo dirigido etiquetado que da el tiempo de vuelo paraciertas rutas entre ciudades, y se desea construir una tabla que brinde el menor tiemporequerido para volar entre dos ciudades cualesquiera. Este es un ejemplo del problemade los caminos más cortos entre todos los pares (CMCP). Para plantear el problema conprecisión, se emplea un grafo dirigido G =(V,A) en la cual cada arco v w tiene un costo nonegativo C[v,w]. El problema CMCP es encontrar caminos de longitud más corta entre v yw para cada par ordenado de vértices (v,w).

Este problema podría resolverse por medio del algoritmo de Dijkstra, tomando por turnocada vértice como vértice origen, pero una forma más directa de solución es mediante elalgoritmo creado por R.W. Floyd. Por conveniencia, se supone otra vez que los vértices env están numerados 1, 2, 3,..., n. El algoritmo de Floyd usa una matriz A de nxn en las que secalculan las longitudes de los caminos más cortos. inicialmente se hace A[i,j] = C[i,j] paratoda i ≠ j. Si no existe un arco que vaya de i a j, se supone que C[i,j] = ∝ . Cada elementode la diagonal se hace 0.

Después, se hacen n iteraciones en la matriz A. Al final de la K-ésima iteración, A[i,j] tendrápor valor la longitud más pequeña de cualquier camino que vaya desde el vértice i hastael vértice j y que no pase por un vértice mayor que K. Esto es, i y j, los vértices extremos delcamino, pueden ser cualquier vértice, pero todo vértice intermedio debe ser menor oigual que k.

En la k-ésima iteración se aplica la siguiente fórmula para calcular A

Ak-1[i,j] Ak[i,j] = min Ak-1[i,k]+Ak-1[k,j]

El subíndice k denota el valor de la matriz A después de la k-ésima iteración; no indica laexistencia de n matrices distintas.

Marco teórico

2-20

Para obtener Ak[i,j], se compara Ak-1[i,j], el costo de ir de i a j sin pasar por K o cualquierotro vértice con numeración mayor, con Ak-1[i,k] + Ak-1[k,j], el costo de ir primero de i a k ydespués de k a j, sin pasar a través de un vértice con número mayor que k. Si el paso porel vértice k produce un camino más económico que el de Ak-1[i,j], se elige ese costo paraAk[i,j].Ejemplo. Considérese el grafo dirigido ponderado que se muestra en la figura 2.24.

1

36

5 4

2

1

3

2

3

14

3

2

1

6

2

5

Figura 2.24

Como Ak[i,k] = Ak-1[i,k] y Ak[k,j] = Ak-1[k,j], ninguna entrada con cualquier subíndice igual a kcambia durante la k-ésima iteración. Por tanto, se puede realizar el cálculo sólo con unacopia de la matriz A. En la figura 2.26 se muestra un programa para realizar este cálculo enmatrices de n x n.Es evidente que el tiempo de ejecución de este programa es O(n3), ya que el programaesta conformado por el triple ciclo anidado PARA.

1 2 3 4 5 6 1 2 3 4 5 6 1 2 3 4 5 61 0 3 ∞ 4 ∞ 5 1 0 3 ∞ 4 ∞ 5 1 0 3 ∞ 4 ∞ 52 ∞ 0 1 ∞ 6 1 2 ∞ 0 1 ∞ 6 1 2 ∞ 0 1 ∞ 6 13 ∞ ∞ 0 2 ∞ ∞ 3 ∞ ∞ 0 2 ∞ ∞ 3 ∞ ∞ 0 2 ∞ ∞4 ∞ 3 ∞ 0 ∞ ∞ 4 ∞ 3 ∞ 0 ∞ ∞ 4 ∞ 3 ∞ 0 ∞ ∞5 1 ∞ ∞ 3 0 2 5 1 ∞ ∞ 3 0 2 5 1 4 ∞ 3 0 26 ∞ ∞ ∞ 2 ∞ 0 6 ∞ ∞ ∞ 2 ∞ 0 6 ∞ ∞ ∞ 2 ∞ 0 A0[i,j] A1[i,j] A2[i,j]

1 2 3 4 5 6 1 2 3 4 5 6 1 2 3 4 5 61 0 3 4 4 9 4 1 0 3 4 4 9 4 1 0 3 4 4 9 42 ∞ 0 1 ∞ 6 1 2 ∞ 0 1 3 6 1 2 ∞ 0 1 3 6 13 ∞ ∞ 0 2 ∞ ∞ 3 ∞ ∞ 0 2 ∞ ∞ 3 ∞ 5 0 2 11 64 ∞ 3 4 0 9 4 4 ∞ 3 4 0 9 4 4 ∞ 3 4 0 9 45 1 4 5 3 0 2 5 1 4 5 3 0 2 5 1 4 5 3 0 26 ∞ ∞ ∞ 2 ∞ 0 6 ∞ ∞ ∞ 2 ∞ 0 6 ∞ 5 6 2 11 0 A3[i,j] A4[i,j] A5[i,j]

Marco teórico

2-21

1 2 3 4 5 61 0 3 4 4 9 42 7 0 1 3 6 13 12 5 0 2 11 64 10 3 4 0 9 45 1 4 5 3 0 26 12 5 6 2 11 0 A6[i,j]

Figura 2.25

Floyd calcula la matriz A de caminos más cortos dada la matriz de costos de arcos C, A y C son matrices de n x n denúmeros reales

PROCEDIMIENTO Floyd(VAR:A, C);COMIENZA PARA i := 1 HASTA n HAZ PARA j := 1 HASTA n HAZ A[i,j] := C[i,j]; PARA i := 1 HASTA n HAZ A[i,i] := 0 PARA k := 1 HASTA n HAZ PARA i := 1 HASTA n HAZ PARA j:= 1 HASTA n HAZ SI A[i,k]+A[k,j] < A[i,j] ENTONCES A[i,j] := A[i,j] + A[k,j]TERMINA /* Floyd */

Figura 2.26 Algoritmo de Floyd.

Recuperación de los caminos

En muchos casos se desea imprimir el camino más económico entre dos vértices. Unmodo de lograrlo es usando otra matriz P, donde P[i,j] tiene el vértice K que permitió aFloyd encontrar el valor más pequeño de A[i,j]. Si P[i,j] =0, el camino más corto de i a j esdirecto, siguiendo el arco entre ambos. La versión modificada de Floyd de la figura 2.27almacena los vértices intermedios apropiados en P.

Para imprimir los vértices intermedios del camino más corto del vértice i hasta el vértice j,se invoca al procedimiento camino(i,j) dado en la figura 2.28. Mientras que en una matrizarbitraria P, Camino puede iterar infinitamente, si P viene del procedimiento más corto, noes posible tener por ejemplo, k en el camino más corto de i a j y también tener j en elcamino más corto de i a k. Obsérvese cómo la suposición de pesos no negativos es crucialotra vez.

Marco teórico

2-22

MasCorto toma una matriz de costos C de n x n y produce una matriz A de n x x de longitudes de caminos máscortos y una matriz P de n x n que da un punto en la "mitad" de cada camino más corto. A y C son matrices denúmeros reales y P una matriz de números enteros

PROCEDIMIENTO MasCorto(VAR:A, C, P);COMIENZA PARA i := 1 HASTA n HAZ PARA j := 1 HASTA n HAZ COMIENZA A[i,j] := C[i,j]; P[i,j] := 0 TERMINA PARA i := 1 HASTA n HAZ A[i,i] := 0 PARA k := 1 HASTA n HAZ PARA i := 1 HASTA n HAZ PARA j := 1 HASTA n HAZ SI A[i,k]+A[k,j] < A[i,j] ENTONCES COMIENZA A[i,j] := A[i,j] + A[k,j] P[i,j] := k TERMINATERMINA /* Floyd */

Figura 2.27 programa para los caminos más cortos

PROCEDIMIENTO Camino(i,j)COMIENZA k := P[i,j]; SI k = 0 ENTONCES RETORNA; Camino(i,k); ESCRIBE(k); Camino(k,j)TERMINAS /* Camino */

Figura 2.28 Procedimiento para imprimir el camino más corto

La figura 2.29 muestra la matriz P final para el grafo dirigido de la figura 2.24

1 2 3 4 5 6 1 0 0 1 0 1 1 2 4 0 0 2 0 0 3 4 3 0 0 3 3 4 4 0 1 0 1 1 5 0 0 1 0 0 0 6 4 3 3 0 3 3 P

Figura 2.29

3-1

333Introducción

Los grupos que se forman en un proyecto de capacitación cumplen ciertas característicasque satisfacen los lineamientos establecidos en las políticas de la estructura de laorganización de OCM. Entre estas características se identifica el que los grupos sean paraun campus, tipo de empleado y especialidad en particular, esto es por ejemplo, un grupoes un conjunto de personas que solicitan un curso, sus períodos de disponibilidadcoinciden, todo el personal del grupo son empleados de confianza y todos pertenecen alcampus uno.

Tomando esta idea de conjuntos y considerando al conjunto total de solicitudes decapacitación para un proyecto dado, se describe a continuación una de las estrategiasque se consideraron como alternativa para la solución del problema de la programaciónde cursos.

Esta estrategia tiene como fundamento partir al conjunto total de solicitudes decapacitación para un proyecto por medio de la aplicación de relaciones obtenidas enlas políticas asociadas al proyecto. Con esto se pretende que las particiones tiendan aformar de manera natural los grupos para los cursos.

La estrategia a simple vista parece aceptable sin embargo en la siguiente descripcióntambién se analizan el principal inconveniente que no permiten que esta solución seaóptima de acuerdo a los objetivos pretendidos.

Desarrollo

Dado el conjunto de solicitudes de capacitación para un proyecto, existen tres criteriosque permiten clasificarlas y separarlas en conjuntos más pequeños que faciliten suprogramación. Estos criterios son el campus, tipo de empleado y nivel o especialidad.Cada campus programará sus solicitudes de capacitación independientemente de losotros campus, ayudando así a que cada campus satisfaga en lo más posible su demandade capacitación con sus propios recursos. Con esto se espera disminuir el desplazamientode recursos humanos y materiales y contribuir con ello a la disminución de los costos.

Dentro de las políticas de OCM se sigue que preferentemente se agrupen de maneraseparada el personal de confianza del personal sindicalizado. Por ello el tipo deempleado nos permite hacer una división más al conjunto de solicitudes de capacitacióndando dos conjuntos ajenos uno del personal sindicalizado y otro de personal deconfianza.

Solución funcional

Solución funcional

3-2

Una tercera clasificación se obtiene al dividir las solicitudes por niveles o especialidades.Esto permite agrupar las solicitudes de capacitación de manera que las disponibilidadesde las solicitudes coincidan en lo más posible.

Hasta aquí la estrategia de clasificación nos permite obtener conjuntos ajenos desolicitudes de capacitación manejables independientemente.

El siguiente paso es dividir estos conjuntos para períodos de disponibilidad. Es decirproponer fechas para impartir un curso e integrar en estos períodos al personal que estedisponible para asistir al curso en la fecha propuesta.

Analizando los períodos de disponibilidad individual para cada integrante de losconjuntos hasta ahora obtenidos con las clasificaciones de campus, tipo de empleado ynivel o especialidad, se espera que estos no difieran mucho y por ello se puedan obtenernuevos conjuntos que en sí podrían conformar los grupos finales. Sin embargo en estepunto es donde la estrategia propuesta encuentra el mayor inconveniente para suaplicación.

En la figura 3.1 se simulan los períodos de disponibilidad para un pequeño conjunto deempleados. Suponemos en el conjunto que se muestra para el ejemplo que losempleados pertenecen a mismo centro de trabajo y están ordenados por categoría yantigüedad es decir, el empleado E1 es de mayor categoría y/o antigüedad que elempleado E2 y así sucesivamente. También suponemos que los períodos representansemanas.

Emplead

o

Sem1

Sem2

Sem3

Sem4

Sem5

Sem6

Sem7

Sem8

Sem9

Sem10

Sem11

Sem12

Sem13

Sem14

Sem15

Sem16

Sem17

E1

E2

E3

E4

E5

E6

E7

E8

E9

E10

Vacaciones Periodo crítico DisponibleFigura 3.1

Como se puede observar entre un empleado y otro no difieren más que en su período devacaciones debido a que pertenecen a una misma especialidad o nivel, por esta mismarazón los períodos críticos son comunes.

Ahora se proponen fechas para impartir los cursos y se trata de integrar al personal en losgrupos propuestos de acuerdo a sus disponibilidades. La fechas para los cursos se

Solución funcional

3-3

proponen tomando en consideración, entre otros factores, la duración del curso. Porejemplo supongamos, para facilidad de la explicación, que el curso que se estaprogramando dura tres semanas. Suponemos también que los cursos siempre comienzanen lunes y que no se interceptan días inhábiles. Las fechas para el curso puedenproponerse desde la semana 1 a la semana 3, de la 2-4, 3-5, 4-6, etc.

La figura 3.2 muestra los primeros 16 grupos que se podrían proponer y la distribución delos empleados de acuerdo a sus disponibilidades.

Como se puede observar en la figura para el curso de la semana 1 a 3 se pueden integrarlos empleados E1, E4, E5, E6, E7, E8 y E9. El empleado E10 solo puede asistir a un grupo que seabra en la semana 2 o posterior y el empleado E3 solo puede asistir a un curso que iniciedespués del período crítico de la especialidad.

A los grupos que inician entre la semana 4 y la semana 10 no puede asistir ningúnempleado de la muestra elegida para el ejemplo debido al período critico de laespecialidad que se intercepta en estas semanas.

Cuando se tomaban conjuntos de empleados para un campus, tipo de empleado yespecialidad las particiones se daban de manera directa y única. Sin embargo al generarahora conjuntos con períodos de disponibilidad comunes, un empleado no se integra demanera única a un conjunto y además no se puede agrupar de manera directa porquelas disponibilidades de cada empleado están además sujetas a las disponibilidades de losotros empleados por los criterios de categoría y antigüedad.

I II III IV

V VI VIIVII

IX X XI XII

XIII XIV XV XVI

sem1-sem3 sem2-sem4 sem3-sem5 sem4-sem6

sem5-sem7 sem6-sem8 sem7-sem9 sem8-sem10

sem9-sem11 sem10-sem12 sem11-sem13 sem12-sem14

sem13-sem15 sem14-sem16 sem15-sem17 sem16-sem18

E1,E2,E3,E4,E5,E6E7,E8,E9,

E10

E2,E5,E6E8,E9,E10

E4,E5,E6E7,E8,E9,

E10

E1,E4,E5,E6,E7,E8,

E9

E1,E2,E3,E4,E6,E7,

E8,E10

E1,E2,E3,E4,E7,E8,

E10

E1,E2,E3,E4,E7,E9,

E10

E1,E2,E3,E4,E5,E7,

E9,E10

E1,E2,E3,E4,E5,E6,

E7,E9

figura 3.2

Solución funcional

3-4

Siguiendo con la estrategia de particiones supongamos que el criterio para elegir el grupomás óptimo es elegir aquel que comienza en las primeras semanas del período en quedebe cubrirse el proyecto. Este fundamento da mayor posibilidad de ordenar todos loscursos que conforman en proyecto en el período indicado. También como criterio deelección para un grupo tomemos que el grupo integre al mayor número de empleadosposibles. Estos dos criterios se ponderarían para dar mayor importancia a uno u otro deacuerdo a las necesidades prioritarias del proyecto.

De acuerdo a las suposiciones anteriores se tomaría como grupo el conjunto II de lasemana 2 a 4, a este se integrarían los empleados E4, E5, E6, E7, E8, E9 y E10. Para integrar a losotros empleados (E1, E2 y E3) se podría tomar el grupo XI de la semana 11 a 13.

Con este criterio se tendrían dos conjuntos que podrían formar grupos definitivos. Sinembargo con la aplicación de los criterios de categoría y antigüedad la generación denuevas particiones no es tan directa. Para integrar a un empleado a un conjunto comogrupo se debe hacer de manera individual porque cada asignación de un elemento a unconjunto genera reacomodos en los demás conjuntos. Por ejemplo si integráramos a losempleados al grupo más próximo, para el empleado E2 el grupo correspondiente es el III,esto hace que también los empleados E4 al E10 no puedan integrarse a los grupos más quea partir de éste mismo. Siguiendo con este criterio, el empleado E4 no puede asistir hasta elcurso XI y con ello los empleados E5 a E10 tampoco pueden asistir sino hasta esta semana.Y así sucesivamente continúan los reacomodos en los conjuntos.

Los grupos, integrando los criterios de categoría y antigüedad, quedarían como semuestra en la figura 3.3 después de las primeras asignaciones.

I II III IV

V VI VIIVII

IX X XI XII

XIII XIV XV XVI

sem1-sem3 sem2-sem4 sem3-sem5 sem4-sem6

sem5-sem7 sem6-sem8 sem7-sem9 sem8-sem10

sem9-sem11 sem10-sem12 sem11-sem13 sem12-sem14

sem13-sem15 sem14-sem16 sem15-sem17 sem16-sem18

E8,E9,E10

E2E1

E3,E4

E5 E6,E7

Figura 3.3

En la figura se muestra que el empleado E1 se puede integrar al conjunto I; para elempleado E2 el conjunto más próximo es el III. El empleado E3 solo puede asistir hasta el

Solución funcional

3-5

grupo XI junto con el empleado E4. Como se puede observar en la figura 3.2 el empleadoE4 podría haberse integrado al conjunto I ó II pero la asignación del empleado E3 lo limitohasta el conjunto XI. De manera semejante sucede para las asignaciones de losempleados restantes.

Las disponibilidades de los empleados no proporciona particiones únicas y directas en elconjunto de empleados es por esta razón que la idea de las particiones no proporcionouna buena alternativa como solución para el problema de horarios. No se desechatotalmente puesto que las primeras clasificaciones de campus, tipo de empleado yespecialidad se aplicaron en la solución final dividiendo así el problema total en conjuntosmás pequeños manejables independientemente.

4-1

444Introducción

El proceso para la programación de cursos se puede describir de manera general comose muestra en la figura 4.1

Programacion delpersonal

sindicalizado

Solicitudes decapacitación paraun proyecto en un

campus

Definición deacuerdos y

lineamientos

Preparación dedaos para la

programación decursos

Programaciónautomatica

Programación delpersonal deconfianza

Selección decursos a

programar

Selección desolicitudes a

programar paracada curso

Generación degrupos

alternativos

Asociaciónparticipante-

grupo alternativo

Asignaciónparticipantes a

grupos

Generación degrupos

definitivos

Asignación derecursos

Figura 4.1

El proceso comienza cuando OCM define un proyecto de capacitación ya sea pordetección de necesidades o por requerimientos. De acuerdo a los objetivos y a ladirección que se define en el proyecto se generan las solicitudes de capacitacióncorrespondientes para cubrir las necesidades de éste.

Posteriormente cada campus genera de manera independiente un programa queatiende las solicitudes del proyecto en su área de dominio. En esta parte es donde entraen juego el proceso automático de la programación de cursos.

Solución por procedimiento

Solución por procedimiento

4-2

Antes de ejecutar el proceso automático de la programación de cursos se definen losacuerdos y lineamientos que regirán el proceso de programación. Se define también elcalendario al cual debe ajustarse la programación. Con este calendario se establece lafecha de inicio y finalización del proyecto y las fechas dentro del período del proyectoque no son fechas laborables para capacitación.

Otros procesos que se efectúan anteriormente al proceso automático, es la preparación oinicialización de algunas tablas de donde el proceso automático tomará datos. Entreestas tablas se pueden mencionar las siguientes: la tabla de cursos ordenados porseriación; tabla de rutas mínimas entre localidades; tabla de contadores del personal encapacitación por día y centro de trabajo; tabla de contadores del total de personal encapacitación de OCM por día.

En la programación automática de los cursos se procesan de manera separada lassolicitudes del personal de confianza del personal sindicalizado con el fin de dividir de estamanera el problema general en partes más pequeñas. Esta consideración se basa en elhecho de que dentro de los lineamientos este es un acuerdo que se establece de manerafrecuente por razones de tipo laboral y por la orientación de la capacitación.

El siguiente paso en el proceso automático es la elección de los cursos que se van aprogramar. Teniendo la lista de cursos se efectúa un proceso de programación para cadacurso. En la programación del curso se seleccionan las solicitudes a programar para elcurso y se lleva a cabo la generación de grupos con estas solicitudes para el curso dado.

La generación de grupos para un curso es la parte más importante del procesoautomático porque es en esta etapa donde el programa del proyecto va adquiriendo suforma final.

En la generación de grupos para un curso primero se definen todos los grupos posiblesque se pueden abrir a lo largo del período del proyecto. Para la definición de estos gruposse considera la duración del curso y los requerimientos de instalaciones y equiposnecesarios para su dar el curso.

Posteriormente se relacionan las solicitudes del curso con los grupos propuestosasociándolos por medio de una función de costo - beneficio en la que se evalúan variosfactores como son el costo estimado para el grupo y la fecha para impartir el curso.Además para que se dé la asociación entre un solicitante y un grupo propuesto, elparticipante debe estar disponible en la fechas que define el grupo para impartir el curso.

El siguiente paso es definir para cada participante el grupo alternativo de costo mínimo yasignarlo a éste. Para asignar un participante a un grupo, el participante debe estardisponible en la fechas en que se efectúa el curso, el grupo no debe pasar del númeromáximo de participantes y los porcentajes de personal en capacitación por centro detrabajo y totales no deben excederse.

Al asignar al participante al grupo también se efectúan otros procesos como sonincrementar los contadores del personal en capacitación y afectar asociaciones de otrosparticipantes.

Solución por procedimiento

4-3

Dentro del proceso de generación de grupos se define un grupo como definitivo cuandosus asignaciones han llegado al mínimo de participantes definido para el curso. En estemomento se asignan recursos al grupo. Si la asignación de recursos tiene éxito, el grupopropuesto se define como grupo real para el programa de capacitación y se inscriben demanera definitiva todos los participantes hasta el momento asignados. Si la asignación derecursos no tiene éxito se desintegra el grupo, se restablecen las relaciones de losparticipantes asignados y se comienza de nuevo con el proceso para asignar a losparticipantes a otro grupo alternativo.

Para que el proceso de la generación de grupos no llegase a hacerse infinito seintrodujeron procesos de depuración y condiciones de decisión para precipitar laconclusión del proceso.

Ésta es en general la descripción del proceso de solución final para la programaciónautomática de los cursos. En las siguientes secciones se efectúa la descripción detalladade cada una de las etapas principales del proceso.

Definición del modelo de solución para la programación decursos

Requerimientos de información para realizar la programación de los cursos

Información sobre los participantes

• Número de expediente (Clave de empleado)• Especialidad• Antigüedad• Categoría• Período de vacaciones• Período crítico de trabajo,• Tipo de empleado (sindicalizado, confianza)• Cursos solicitados• Centro de trabajo en el cual labora,• Campus al cual pertenece

Información general de los recursos humanos del cliente

• Población total del cliente,• Población por centro de trabajo• Información sobre los cursos• Cronograma del curso• Duración• Cupo máximo en un grupo,• Cupo mínimo en un grupo• Instalaciones y equipos necesarios para impartir el curso• Cronograma de uso para instalaciones y equipos• Seriación de los cursos

Solución por procedimiento

4-4

• Cual es el máximo de grupos simultáneos de un curso que se pueden abrir (Debidoa limitaciones de instructores, instalaciones o equipo tal como maquetas,laboratorios, aparatos o herramientas especiales)

Información general sobre los cursos de un proyecto

• Volumen total de cursos solicitados• Volumen de solicitudes por curso

Información sobre las instalaciones y equipos del cliente y del instituto utilizadas paracapacitación

• Inventario de instalaciones y equipos propiedad del cliente y del instituto utilizadaspara la capacitación

• Períodos y horarios de disponibilidad de instalaciones y equipos• Costo por utilización de instalaciones y equipos• Ubicación de las instalaciones y equipos

Información sobre los proveedores de capacitación, proveedores de equipo yproveedores de instalaciones

• Inventario de cursos, instalaciones y equipos por proveedor• Disponibilidad de los proveedores y sus recursos• Costos de renta de los recursos de los proveedores• Información sobre los paquetes (curso, instalaciones y equipo) ofrecidos por los

diferentes proveedores.

Información sobre las aulas

• Ubicación• períodos de disponibilidad (a nivel hora)• Tipo de aula• Cupo

Información sobre los instructores del instituto

• Clave• Períodos de disponibilidad• Cursos que puede impartir• Costo por curso que imparte• Formas de cobro

Información sobre instructores del cliente (recursos humanos del cliente que puedenasignarse para proporcionar capacitación)

• Clave del instructor

Solución por procedimiento

4-5

• Clave del tipo de instructor• Cursos que puede impartir• Forma de remuneración por curso• Períodos de disponibilidad• Cursos que puede impartir

Información sobre costos adicionales

• Viáticos (por día) para la estancia de instructores en la localidad donde seimpartirán los cursos

• Viáticos por viaje para los instructores a la localidad donde se impartirán los cursos• Viáticos (por día) para la estancia de los participantes en la localidad donde se

imparten los cursos• Viáticos para viaje de participantes a la localidad donde se impartirán los cursos

Información sobre los proyectos de capacitación

• Períodos en los que debe cubrirse cada proyecto• Proveedores de capacitación involucrados

Información sobre lineamientos

• Cuantos recursos humanos de una mismo centro de trabajo pueden tomarcapacitación simultánea.

• Cuantos recursos humanos del total de recursos de OCM pueden tomarcapacitación simultánea.

• Especificación de recursos con los cuales se debe cubrir la demanda para unproyecto (recursos del instituto, recursos del cliente, recursos de proveedores ocombinación de ellos)

• Porcentajes de comisión para instructores• Aplicación de criterios de escalafón para la asignación de participantes a los cursos

Solución por procedimiento

4-6

Restricciones del modelo

El modelo de solución deberá ajustarse a las siguientes restricciones para la programaciónde los cursos

1. Las fechas de los cursos deberán ajustarse a las disponibilidades de los participantes.La disponibilidad se determina de acuerdo al período de vacaciones y a la cargade trabajo

2. Los instructores deberán asignarse de acuerdo a sus disponibilidades y ajustándosea las fechas de los grupos

3. Un participante, un instructor, un aula o un instalación equipo no podrán estarasignados a dos grupos simultáneamente

4. Se deberá respetar, cuando así se defina, el escalafón. Si dos participantes solicitanun mismo curso y son de un mismo centro de trabajo el participante de mayorcategoría deberá ser programado primero, si son de la misma categoría el demayor antigüedad deberá ser programado primero.

5. Se deberá respetar la seriación de los cursos. Un participante que solicita dos o máscursos que están seriados deberá ser programado de tal manera que se respete laseriación

6. No sobrepasar el máximo de grupos simultáneos de un curso. Esto es debido a quepuede haber limitaciones de instructores, instalaciones o equipo, o debido alineamientos.

7. No sobrepasar el cupo máximo de un grupo

8. No crear grupos con menos del cupo mínimo

9. No asignar a los participantes a capacitación en períodos críticos de suespecialidad

10.En el caso de cursos que requieren instalaciones o equipos limitados las fechas delos grupos deberán ajustarse a las disponibilidad de dichas instalaciones o equipos.Estas instalaciones pueden pertenecer al cliente o al instituto .

11.No sobrepasar el numero máximo de participantes del total de población de OCMque pueden tomar capacitación simultánea.

12.No sobrepasar el máximo número de participantes de un centro de trabajo quepueden asistir a capacitación simultánea.

Estos dos criterios se aplican para evitar que en un momento dado un centro detrabajo o incluso toda la institución se vea detenida por completo al estar encapacitación todo su personal.

Solución por procedimiento

4-7

13.Satisfacer la demanda de recursos ajustándose a lo indicado en los lineamientos.Esto es, tomar recursos del cliente, del instituto, de proveedores o combinación deellos para satisfacer los requerimientos del proyecto.

Restricciones de procesamiento

Para el proceso de la programación de cursos se toman las siguientes consideracionespara la selección de las estructuras de datos y los algoritmos.

Dada la magnitud del volumen de los datos con los cuales se lleva a cabo el proceso sedebe evitar el uso de procesos recursivos; se debe procurar tener en memoria lainformación necesaria para evitar en lo posible el número de accesos a la base de datosy agilizar de esta manera algunas consultas que se repetirán constantemente.

El tamaño de las estructuras de datos deben elegirse de manera que empleen el menorespacio posible de memoria. Para ello se utilizan arreglos de bits, y memoria dinámica.

Procesos previos a la programación de cursos

Existen algunos procesos que se necesitan en cada proyecto pero que sin embargo losdatos que generan no cambian entre un programa y otro es decir, son procesos que sepueden ejecutar solo una vez y no en cada proyecto por que son independientes de loslineamientos o políticas que definen a cada proyecto. También existen otros procesos quedeben iniciar tablas para cada proyecto. Estos procesos son los que se generan fuera delproceso automático de programación.

Existen principalmente tres procesos que deben efectuarse antes a la programaciónautomática, éstos son:

• La creación de una vista de cursos ordenada por seriación.

• La creación de tablas de rutas mínimas entre localidades para el calculo de viáticosde transportación

• Inicialización de tablas de contadores de personal en capacitación por centro detrabajo y día.

Ordenación de cursos

En la generación automática de cursos se genera una lista de los cursos que se van aprogramar para un proyecto y se generan grupos para cada curso en la lista tomándolossecuencialmente.

El orden de los cursos considerando su seriación es una característica que esindependiente de los lineamientos o acuerdos de cada proyecto. El orden de los cursospor seriación solo depende de las currículas o planes de estudio, por ello la ordenación de

Solución por procedimiento

4-8

los cursos se efectúa solo una vez cada que se requiera y este orden se mantiene en unatabla de manera permanente.

El proceso de ordenación se efectúa con un algoritmo muy semejante al método de“burbuja”. Se toman todos los cursos dados de alta y se genera con ellos una listadoblemente ligada. La lista se recorre del último elemento al primero. Con cada uno delos cursos se realiza una búsqueda hacia adelante de los prerrequisitos de éste y semueven de posición en caso de que se encuentren. Para generar un orden entre loscursos también se considera la duración del curso en orden descendente es decir, si doscursos no son prerrequisitos entonces el orden lo da el número de horas de duración delcurso.

Supongamos que se tienen los planes de estudio que se muestran en la figura 4.2

Curso ADuración:

15 hrs.

Curso BDuración:

10 hrs.

Curso CDuración:

10 hrs.

Curso DDuración:

10 hrs.

Curso EDuración:

15 hrs.

Curso FDuración:

12 hrs.

Curso GDuración:

10 hrs.

Curso HDuración:

10 hrs.

Curso IDuración:

12 hrs.

Curso ADuración:

15 hrs.

Curso BDuración:

10 hrs.

Curso CDuración:

10 hrs.

Curso DDuración:

10 hrs.

Curso EDuración:

15 hrs.

Curso FDuración:

12 hrs.

Curso GDuración:

10 hrs.

Curso HDuración:

10 hrs.

Curso IDuración:

12 hrs.

Curso E’Duración:

10 hrs.

curricula I curricula II

Figura 4.2

Como se puede observar se supone que se puede dar el caso de que un curso tenga másprerrequisitos en una currícula que en otra como es el caso del curso H que en la currículaI solo tiene como prerrequisitos el curso e y en la currícula II tiene como prerrequisitos elcurso E y E'. Además se supone que la relación de prerrequisitos entre dos cursos mantienesu dirección en todas las currículas donde se presente y que nunca se ocurre la relaciónde manera inversa. Por ejemplo si el curso A es prerrequisito del curso D en la currícula I noexiste ninguna otra currícula donde el curso D sea prerrequisito de A. Esta es unasuposición lógica que se toma como cierta para la ordenación de los cursos.

Si la lista de cursos inicial se obtuviera así: [AEFIBCDE'GH]; la lista ordenada sería comosigue: [ABECFIDE'GH].

De la figura 4.2 podría esperarse que el orden fuera como sigue: [ABCEFDE'IGH]. Esto seríasi se pudiera tomar en consideración el nivel en el que se encuentran los cursos. Sinembargo el nivel no es una característica propia del curso y puede variar mucho entreuna currícula y otra. En el apéndice B se encuentra el programa para la ordenación decursos.

Rutas mínimas entre localidades

Solución por procedimiento

4-9

La organización cliente modelo es una institución cuya magnitud abarca todos losestados del país. Para la administración se organiza en nueve campus. Cada campusabarca diferentes estados federativos y estos a su vez asocian a diferentes localidades.Cada recurso humano esta registrado en un centro de trabajo en una determinadalocalidad.

Cuando un empleado asiste a capacitación es muy frecuente que tenga que trasladarsede su localidad de trabajo a otra localidad en la cual se impartirá el curso. Para efectosdel modelo de programación automático se trata de evitar en lo más posible eldesplazamiento de recursos entre localidades para disminuir los costos de viáticos detransportación. Esto se logra integrando el costo de viáticos en la asociación entre lossolicitantes y los grupos propuestos.

Para el calculo de los viáticos de transporte es necesario conocer el costo de transporteentre una localidad origen y una localidad destino. Para ello se debe tener registrado elmonto por concepto de transporte para cada par de localidades. Este problema sepuede modelar por medio de un grafo dirigido en el que los nodos representan laslocalidades, las aristas la conexión entre las localidades por medio de algún tipo detransporte y el valor de las aristas representa el importe de transportación

Al trasladarse de una localidad a otra se pueden presentar los siguientes casos:

1. Que no se paguen viáticos de transporte de la localidad origen a la localidaddestino

2. Que se paguen viáticos para una ruta directa entre la localidad origen y lalocalidad destino

3. Se tiene que pagar viáticos a localidades intermedias entre la localidad origen y lalocalidad destino es decir, existe una ruta indirecta entre la localidad origen ydestino.

Para los casos en que deba pagarse viáticos se debe minimizar el costo de éstos. Paraeste fin se utiliza el concepto del problema de los caminos más cortos entre los nodos deun grafo donde los nodos del grafo representan las localidades y las aristas del graforepresentan el costo de transportación de una localidad a otra.

Existen además diferentes medios de transporte para los que se pagan viáticos (autobús,avión, tren, etc.) y por lo tanto también diferentes costos para cada tipo de transporte.

La función de costo para los viáticos de transporte es una función del costo de transportey del valor de comodidad del medio de transporte. Ambos afectados por un factor deponderación respectiva que hace que la función se incline hacia uno u otro parámetro

fviáticos = Factor Costo * CostoTransporte + ValorComodidad * (100 - FactorCosto)

Para la función de viáticos primero se calculan las rutas mínimas entre todas laslocalidades para todos los medios de transporte. Esto se hace por medio del algoritmo de

Solución por procedimiento

4-10

Floyd1 y se guarda en la base de datos de manera permanente. Este proceso se realizasolo una vez fuera de la programación automática de los cursos y la información sirvepara todos los proyectos.

Dentro del modulo de la programación automática de cursos se aplica la función a cadauna de los rutas mínimas de los diferentes medios de transporte y se elige la de menorcosto - beneficio de acuerdo a la función.

Tablas de contadores de personal en capacitación

La capacitación en la institución cliente modelo es una actividad que nunca se detiene;siempre existen proyectos en ejecución y siempre hay personal en capacitación.

Para generar un nuevo programa se debe tomar en cuenta los datos de los proyectos yaprogramados y en ejecución para procurar que la actividad de la institución no sedetenga por los proyectos de capacitación. Esto es, se debe evitar que en un día, en uncentro de trabajo no haya actividad laboral a causa de que todo el personal seencuentre asistiendo a capacitación, o incluso evitar que toda la institución pueda versedetenida en un día o periodo por los proyectos de capacitación. Para este fin se crea unatabla con el número de personas que se encuentran programadas para capacitaciónpor día para cada centro de trabajo.

También se requiere conocer cuantos empleados del total de personal del instituto seencuentran en capacitación. Este dato se obtiene de una tabla de contadores depersonal en capacitación por día para toda la institución cliente.2

Al momento de definir un nuevo programa se establece como parámetro un porcentajeque indica cuántas personas como máximo del total de un centro de trabajo puedenprogramarse en un mismo día a capacitación. También se define un porcentaje parasaber cuántas personas como máximo de todo el personal de OCM pueden asistir acapacitación en un mismo día.

El proceso automático de la programación de cursos toma los datos de las tablas decontadores para saber si es posible asignar a un recurso humano a un grupo sin excederlos porcentajes de personal por centro de trabajo y general establecidos.

Veamos este proceso con un ejemplo. Supongamos que se va a programar a unempleado a un curso que dura 8 días y la fecha de inicio del curso al cual se deseaasignarlo es el 01/marzo/92. En el centro de trabajo del empleado existen un total de 30personas y el porcentaje de empleados que pueden asistir a capacitación en un mismodía por centro de trabajo se establece como el 50% y lo mismo para toda la institución. Elporcentaje indica que del centro de trabajo del empleado en estudio pueden asistir acapacitación en un mismo periodo 15 personas a la vez. Para verificar que el empleado

1 Par más información del algoritmo de Floyd ver la sección del el problema de los caminos más cortos entre todoslos pares en el capitulo de marco teórico.

2La tabla de contadores de personal en capacitación por día para toda la institución realmente no esnecesaria ya que este datos se puede obtener a partir de la tabla de contadores por centro de trabajo.

Solución por procedimiento

4-11

puede asignarse al grupo propuesto se verifica para cada uno de los días que durará elcurso cuantas personas están ya asignadas a capacitación de modo que asignando alempleado en estudio no se excedan las 15 personas permitidas. Esto mismo se hace parael total de personal de OCM. Si el total de personal del cliente son 1000 personas solopueden estar en capacitación en un mismo día 500.

Si al verificar el número de personas actualmente asignadas a capacitación para elcentro de trabajo del empleado de estudio se obtiene que ya existen 15 personasasignadas entonces se establece que no es posible asignarlo a dicho grupo. Sin embargopuede ser que solo un día se asignen más de 15 personas. En este caso se podría haceruna excepción y decidir asignar al empleado al grupo. Para estas excepciones seestablecen otros dos parámetros: 1) un porcentaje que de cierta manera se suma alporcentaje que indica cuantas personas pueden asistir a capacitación en un mismo día y2) un porcentaje que indica que cuantos días dentro de un periodo se puede tomar elporcentaje excedente para asignar personas a capacitación.

Siguiendo el ejemplo se establece que adicionalmente podrían ir dos personas más acapacitación para el centro de trabajo del empleado en estudio. Esto es siempre ycuando el número de días para los cuales se asignen las 17 personas no excedan en 3digamos. Estos parámetros se establecen también como porcentajes.

Las tablas de contadores de personal en capacitación se inician una sola vez y semantienen los datos para todos los proyectos. 3

Parametrización del modelo de programación de cursos

Definición de acuerdos y lineamientos

Los acuerdos y lineamientos son políticas de OCM que se establecen para la generaciónde un programa de capacitación. Entre los lineamientos que se definen regularmente sepueden mencionar los siguientes.

• Aplicación del escalafón en la asignación de participantes a grupos. Si dosparticipantes de un mismo centro de trabajo solicitan un mismo curso se debeprogramar primero al de mayor categoría o nivel. Si son de la misma categoría sedeberá programar primero al de mayor antigüedad.

• Se definen porcentajes de empleados de un centro de trabajo que pueden asistir acapacitación simultáneamente por día.

• Porcentajes de personal de OCM que puede asistir a capacitaciónsimultáneamente.

3Si los porcentajes de personal permitidos para capacitación simultánea se cambian para los diferentesproyectos la verificación de los mismos no será real. Por ejemplo si se establece para un proyecto el 20% ypara uno posterior el 30% En las fechas de intersección entre los dos proyectos se verificarán como 30% lo cuales valido para uno pero viola los parámetro establecidos para otro.

Solución por procedimiento

4-12

• Se define el tipo de personal al cual se dirige el programa (sindicalizado, confianza,o ambos)

• Porcentajes de comisión para instructores

• Definición del tipo de recursos con los que se debe satisfacer las necesidades delprograma

Recursos propios (equipo, instalaciones e instructores de OCM e ITM)Recursos de proveedoresCombinación de recursos propios y de proveedores.

En el proceso automático de generación de grupos se necesitan además de loslineamientos del proyecto listados anteriormente otros valores de parámetros que ayudenen la toma de decisiones del proceso. Estos parámetros también deben definirse comolineamientos.

Dentro de los parámetros para la toma de decisiones se pueden listar los siguientes:

• Porcentajes de ponderación par los diferentes factores que intervienen en laelección de un grupo para un participante.

• Definición del número de veces que debe intentarse reprogramar las solicitudes conel modelo de costo mínimo para evitar que se intente indefinidamente.

• Definición de criterios para elegir definir un grupo como real o desintegrarlo

• Definición del número de días que se requieren para que un participante se trasladede una localidad a otra.

Los lineamientos para el programa se traducen para el procesamiento en una lista deparámetros que identifican cada lineamiento con una clave y un valor. Estos parámetrosse definen anteriormente el proceso automático en una tabla donde se tiene la clave delparámetro, su valor, una descripción abreviada y una descripción detallada de susignificado.

En el apéndice A se encuentran todos los parámetros que se definen para laprogramación automática, sus valores y su descripción.

Solución por procedimiento

4-13

Definición del calendario para el proyecto

El calendario del proyecto es una tabla donde se definen las fechas en las que porlineamiento o por ser día festivo aceptado por el cliente y el instituto no son fechaslaborables para la impartir la capacitación. La definición de este calendario es unproceso que se efectúa como preparación a la programación automática de los cursos.Este calendario se traduce para efectos de la programación en un arreglo de bits. Eltamaño del arreglo se determina con el número de días que existen entre la fecha inicial yla fecha final del período del proyecto. Cada bit en el arreglo representa un día en elperíodo u su valor, 0 ó 1, representa día hábil o inhábil respectivamente.

Solución por procedimiento

4-14

Proceso de programación de cursos

Los módulos principales del proceso de la programación de cursos se muestran en lasfiguras 4.3, 4.3, 4.5 y 4.6. Estos algoritmos describen de manera general el proceso de laprogramación de cursos

/* Módulo iniciador de la generación automática de grupos */PROC ProgramacionCursos(Proyecto,Campus)COMIENZA EdoProyecto := ObtenPeriodoProyecto(Proyecto,PeriodoProyecto) SI EdoProyecto = 1 ENTONCES /* El status del proyecto indica que es aceptado */ COMIENZA ObtenListaParametros(Proyecto,Campus,GLBListaParametros) ObtenCalendario(PeriodoProyecto) CadTipoEmpleado := Parametro('AsigTipoEmp') SI SeEncuentra("SINDICALIZADOS",CadTipoEmpleado) ENTONCES ProgramaCursosParaTipoEmp(Proyecto,Campus,SINDICALIZADO,PeriodoProyecto) SI SeEncuentra("CONFIANZA",CadTipoEmpleado) ENTONCES ProgramaCursosParaTipoEmp(Proyecto,Campus,CONFIANZA,PeriodoProyecto) TERMINATERMINA

Figura 4.3

PROC ProgramaCursosParaTipoEmp(Proyecto,Campus,Tipo,PeriodoProyecto)COMIENZA ObtenNumCursosxPart(GLBPartNumCursos,Campus,Proyecto,Tipo) SeleccionaCursos(Tipo,Proyecto,Campus,ListaCursos) /* Genera una lista ligada con mínimo y máximo de participantes */ OrdenaCursos(NULL,ListaCursos,Tipo) /* Ordena la lista de acuerdo a la vista de cursos VistaCursosOrdSeriac */ InvierteListaCursos(NULL,ListaCursos,ListaCursos) /* El procedimiento OrdenaCursos deja la lista invertida, por lo que se ProgramaCursoxCurso(Tipo,ListaCursos,Proyecto,Campus,PeriodoProyecto) Libera(ListaCursos)TERMINA

Figura 4.4

Solución por procedimiento

4-15

PROC ProgramaCursoxCurso(Tipo,ListaCursos,Proyecto,Campus,PeriodoProyecto)COMIENZA ApCurso := ListaCursos MIENTRAS Curso <> NIL HAZ COMIENZA TotalSolicitudes := 0 EligeParticipantes(Tipo,Proyecto,Campus,ApCurso,ListaParticipantes,TotalSolicitudes) /* Este procedimiento genera una lista ligada ordenada para un campus,centro de trabajo, categoria y antigüedad. Sus campos son: ClaveEmpleado,ClaveCentroTrab, Liga y ListaGruposAfectados. TotalSolicitudes es el tamaño de la lista de participantes */ GeneraListaRecursos(ApCurso,ListaRecursosRequeridos,Campus) /* ListaRecursos es un registro de dos listas ligadas, una para tipos de equipos y una para tipos de instalaciones que requiere el curso para impartirse. Se incluye el cronograma del curso. */ GeneraGrupos(PeriodoProyecto,Proyecto, Campus, ApCurso, ListaParticipantes, ListaRecursosRequeridos, TotalSolicitudes,Tipo) /* Deja el resultado en la tabla Grupos y sus asociaciones de instalaciones, Equipos, Instructores Proveedores y part. */ ApCurso := ApCurso^.liga Libera(ListaParticipantes) Libera(ListaRecursosRequeridos.ListaEquiposRequeridos) Libera(ListaRecursosRequeridos.ListaInstalRequeridas) Libera(ListaRecursosRequeridos.InstructoresPosibles.ListaInstructores) Libera(ListaRecursosRequeridos.InstructoresPosibles.ListaProveedores) TERMINATERMINA

Figura 4.5

Solución por procedimiento

4-16

PROC GeneraGrupos(PeriodoProyecto,Proyecto,Campus,ApCurso,VAR ListaParticipantes,ListaRecursosRequeridos,TotalSolicitudes,TipoEmp)COMIENZA AbrePosiblesGrupos(PeriodoProyecto,Campus,ApCurso,GruposPosibles,ListaRecursosRequeridos, CantGposPosibles,DatosFuncionGLB.CostoMin,DatosFuncionGBL.CostoMax) CreaAsigParticPosibles(ListaParticipantes,GruposPosibles,CantGruposPosibles,PeriodoProyecto) SolicProgramadas := SolicNoProgramadas := NumReprogramanciones := 0 DebeProgramar := CIERTO NumVecesAplicacion := Parametro('CantProgRem') ApPartActual := ListaParticipantes MIENTRAS DebeProgramar HAZ COMIENZA MIENTRAS PartActual <> NIL HAZ COMIENZA EligeAsigPartCostoMin(ApPartActual,GruposPosibles,ApGrupoPosible) SI ApGrupoPosible != NULL ENTONCES COMIENZA SI CumplePorcentajesLineamientos(ApCurso,ApPartActual,ApGrupoPosible) ENTONCES COMIENZA AsignaPartAGrupo(ApPartActual,GruposPosibles, ApGrupoPosible) SI CubreMínimoPart(ApCurso,ApGrupoPosible) ENTONCES COMIENZA SI PuedeAsignarRecursos(PeriodoProyecto,ApCurso,ApGrupoPosible, ListaRecursosRequeridos,ListaRecursos,CveCampus) ENTONCES COMIENZA ApPartActual := ApPartActual^.Liga DefinirGrupoDefinitivo(ListaParticipantes,ApGrupoPosible,ApCurso, ListaRecursos,ListaRecursosRequeridos, TablaCorrespGrupos,Proyecto,TipoEmp) SolicProgramadas := SolicProgramadas + ApCurso .MinParticipantes TERMINA OTRO COMIENZA EliminaGrupoPosible(GruposPosibles, ApGrupoPosible,ListaParticipantes) ApPartActual := ListaParticipantes TERMINA TERMINA OTRO COMIENZA SI EstáEntreMinyMax(ApCurso,ApGrupoPosible) ENTONCES COMIENZA AsignaPartDefinitivamente(ListaParticipantes, ApPartActual,ApGrupoPosible, TablaCorrespGrupos) SolicProgramadas := SolicProgramadas + 1 TERMINA OTRO ApPartActual := ApPartActual^.Liga SI CubreMáximoPart(ApCurso,ApGrupoPosible) ENTONCES CierraGrupo(PeriodoProyecto,GruposPosibles,ApGrupoPosible,TablaCorrespGrupos, ListaRecursosRequeridos) TERMINA TERMINA TERMINA OTRO ApPartActual:= ApPartActual^.Liga TERMINA DepuraListaParticipantes(ListaParticipantes,SolicNoProgramadas) DebeProgramar := AplicarMismoMetodo(TotalSolicitudes,SolicProgramadas,SolicNoProgamadas, NumVecesAplicacion,NumReprogramaciones) SI DebeProgramar ENTONCES DepuraAsociaciones(GruposPosibles,ApCurso,ListaParticipantes) TERMINA ProgramaRemanente(PeriodoProyecto,Proyecto,Campus,ListaParticipantes,ListaRecursosRequeridos,ApCurso, GruposPosibles,TablaCorrespGrupos,CantGposPosibles,TipoEmp) TerminaProcesoCurso(GruposPosibles,TablaCorrespGrupos)TERMINA

Figura 4.6

Como se puede observar en los procedimientos el proceso de la programación decursos primeramente realiza una clasificación de solicitudes por campus. Estaclasificación se debe a la independencia relativa que existe en la operación de loscampus.

Solución por procedimiento

4-17

El siguiente paso es la clasificación de solicitudes por tipo (sindicalizado o confianza).Por razones de tipo laboral y por la orientación de la capacitación es convenienteprogramar separadamente la capacitación del personal de confianza ysindicalizado. El instituto trata de dar mayor prioridad al sindicato, por ello seprograman primero a los empleados sindicalizados que a los de confianza

Como siguiente paso se realiza una clasificación de solicitudes por curso. Estaclasificación facilita el llenado de los grupos de acuerdo a la seriación de los cursos.

Se clasifican las solicitudes por centro de trabajo. Esta clasificación facilita laasignación de participantes de un mismo centro de trabajo. En la medida en que selogre impartir los cursos en la localidad de trabajo de los participantes se podrá evitarel desplazamiento del personal a otras localidades y se minimizarán los gastos porviáticos para los participantes.

Se clasifican las solicitudes por categoría del solicitante. Esta clasificación permiteasignar a los participantes de acuerdo a su categoría.

Se clasifican las solicitudes por antigüedad del solicitante. Esta clasificación permiteasignar a los participantes de acuerdo a su antigüedad.

Se Generan grupos de tal modo que se puedan impartir la mayor cantidad de cursossolicitados. Este proceso define grupos con participantes y calendarios, considerandola disponibilidad de los participantes, los periodos de programación y loslineamientos. Para el logro de la segunda parte del objetivo (al menor costo) debetomarse en cuenta la ubicación de los participantes y los costos que implica eldesplazamiento de los participantes desde sus localidades de trabajo a los plantelesdonde se ofrecerá la capacitación.

se realiza la asignación de instructores a los grupos. Los criterios de selección yasignación de los instructores de capacitación deben considerar el costo por cursoimpartido, el índice de calidad, la capacidad de cursos simultáneos y ladisponibilidad de los instructores y los acuerdos y lineamientos. Un factor adicionalque debe tomarse en cuenta es la ubicación de las localidades de capacitación,debido a que puede ser necesario que el instructor se desplace desde su localidadpara impartir la capacitación, o en casos extremos, si el instructor no tuviera ladisponibilidad para viajar, sea él el que determine la localidad de capacitación. Aligual que con los participantes se debe tratar de hacer las asignaciones deinstructores de modo que se obtengan costos mínimos.

Se realiza la asignación de instalaciones/equipos. Los criterios de asignación deinstalaciones/equipos deben tomar en cuenta su disponibilidad y ubicación, ya queal igual que con los instructores, pueden ser éstos los que determinen tanto las fechascomo los planteles para ofrecer la capacitación.

Solución por procedimiento

4-18

Para la asignación de instalaciones, equipos e instructor se consideran tanto recursosmateriales y humanos de OCM como de ITM seleccionándolos de acuerdo a loscriterios dados en los en los párrafos anteriores. Para cubrir la capacitación tambiénse toman en cuenta proveedores externos tanto al instituto como al cliente. Losproveedores proporcionan paquetes de capacitación, es decir cursos que incluyencapacitación, instalaciones y equipos. Para seleccionar a los proveedores se tomaen cuenta la calidad y el costo de los paquetes que proporcionan. Un puntoimportante en la selección de un proveedor para capacitación es que para solicitarlecualquier recurso, como aulas y equipo, se debe solicitar también la capacitación, deotra manera no se puede solicitar a proveedores de capacitación solo los recursosmateriales de un curso.

Generación de grupos propuestos

A continuación se presenta el proceso general para la generación de grupos:

Para cada proyecto/campus se realizan los siguientes procesos para la preparaciónde la programación de los cursos:

Se obtienen los datos del proyecto necesarios para la programación como son: lafecha de inicio y finalización del proyecto de capacitación, la lista de lineamientos oparámetros que se aplicarán en la elaboración del programa de capacitación y lalista de cursos que se deben cubrir para satisfacer las necesidades requeridas para elproyecto.

Se define un calendario marcando las fechas en las que por lineamiento o por ser díafestivo aceptado por el cliente y el instituto no son fechas hábiles para impartir lacapacitación

Se obtiene la lista general de los cursos que se cubrirán en el programa y se ordenande acuerdo a la seriación de éstos. La seriación de los cursos se verifica en lascurrículas del tipo de empleado para el cual se genera el programa activo. Lageneración de grupos se realiza entonces curso por curso tomándolos en el ordendado por la seriación.

Para cada uno de los cursos que se programan se genera una lista del personal quesolicita el curso. Esta lista se ordena por centro de trabajo, categoría y antigüedadpara facilitar la aplicación de los lineamientos de escalafón establecidos y formargrupos para un curso.

Se definen las posibles fechas y planteles para cada curso. Para definir las posiblesfechas para cada grupo se toman en cuenta los periodos en los que se debe impartirel curso, la duración del curso, así como los posibles planteles para impartir el curso. Esaquí donde se toman en cuenta los lineamientos acerca de las fechas y los lugaresdonde se debe impartir la capacitación.

Para llevar a cabo la definición de fechas y planteles se procede de la siguientemanera:

Solución por procedimiento

4-19

Se definen las posibles fechas de para impartir el curso, tomando en cuenta loslineamientos acerca de las fechas en las que se debe impartir la capacitación,así como la frecuencia para impartir el curso. Factores que intervienen: Periodode programación, duración del curso, lineamientos, calendario de días hábiles.Las fechas propuestas incluyen una fecha de inicio y una fecha de finalizacióndel curso. Las fechas de inicio y fin de un curso se proponen tratando de que enel periodo comprendido entre éstas fechas haya el mínimo de interrupciones pordías inhábiles de acuerdo al calendario definido para el proyecto decapacitación, es decir, que un curso se realice en un periodo lo más consecutivoposible. Para definir el mínimo de interrupciones por fines de semana inhábiles seencuentra una relación entre la duración en días de un curso y el día de lasemana apto para que comience el curso. Esta relación indica si una fechapropuesta para el inicio de un curso es factible o no.

Se definen los planteles en los que se podría impartir el curso tomando en cuentalos lineamientos acerca de los planteles en donde se debe impartir lacapacitación. Factores que intervienen: Lista de fechas, instalaciones y equiposque se requieren para el curso, incluyendo precio por hora de utilización,periodos y horarios de disponibilidad y planteles.

A partir de la clave del curso se determinan los tipos de instalaciones necesariaspara su desarrollo. A partir de la clave de los recursos y del inventario de recursosdel campus se determina la lista de posibles planteles para impartir el curso.

Del inventario de instalaciones se determinan los planteles pertenecientes alcampus en que se genera el programa y se verifica si en cada una de ellosexisten instalaciones de todos los tipos requeridos para el curso y están disponiblesen alguna de las fechas propuestas. Con esta información se pueden definir losplanteles en los que se podría impartir el curso. Si llega a faltar una instalación sedescarta el plantel.

En caso de que no existan lineamientos, el criterio que se sigue para definir las fechasy planteles posibles es la disponibilidad de las instalaciones requeridas para el cursoen el campus para el cual se genera el programa.

Nótese que no se está hablando todavía de una asignación de recursos, solo se estánabriendo aquellas posibilidades de fechas y planteles que son factibles.

El realizar el análisis de disponibilidad de las instalaciones y equipos en este puntotiene las siguientes ventajas:

• Permite reducir el número de posibilidades para las fechas y planteles paraimpartir el curso

• Permite obtener una aproximación al costo por concepto de instalaciones,que tendrá cada grupo.

Con las fechas y los planteles en donde de puede impartir el curso se genera una listade grupos propuestos o posibles. Para esto se realiza un recorrido sobre la lista de

Solución por procedimiento

4-20

fechas propuestas para la impartir el curso. Cada elemento de la lista determina elperiodo en el que se impartirá el curso y se realiza un recorrido sobre la lista deposibles planteles. Del conjunto de instalaciones pertenecientes a cada plantel sedetermina si una de cada una de las instalaciones que se requieren para el cursotiene un periodo de disponibilidad que contenga al periodo de la fechas propuestasdel curso y cuyo horario de desocupación coincida con el cronograma del cursocorrespondiente a esa instalación. Al mismo tiempo se determina (acumulándose) elcosto de utilización de cada una de las instalaciones. El costo de una instalación seobtiene de su costo por hora por el número de horas que se utilizará para el grupo.Este proceso se realiza iterativamente con cada una de los posibles plantelesgenerando así propuestas de grupos para un curso con la siguiente información:Fecha de inicio del curso, fecha de finalización del curso, plantel o localidad en quese efectuará el curso y costo promedio por utilización de instalaciones. Los gruposdeben quedan ordenados ascendentemente por fecha de inicio

Para la generación de los grupos posibles sólo se consideran las instalacionesrequeridas para el curso puesto que dado que éstas no son móviles determinan ellugar en donde se imparte un curso. Los equipos requeridos para el desarrollo delcurso son móviles y aunque un plantel no contara con alguno podrían conseguirse deotros planteles, de proveedores, etc. por ello no determinan el lugar para impartir elcurso.

El siguiente paso del proceso es definir las asociaciones participante-curso/ fecha/plantel. Esto consiste en relacionar a cada uno de los solicitantes del curso con losgrupos propuestos. Basándose en la disponibilidad de los participantes se definen lasasociaciones participante-curso/fecha/plantel. La asociación entre participantes yfechas/planteles se muestra en la figura 4.7

0

Figura 4.7

Cada una de las asociaciones representa una posibilidad de asignación. Los nodosde la izquierda en la figura representan participantes y los nodos de la derecha soncurso/fecha/plantel (grupos propuestos). Un participante estará asociado con uncurso/fecha/plantel, si solicita el curso y su disponibilidad le permite tomar el curso enla fecha propuesta. De este modo se obtiene un grafo con dos grupos de vértices:

Solución por procedimiento

4-21

participantes y grupos posibles para impartir cada curso. Cada arista tiene asociadauna función de costo que se tomará como criterio para asignar al participantecorrespondiente al vértice del lado izquierdo al grupo con la fecha/plantelcorrespondiente al vértice del lado derecho.

El proceso que genera la relación entre los grupos y los participantes se efectúa de lasiguiente manera:

• Se recorre la lista de solicitantes del curso. Sobre este recorrido se analizan cadauno de los grupos propuestos. Esto es que para cada solicitud del curso serecorre toda la lista de grupos propuestos.

• Con cada una de las parejas solicitante - grupo se analiza si el solicitante estadisponible en el periodo comprendido entre la fecha de inicio del curso y lafecha de finalización del curso para establecer que el empleado puede asistir,posiblemente, al grupo específico. Como en muchos de los casos los recursoshumanos se tienen que desplazar de una localidad a otra para obtener lacapacitación, al verificar la disponibilidades de éstos en las fechas del grupopropuesto se toma en cuenta la disponibilidad desde un día antes del inicio delcurso y un día después de la fecha final de curso para tomar estos días demargen para la traslado en caso de que sea necesario.

• Al relacionar un empleado con un grupo se asocia un costo a la relación. Estevalor depende de los costos de transportación y viáticos de hospedaje en casode que sea necesario el desplazamiento del participante de una localidad aotra; el costo promedio del grupo y un costo ficticio por la fecha en la que seimparte el curso. De acuerdo a este costo de las asociaciones se determinapara un empleado cual es el grupo óptimo, de costo mínimo, al cual se deberáasignar para satisfacer su solicitud de capacitación.

El costo de las relaciones participantes - grupos propuestos se determina con lasiguiente función:

FAsocPart = f1 * (F-FIP) + f2 * (CC - CMinC) + f3 * (CViat - CViatMin)

(FFP - FIP) CMaxC - CMinC CViatMax - CViatMin

donde:

f1 = Factor de importancia de las fechas

f2 = Factor importancia de costo

f3 = Factor de importancia de viáticos

FIP = Fecha inicial del periodo de capacitación

FFP = Fecha final del periodo de capacitación

Solución por procedimiento

4-22

CMaxC = Costo promedio máximo de los grupos propuestos

CMinC = Costo promedio mínimo de los grupos propuestos

CViatMax = Costo de viáticos máximo registrado en las asociaciones

CViatMIn = Costo de viáticos mínimo registrado en las asociaciones

CC = Costo del grupo propuesto

F = Fecha de inicio del curso para el grupo propuesto

CViat = Costo de viáticos (transporte y hospedaje) asociados al desplazamientodel participante de su localidad de trabajo a la localidad de capacitación.

El parámetro de fechas se establece para permitir que los participantes seanasignados a los grupos con fechas cercanas al inicio del periodo de capacitación demanera que todos los cursos se distribuyan en el periodo y se pueda con ello cubrir elmáximo de solicitudes.

En la función los factores de importancia para cada uno de los parámetros sonconstantes definidas por el usuario que indican bajo que criterio se ordenan, deacuerdo al costo mínimo, las asociaciones para un participante. Por ejemplo, si elfactor de costo es mas importante que las fechas entonces la función tenderá aasociar a un participante al grupo más barato aun siendo en fechas últimas alperiodo de capacitación. Si el factor de fechas es más alto que el de costo lasasociaciones de un participante se ordenarán por fecha es decir, los grupos óptimosserán aquellos de fechas mínimas

Los factores de importancia de los parámetros deben manejarse en valores quetiendan a un equilibrio es decir, que se ahorre en lo posible dinero y tiempo. Porlograr un costo mínimo se puede incurrir en la no satisfacción de un gran número desolicitudes de capacitación (Factor de costos y viáticos alto) y por lograr satisfacertodas las solicitudes se pueden incurrir en costos muy altos, esto se podría presentar silas fechas son muy importantes y la función no permite esperar algunos díasrazonables para enviar a curso más económico a un empleado.

La función de las asignaciones de los participantes tiene un comportamientosemejante al que se muestra en la figura 4.8

FIP = 34350 (01/01/94 formato juliano)

FFP = 34500 (30/06/94 formato juliano)

CMaxCurs = 20000

CMinCurs = 8000

CMaxViat = 1000

Solución por procedimiento

4-23

CMinViat = 10

f1 = 34

f2 = 33

f3 = 33

0

Figura 4.8

Es importante hacer notar que esta función produce un valor numérico que no indicael costo real de que el participante asista al grupo asociado, sino un valor que sirvecomo criterio para realizar las asignaciones mediante la cuantificación de todos losfactores que influyen en las asignaciones. El estado que se asigna al momento decrear la asociación es el de "libre".

Generación de grupos

Nótese que en el grafo resultante de las asociaciones, un participante está asociadocon varios curso/fecha/plantel, es decir, que el participante puede ser asignado acualquier grupo en las fechas y planteles asociadas. En el momento en que unparticipante sea asignado a un grupo, las asociaciones que ese participante tengacon fechas/planteles que pertenezcan al mismo curso deberán descartarse, ademásdeben actualizarse sus periodos de disponibilidad para evitar el riesgo de asignarlo amás de un grupo simultáneamente, y en su caso, actualizar los periodos dedisponibilidad de los participantes de su mismo centro de trabajo que sean de menorcategoría o antigüedad, para evitar que sean asignados a grupos con fechasanteriores. De esta manera se forman los grupos reales. Para cada uno de losparticipantes se elige el grupo de costo mínimo, de acuerdo a la función, y se inscribe

Solución por procedimiento

4-24

en él eliminando los demás asociaciones, de modo que al final el grafo tendrá paracada participante una sola arista que lo une con un grupo propuesto y de estamanera se identifican los grupos para un curso y los empleados inscritos es cadagrupo.

el algoritmo debe indica el orden en el que se deben realizar las asignaciones. esteorden está afectado principalmente por las restricciones impuestas por la cláusula 185del cct de la organización cliente, a saber, la categoría y antigüedad de losparticipantes, y la seriación de los cursos. aún cuando el objetivo del modelo esgenerar grupos a un costo mínimo, estas restricciones impiden que se pueda obtenerun costo aún menor.

Los grupos se generan conforme se toma la decisión de cuál es la fecha/plantel paraque cada participante tome los cursos que solicita. La decisión esta basadafundamentalmente en las funciones de costo asociadas a las aristas que conectan alos participantes con los cursos/fechas/planteles, ya que en todo momento se tomalas de menor costo.

Si consideramos solo las aristas del grafo, el proceso anterior equivale a un recorridodel conjunto de las aristas. Las aristas contienen un estado que indica el estado de larelación del participante con el grupo propuesto en cualquier momento del recorrido.Los estados de la relación son:

• "libre". Es el estado original e indica que durante el recorrido no se ha realizadoninguna operación con el participante asociado. El recorrido solo se realizasobre las relaciones cuyo estado es libre.

• "cancelada". Es el estado que indica que la asociación no deberá ser tomadaen cuenta debido a dos posibles razones: que el participante ya fue asignadodefinitivamente a otro grupo o que el grupo no será abierto. En este caso lo quese hace es borrar definitivamente las asociaciones.

• "afectada". Indica que un participante de mayor categoría y/o antigüedad queel actual en el recorrido no permite que éste sea asignado al grupo con la aristaafectada.

• "provisional". Indica que el participante esta asignado provisionalmente algrupo. El estado provisional se mantiene hasta que el grupo sea definitivo.

• "inhibida". Indica que un participante ya está asignado provisionalmente a ungrupo.

Cada operación de asignación/desasignación provoca el cambio de estado endiversas relaciones que tienen que ver con el participante. En ningún momento seelimina una relación debido a que podría llegar a utilizarse para asignacionesposteriores excepto cuando los grupos ya son definitivos es decir que el grupo ya esun grupo real que conforma el programa de capacitación.

Solución por procedimiento

4-25

Además de las relaciones de grupos con participante se tienen un arreglo cuyoscomponentes son las cantidades de participantes del cliente por cada día delperiodo de capacitación y una matriz donde los renglones representan un centro detrabajo y las columnas representan los días del periodo. Una entrada de la matrizrepresenta la cantidad de participantes del centro de trabajo que se encuentretomando capacitación el día señalado. Estos arreglos se utilizan para evitar que seexceda el número de participantes que pueden tomar capacitaciónsimultáneamente, tanto de un centro de trabajo como del cliente en su conjunto enun día determinado. En estos arreglos cada operación de asignación/desasignaciónprovoca un aumento o disminución de sus valores. Además para cada asignación sedebe tomar en cuenta los valores del arreglo junto con los porcentajes definidos porel usuario para el control de estos lineamientos.

El proceso de las asignaciones de los participantes a los grupos se describe acontinuación.

Se realiza un recorrido secuencial sobre la lista de asociaciones para asignar losparticipantes a los grupos. Para cada participante que tenga al menos una de susasociaciones con el estado "libre" se elige la de menor costo verificando que secumplan las restricciones de número de participantes por centro de trabajo y por eltotal del campus. En caso de que el grupo de esta asociación tenga un número departicipantes menor que el cupo mínimo, a la asociación se le pone el estado de"provisional", en caso contrario, el participante se inscribe definitivamente en el grupoy se actualiza su periodo de indisponibilidad. Todas las otras asociaciones delparticipante con otros grupos cambian su estado a "inhabilitada" o se borran si seinscribe definitivamente. Asimismo se afectan o borran las asociaciones de losparticipantes del mismo centro de trabajo que tengan asociaciones comunes engrupos con fechas previas. Se incrementa el número de participantes candidatoshasta el momento al grupo, así como el incremento de participantes del campus ydel centro de trabajo correspondiente.

Cuando un grupo llega al mínimo de participantes inscritos provisionalmente seintenta asignar recursos al grupo, se asignan instructor, instalaciones y equipos. Si selogran asignar los recursos para el curso entonces se inscriben realmente a todos losparticipantes asignados a éste provisionalmente y se actualizan los periodos deindisponibilidad del personal, los instructores, las instalaciones y los equipos de maneradefinitiva.

En caso de no poder asignar instalaciones, se desasocian los participantes liberandosus asociaciones a otros grupos. El grupo al cual no se consiguió asignar recursos seelimina de la lista de grupos propuestos y se eliminan todas las asociaciones de todoslos solicitantes al grupo para evitar considerarlo nuevamente. Se actualizan loscontadores de participantes a nivel campus y centro de trabajo.

En caso de que el grupo haya completado el cupo máximo se cierra el grupo encuestión y se verifica si se puede abrir uno nuevo en las mismas condicionespropuestas (fecha, plantel) para tomarlo como otro grupo. Las condiciones para abrirotro grupo lo indica la disponibilidad de las instalaciones en el plantel. Si ya no existen

Solución por procedimiento

4-26

instalaciones en el plantel para abrir un nuevo grupo entonces éste se elimina de lalista de grupos propuestos y de las asociaciones de participantes.

Si existe un remanente muy grande al terminar un primer recorrido sobre la lista departicipantes se intentan formar grupos utilizando el mismo procesos descrito hastaaquí. Si el remanente es pequeño entonces se intentan llenar los grupos que tenganmayor número de participantes provisionales hasta que todos los participantesqueden inscritos o ya no tengan ninguna posibilidad de inscripción.

Asignación de recursos

La asignación de recursos a los grupos incluye la asignación de instalaciones, equipose instructor a un grupo. Las instalaciones son altamente determinantes para lapermanencia de un grupo. Si un grupo no tiene instalaciones entonces no debe existirpuesto que no tiene un lugar físico para la capacitación. Los equipos y los instructoresse pueden mover y transferir con facilidad por ello un grupo puede dejarse sin estosrecursos y conseguirse posteriormente con el mercadeo con los otros campus.

La asignación de recursos también esta sujeta lineamientos que indicanprincipalmente la fuente de la que se obtendrán (recursos propios, cliente e instituto,o recursos de proveedor). Se recuerda aquí que para la asignación de recursos deproveedor se deben tomar paquetes completos de los que éstos ofrecen para uncurso incluyendo forzosamente la instrucción. Esto se facilita de cierta manera porquela asignación de recursos se divide en dos módulos: asignación de recursos propios(propiedad del instituto o del cliente) y asignación de recursos de proveedor.

Los equipos e instalaciones propios se asignan a los grupos tomándolas del inventariode éstos del cliente y del instituto. Con la clave del curso se verifica el tipo deinstalaciones y equipos que requiere y las horas de capacitación en las que sesolicitan de acuerdo a su cronograma. Del inventario de equipos e instalaciones delplantel propuesto para el grupo se identifica la disponibilidad de los recursos y seasignan al grupo. Si falta alguna instalación requerida (no hay disponibles en elperiodo solicitado) entonces la asignación de recursos se declara no aceptada.

La asignación de proveedores toma en cuenta los diferentes paquetes decapacitación que proporcionan los proveedores y se elige a aquel que de unaopción optima de acuerdo a criterios de calidad, costo de los recurso y lacapacitación y además que cubra en su mayoría las necesidades materiales delcurso.

La asignación de instructores se realiza de manera semejante a la asignación departicipantes. Se crea una lista de todos los instructores posibles para un curso y se leasocia un costo de asignación por medio de una función que cuantifica el costo y lacalidad del instructor. A continuación se presenta un grafo que representa laasociación entre instructores. La asociación entre instructores y curso/ fecha/ plantelestá basada en la disponibilidad de los instructores se muestra en la figura 4.9

Solución por procedimiento

4-27

0

Figura 4.9

Como se puede observar el esquema del grafo es muy similar al de los participantes.Cada una de las asociaciones representa una posibilidad de asignación. Los nodosde la izquierda en la figura representan instructores y los nodos de la derecha soncurso/fecha/plantel. Un instructor estará asociado con un curso/fecha/plantel, sipuede impartir el curso y su disponibilidad le permite impartirlo en la fecha propuesta.Basándose en la localidad de residencia del instructor, en la duración del curso, elcosto y los posibles planteles para impartir el curso se establece una función de costopara cada asociación. Esta función también considera el índice de calidad para laselección de un instructor. Cada arista entre el grupo de nodos de instructores y decurso/fecha/plantel tiene asociada una función de costo para impartir el curso por elinstructor en la fecha/plantel asociada. La función de costo está definida como:

Cálculo del costo de instructores

Costo=x*(Ccur + Cvt + Cvh*Duración)/Cmax+ (1-x)I

donde

I es el índice de calidad del instructor (entre 1 y 10),

Ccur es el costo que el instructor cobra por impartir el curso

Cvt es el costo de viáticos de transportación

Cvh es el costo de viáticos de hospedaje del instructor para impartir el curso fuerade su localidad y Duración es la duración del curso.

Cmax es el costo máximo por concepto de instructor registrado para el curso.

La función con los siguientes valores constantes : Cvt=150, Cvh=15, Duracion=3,Cmax=100 y x=0.2; tiene el comportamiento mostrado en la figura 4.10

Solución por procedimiento

4-28

0

Figura 4.10

La calidad de la capacitación que proporciona el proveedor se mide de la mismamanera que la asignación de instructores a los grupos.

Esta es la descripción general del proceso de la programación automática de cursos.

En el apéndice B se encuentran los algoritmos de la mayor parte del proceso y en elapéndice C se encuentra el diccionario de datos del mismo.

A-1

AAAParámetros del modelo de programación de cursos.

La programación de los cursos es afectada por diferentes lineamientos y factores queindican valores o criterios determinantes del orden y la forma en que se realiza lageneración de los grupos para un programa de capacitación. Algunos factores olineamientos pueden ser controlados por el usuario y para permitir flexibilidad almodelo se han creado variables que cuantifiquen o indiquen la manera en que éstosafectan las generación de los grupos. Estos parámetros indican porcentajes, valores ydatos bajo los cuales se debe regir la programación de los cursos. A continuación sedescriben los parámetros utilizados en la programación, su descripción y los valoresque generalmente se mantienen o que en algunos casos son óptimos para lasatisfacción de los objetivos del modelo.

AsigEq. Valor por omisión: SI. Este parámetro sirve para decidir si se desintegra ungrupo en caso de que la asignación de equipos haya fracasado. Este parámetroindica que decisión tomar para desintegrar un grupo y acomodar nuevamente a losparticipantes a otros grupos cuando la asignación de equipos no se pudo realizar demanera adecuada. Si el grupo se deja sin equipos se podrían asignar posteriormentede manera manual sin embargo si los equipos no determinan la existencia de ungrupo podrían al final quedar tantos grupos abiertos sin equipos que no se puedacubrir sus requerimientos posteriormente.

AsigInstal. Valor por omisión: SI. En la generación automática de grupos se puede darel caso de que para un grupo propuesto no haya las instalaciones necesarias paraimpartir un curso. Este parámetros sirve para decidir si un grupo se deshace o nocuando la asignación de instalaciones necesarias para el curso no se realizósatisfactoriamente.

AsigInstr. Valor por omisión: NO. La asignación de instructores puede fallar cuando noexiste disponibilidad de los instructores posibles para impartir el curso. Si en grupo sequeda sin instructor se debe tomar la decisión de deshacer al grupo y reintegrar a losparticipantes a otros grupos o dejar el grupo sin instructor y asignarlo posteriormentede manera manual. El valor de este parámetro indica si se desintegra o no un grupodada la falta de instructor. Los instructores que se toman para impartir el curso sonsolo aquellos ubicados dentro del campus en el que se realiza la programación en elmomento actual. Si los grupos se dejan sin instructor posteriormente se podría asignaralguno de otro campus o un proveedor.

ApéndiceParámetros del sistema

Apéndice A. Parámetros del sistema

A-2

AsigTipoEmp . Valor por omisión: SINDICALIZADOS Y CONFIANZA. Este parámetro indicaque tipo de empleado será el que se tome para la generación automática de gruposes decir, el parámetro indica si se programará solo el personal sindicalizado, elpersonal de confianza o ambos. Aunque se programe a los dos tipos de empleado demanera simultánea, la generación automática de grupos realiza las programacionespor separado, es decir forma grupos de personal sindicalizado y grupos de personalde confianza por separado.

CantProgRem. Valor por omisión: 2. Cantidad de veces que debe intentarseprogramar nuevamente las solicitudes con el modelo de costo mínimo para llegar alporcentaje de remanente permitido. Este parámetro indica cuantas veces seintentará satisfacer las solicitudes de un curso por medio del modelo de costo mínimode manera que se intente alcanzar el porcentaje máximo de solicitudes noprogramadas sin que la programación automática entre en un ciclo infinito porlograrlo. Si no se alcanza el porcentaje de remanente permitido dadas las veces deprogramación entonces se tratará de satisfacer las solicitudes por otro método en queno se considera de manera estricta el costo mínimo sino más bien la satisfacción delas solicitudes. Valores muy grandes asignados al parámetro hará que se eleve eltiempo de ejecución de la programación automática. Valores muy pequeños haráque se eleven los costos del programa de capacitación generado, aunque con elmayor número de solicitudes programadas.

CoberturaReq. indica la cobertura a la cual se aplicara el proyecto. Sus valores son: 1)Localidad, 2)Estado federativo y 3) Campus

DiasTraslado. Valor por omisión: 1. Días necesarios de disponibilidad de unparticipante antes de un curso necesarios para su el traslado de su localidad deorigen a la localidad en la que se efectuará el curso. Para asignar un empleado a ungrupo se requiere que éste tenga disponibilidad de tiempo en el periodocomprendido entre la fecha en que se inicia el curso y la fecha en que termina éste.Sin embargo dado que muchas veces el participante a un curso tendrá quemovilizarse de su localidad de trabajo a otras localidades requiere además tiempopara transportarse. El parámetro DiasTraslado indica cuantos días se requieren parael traslado de los participantes e instructores de su localidad de origen a la localidaddonde se impartirá el curso al que asistirán. Este parámetro también se considera enla asignación de instructores.

FactorCInsta. Factor de importancia de los costos de las instalaciones. Este factorindica en que porcentaje se requiere que el costo de las instalaciones elegidas paraun grupo sea de costo mínimo.

FactorCInstr. Factor de importancia de los costos de los instructores. Este factor indicaen que porcentaje se requiere que el costo del instructor elegido para impartir uncurso en un grupo dado sea de costo mínimo.

FactorEquipo. Factor de importancia que tiene el hechi de que un grupo tengaequipos

Apéndice A. Parámetros del sistema

A-3

FactorInstal. Factor de importancia que tiene el hecho de que un grupo tengainstalaciones

FactorInstr. Factor de importancia que tiene el hecho de que un grupo tengainstructor

FCostoTransp. Factor de importancia de los costos de transportación. Este factorindica en que porcentaje se requiere que el costo de transporte de una localidad aotra sea de costo mínimo.

FteCapRecMat. (fuente de recursos materiales para la capacitación)Valor poromisión: 1. Los valores que adquiere este parámetro son los siguientes: 1. Indica quelos recursos que se asignen a los grupos se tomarán solo de los recursos del cliente ydel instituto. 2. Indica que los recursos que se asignen a los grupos pueden ser delcliente, del instituto o de proveedor, dando siempre prioridad a los recursos del clienteo del instituto. 3. Indica que los recursos que se asignen a los grupos seránexclusivamente de proveedor. 4. indica que los recursos que se asignen a los grupospueden ser del cliente, del instituto o de proveedor dando prioridad a la asignaciónde recursos de proveedor.

MenorCatAnt. Valor por omisión: NO. Las solicitudes para un curso se programan demanera secuencial tomando un orden por centro de trabajo, categoría yantigüedad, si un empleado de mayor categoría y antigüedad no puede asistir en lasprimeras fechas del periodo de capacitación entonces dentro de su centro detrabajo restringirá estas fechas a los demás empleados de menor categoría yantigüedad que él y que soliciten el mismo curso. Estas restricciones traen comoconsecuencia que no se satisfaga el mayor número de solicitudes para un cursodada las limitaciones del periodo de capacitación que se propician. Si se da valorNO al parámetro las asignaciones de empleados a grupos tendrán más libertad ycomo consecuencia se obtendrá un programa más satisfactorio.

PtjeCobLinCl. Valor por omisión: 80. Porcentaje de días en los que, debe cumplirse,estrictamente, que no se exceda el porcentaje de personal en capacitaciónsimultánea para el cliente. Porcentaje de días dentro de un periodo en que debecumplirse estrictamente que la cantidad de empleados que se encuentran encapacitación en tiempo simultáneo, del total de empleados del cliente no exceda alporcentaje indicado. Cada que se realice la asignación de un empleado a un grupopara un curso, se verifica que para todos los días que el curso durará no se exceda elporcentaje de personal en capacitación permitido, sin embargo podría darse el casode que en algunos de los días del periodo del curso se excedan los porcentajes, porello el valor de PtjeCobLinCl se toma para dar un poco de flexibilidad y asignar alempleado al grupo aun cuando se exceden los porcentajes en un día o másdependiendo del valor dado a este parámetro. Valores más grandes al propuestopodrían ocasionar que no se satisfaga en su totalidad la demanda de capacitación.Valores más pequeños darán como consecuencia que el porcentaje de empleadosen capacitación simultánea para un centro de trabajo se exceda en la mayor partedel tiempo.

Apéndice A. Parámetros del sistema

A-4

PtjeCobLinCT. Valor por omisión: 80. Porcentaje de días en los que debe cumplirse,estrictamente, que no se exceda el porcentaje de personal en capacitaciónsimultánea para un centro de trabajo. Cada que se realiza la asignación de unempleado a un grupo para un curso, se verifica que para todos los días que el cursodurará no se exceda el porcentaje de personal en capacitación permitido para sucentro de trabajo, sin embargo podría darse el caso de que en algunos de los díasdel periodo del curso se excedan los porcentajes, por ello el valor de PtjeCobLinCT setoma para dar un poco de flexibilidad y asignar al empleado al grupo aun cuando seexceden los porcentajes en un día o más dependiendo del valor dado a esteparámetro. Valores más grandes al propuesto podrían ocasionar que no se satisfagaen su totalidad la demanda de capacitación. Valores más pequeños dan comoconsecuencia que el porcentaje de empleados en capacitación simultánea para uncentro de trabajo se exceda en la mayor parte del tiempo y se pierda el control deeste lineamiento.

PtjeComision. Valor por omisión: 40. Porcentaje de comisión adicional que se paga alos instructores sobre su sueldo por la participación en la impartición de un curso.

PtjeExcDiaCl. Valor por omisión: 10. Porcentaje de participantes permitidos en excesopor día para el total del cliente. Dado que se permite que se exceda el porcentaje depersonal en capacitación para el total del cliente, se debe poner un límite para queno se pierda el control del porcentaje. El parámetro PtjeExcDiaCT pone un límite alexceso permitido al porcentaje.

PtjeExcDiaCT. Valor por omisión.: 10. Porcentaje de participantes permitidos enexceso por día en cada centro de trabajo. Dado que se permite que se exceda elporcentaje de personal en capacitación para un centro de trabajo, se debe ponerun límite para que no se pierda el control del porcentaje. El parámetro PtjeExcDiaCTpone un límite al exceso permitido al porcentaje.

PtjeMinCur. Valor por omisión: 10. Porcentaje de participantes por debajo del mínimoque se permiten para que un grupo permanezca. En la generación automática degrupos puede darse el caso de que un grupo no cubra con el mínimo departicipantes asignados, sin embargo el grupo se puede dejar con los participantesque se tienen para que después se llene manualmente. Para que los grupos no sedejen vacíos y tenga un número de inscritos aceptable, se tiene este parámetro queindica cuantos participantes inscritos por debajo del mínimo se aceptan para que elgrupo permanezca.

PtjePartCl Valor por omisión: 80. Porcentaje de empleados del total del cliente quepueden tomar capacitación simultáneamente. Este porcentaje se utiliza para sabercuanta gente del total del cliente puede estar en capacitación al mismo tiempo. Estoes que en un día, solo el porcentaje indicado de personal, como máximo, puedeestar tomando capacitación y el resto estar en sus actividades normales de trabajo. Sise da un valor 100 al porcentaje se indica que todo el personal del cliente puedeasistir a capacitación en un mismo día. Los valores pequeños para el porcentajepuede traer como consecuencia que no se cubran en su totalidad las necesidadesde capacitación del personal.

Apéndice A. Parámetros del sistema

A-5

PtjePartCT. Valor por omisión: 80. Porcentaje de empleados de un centro de trabajoque pueden tomar capacitación simultáneamente. Este porcentaje se utiliza parasaber cuanta gente de un centro de trabajo puede estar en capacitación al mismotiempo. Si se da un valor 100 al porcentaje se indica que todo el personal de uncentro de trabajo puede asistir a capacitación en un mismo día. Los valorespequeños para el porcentaje puede traer como consecuencia que no se cubran ensu totalidad las necesidades de capacitación del personal.

PtjeIndicCal. Porcentaje de importancia de la calidad de un instructor en el momentode la asignación a un grupo. El porcentaje de costo será 100 - PtjeImpCalid y expresala importancia que se da al costo mínimo en el momento de asignar un instructor a ungrupo

PtjeRemPart. Valor por omisión: 10. La programación de los cursos se realiza demanera secuencial sobre una lista de empleados que solicitan un curso, cuando seha intentado programar a todos los solicitantes por lo menos una vez pueden quedarempleados sin asignar a un grupo, el remanente puede ser muy grande de maneraque lo más conveniente sea intentar nuevamente la programación aplicando todo elmodelo de costo mínimo, o puede ser muy pequeño de manera que lo importantesea programar y satisfacer las solicitudes aun que no sea considerando estrictamenteel costo mínimo. El porcentaje dado para este parámetro indica el número desolicitudes sin programar para un curso que deben existir para tomar una decisiónque conlleve a la programación del mayor número de las solicitudes. Valores muypequeños asignados al parámetro tendrán como consecuencia que laprogramación automática eleve su tiempo de ejecución. Valores muy grandes haráque se eleven los costos del programa de capacitación generado, aunque con elmayor número de solicitudes programadas.

SustituirRec. Valor por omisión: SI. Cuando los recurso para un curso pueden serasignados de proveedor o del cliente y del instituto siempre se da prioridad a uno deellos. Sin embargo existe la posibilidad de encontrar una mejor opción aunque no seade la fuente de mayor prioridad en el momento. En este caso puede existir la opciónde sustituir la opción primaria por la otra de menor prioridad pero más óptima (enfunción de la calidad y costo) el parámetro indica si esto es valido o no. Cuando sepermite la asignación de recursos del proveedor, del cliente y del instituto dandoprioridad a los recursos del proveedor se eligen los recursos del proveedor y se buscauna segunda opción con recursos del cliente y del instituto, si la segunda opción esmejor y SustituirRec tiene el valor SI entonces se permite la sustitución, en casocontrario solo se busca la primera opción de recursos.

-1-

BBBNOTAS: Procesos que se deben realizar antes de la programación de cursos utiliza el resultado de las vistas que a continuación se mencionan:

### Crear la vista de cursos ordenados por seriación para todas las currículas. Para generar la vista VistaCurOrdSeriac se utilizarán las tablas de Cursos, Currículas del personal de confianza/ Prerrequisitos del curso, Currículas de personal sindicalizado/ Prerrequisitos de curso, Tronco básico del personal de confianza/ Prerrequisitos del curso y Tronco básico del personal sindicalizado/ Prerrequisitos del curso.

### Crear vista de solicitudes de curso que indique el código del curso, clave del solicitante. Para la vista VistaSolicitudesCurso se requieren las tablas de Solicitudes recursos humanos, Solicitudes de capacitación y cursos.

### Crear vista de requerimientos curso que indique el código del curso, clave del solicitante. Para la vista VistaRequrimientosCurso se requieren las tablas de CursosCubrenRequerimientosRH, Cursos que cubren requerimientos y cursos.

### Crear las tablas PartDiaCliente y PartDiaCentroTrabajo que contienen la cantidad de personal en capacitación por dia y la cantidad de personal en capacitación por centro de trabajo y dia, respectivamente. Las tablas tienen la siguiente estructura:

PartDiaCliente DiaJuliano. Fecha en formato juliano CantPart. Cantidad de personal en capacitación en la fecha dada.

PartDiaCentroTrabajo DiaJuliano. Fecha en formato juliano CantPart. Cantidad de personal en capacitación en una fecha y un centro de trabajo. CveCT. Clave del centro de trabajo.

### Crear una vista que relacione a los campus con los centros de trabajo. Dentro del programa de programación de cursos se debe monitoriar cuando se ha abortado el programa para que en este momento en cualquier parte del

programa que se haya detectado cancelar la ejecución de éste y restablecer todo como si no se hubiera iniciado. Todas las fechas involucradas en el programa se manejaran en formato juliano

La lista ligada GruposPosibles tiene la siguiente estructura:GruposPosibles

Clave. Clave del grupo propuesto. FechaIni. Fecha de inicio del grupo propuesto. FechaFin. Fecha de terminación del curso para el grupo propuesto. CvePlantel. Clave del pantel en el que se propuso el grupo. CantPart. Cantidad de participantes asignados al grupo propuesto. CostoEstim. Costo estimado por uso de instalaciones. Liga. Apuntador al siguiente grupo posible

Apéndicepseudocódigo

-2-

La tabla tiene la siguiente estructura:AsocParticipantes:

CveEmp.Clave del participante ClaveGrupoPosible. Clave del grupo propuesto Costo. Costo de la signación Status. Estado de la asignación****************************************************************************************************************************************/

-3-

/*****************************************************************************************************************************************************Módulo iniciador de la generación automática de gruposFecha de actualización: 10/03/94*****************************************************************************************************************************************************/PROC ProgramacionCursos(Proyecto,Campus)COMIENZA EdoProyecto := ObtenPeriodoProyecto(Proyecto,PeriodoProyecto) SI EdoProyecto = 1 ENTONCES /* El status del proyecto indica que es aceptado */ COMIENZA ObtenListaParametros(Proyecto,Campus,GLBListaParametros) ObtenCalendario(PeriodoProyecto) CadTipoEmpleado := Parametro('AsigTipoEmp') SI SeEncuentra("SINDICALIZADOS",CadTipoEmpleado) ENTONCES /* La función se encuentra debe ser reemplazada por la función de C que busca la ocurrencuia de una cadena en otra */ ProgramaCursosParaTipoEmp(Proyecto,Campus,SINDICALIZADO,PeriodoProyecto) SI SeEncuentra("CONFIANZA",CadTipoEmpleado) ENTONCES ProgramaCursosParaTipoEmp(Proyecto,Campus,CONFIANZA,PeriodoProyecto) TERMINATERMINA

/*****************************************************************************************************************************************************Función: Obtener la fecha de inicio y la fecha de finalización del proyecto que se esta programando

Las fechas al ser leidas se obtienen directamente en formato julianoFecha de actualización: 09/03/94

*****************************************************************************************************************************************************/FUNCION ObtenPeriodoProyecto(Proyecto, VAR PeriodoProyecto)COMIENZA SELECT FechaInicial, FechaFinal, Estado INTO PeridoProyecto.FechaIni, PeridoProyecto.FechaFin , Estado FROM ProyCapacit WHERE Clave = Proyecto

PeriodoProyecto.DiaSemIni := DiaSemana(PeriodoProyecto.FechaIni) /* Llamada a la función de informix que da el dia de la semana correspondiente a una fecha */ ObtenPeriodoProyecto := EstadoTERMINA

-4-

/*****************************************************************************************************************************************************Función: Obtener el calendario para el periodo del proyecto de capacitación que se esta programando actualmente.

La tabla de dias festivos tiene los dias en que no se debe dar capacitación, éstos incluyen sábados y domingos siempre y cuando el usuario configure el clendario. Por default sábados y domingos son dias hábiles. Calendario es un arreglo dinamico de bytes, donde cadabit es un diadentro del periodo del proyecto y su estado, 0 ó 1, indica dia inhabil o hábil respectivamente.

Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC ObtenCalendario(PeriodoProyecto)COMIENZA Calendario.Tamaño := (PeriodoProyecto.FechaFin - PeriodoProyecto.FechaIni)+ 1 /* Se suma el 1 por que el dia de inicio del periodo también se cuenta */ Calendario.Arreglo := SolicitaMemoria(Calendario.Tamaño) /* Solicitacion de la memoria para el arreglo del calendario */ InicializaCalendario()

DECLARE FechasInhabiles CURSOR FOR SELECT Fecha FROM DiasFestivos WHERE Fecha BETWEEN PeriodoProyecto.FechaIni AND PeriodoProyecto.FechaFin

OPEN FechasInhabiles FETCH FechasInhabiles INTO Fecha /* Fecha es un entero puesto que es una fecha en formato juliano */ MIENTRAS sqlca.sqlcode = 0 HAZ COMIENZA Calendario.Arreglo[Fecha - PeriodoProyecto.FechaIni] = DIAINHABIL FETCH FechasInhabiles INTO Fecha TERMINA CLOSE FechasInhabilesTERMINA

/*****************************************************************************************************************************************************Función: Programación de cursos para un tipo de empleado específico.Fecha de actualización: 10/03/94

*****************************************************************************************************************************************************/PROC ProgramaCursosParaTipoEmp(Proyecto,Campus,Tipo,PeriodoProyecto)COMIENZA ObtenNumCursosxPart(GLBPartNumCursos,Campus,Proyecto,Tipo) SeleccionaCursos(Tipo,Proyecto,Campus,ListaCursos) /* Genera una lista ligada con mínimo y máximo de participantes */ OrdenaCursos(NULL,ListaCursos,Tipo) /* Ordena la lista de acuerdo a la vista de cursos VistaCursosOrdSeriac */ InvierteListaCursos(NULL,ListaCursos,ListaCursos) /* El procedimiento OrdenaCursos deja la lista invertida, por lo que se requiere se invierta para que realmente quede en orden de seriación */ ProgramaCursoxCurso(Tipo,ListaCursos,Proyecto,Campus,PeriodoProyecto) Libera(ListaCursos)TERMINA

-5-

/*****************************************************************************************************************************************************Función: Obtener una tabla con las claves de los empleados que solicitan cursos y el número de cursos que solicita cada uno dentro del campus y el

proyecto que se está programando en actulamente. El número de cursos que se contabilizan solo son aquellos cuyo estado es de aceptado.Fecha de actualización: 17/03/94

*****************************************************************************************************************************************************/PROC ObtenNumCursosxPart(PartNumCursos,Campus,Proyecto,TipoEmpleado)COMIENZA DECLARE CursorSolicitantes CURSOR FOR (SELECT CveRH, COUNT(*) FROM SoliRH WHERE CveSoli IN (SELECT Clave FROM SoliCapacit WHERE CveProyCapacit = Proyecto AND CveCampus = Campus) AND CveEstAnalis = ACEPTADO AND (CveEstPrerr = 2 OR CveEstPrerr = 3) AND CveRH IN (SELECT Clave FROM RecHumanos WHERE CvePuesto IN (SELECT Clave FROM Puestos WHERE TipoPersonal = TipoEmpleado) ) ) UNION (SELECT SoliRHPrerr.CveRH, COUNT(*) FROM SoliRHPrerr, SoliRH WHERE SoliRHPrerr.CveSoli = SoliRH.CveSoli AND SoliRHPrerr.CveRH = SoliRH.CveRH AND SoliRH.CveEstAnalis = 2 AND (SoliRH.CveEstPrerr = 1 OR SoliRH.CveEstPrerr = 3) AND SoliRHPrerr.Estatus = 3 SoliRHPrerr.CveSoli IN (SELECT Clave FROM SoliCapacit WHERE CveCampus = Campus AND CveProyCapacit = Proyecto) AND SoliRHPrerr.CveRH IN (SELECT Clave FROM RecHumanos WHERE CvePuesto IN (SELECT Clave FROM Puestos WHERE TipPersonal = TipoEmpleado) ) ) UNION (SELECT CveRH, COUNT(*) FROM ReqCursosRH WHERE CveEstAnalis = 'ACEPTADO' AND (CveEstPrerr = 2 OR CveEstPrerr = 3) AND CveRH IN (SELECT Clave FROM RecHumanos WHERE CveCentroTrab IN (SELECT Clave FROM CentrosTrab WHERE CveLocalidad IN (SELECT Clave FROM Localidades WHERE CveEstFederativo IN (SELECT Clave FROM EstFederativos WHERE CveCampus = Campus) )

-6-

) AND CvePuesto IN (SELECT Clave FROM Puestos WHERE TipPersonal = TipoEmpleado) ) AND CveRequerimiento IN (SELECT Clave FROM Requerimientos WHERE CveProyecto = Proyecto) ) UNION (SELECT ReqCursosRHPrerr.CveRH, COUNT(*) FROM ReqCursosRHPrerr, ReqCursosRH WHERE ReqCursosRHPrerr.CveRequerimiento = ReqCursosRH.CveRequerimiento AND ReqCursosRHPrerr.CveRH = ReqCursosRH.CveRH AND ReqCursosRH.CveEstAnalis = 2 AND (ReqCursosRH.CveEstPrerr = 1 OR ReqCursosRH.CveEstPrerr = 3) AND ReqCursosRHPrerr.Estatus = 3 ReqCursosRHPrerr.CveRequerimiento IN (SELECT Clave FROM Requerimientos WHERE CveProyecto = Proyecto) AND ReqCursosRHPrerr.CveRH IN (SELECT Clave FROM RecHumanos WHERE CveCentroTrab IN (SELECT Clave FROM CentrosTrab WHERE CveLocalidad IN (SELECT Clave FROM Localidades WHERE CveEstFederativo IN (SELECT Clave FROM EstFederativos WHERE CveCampus = Campus) ) ) AND CvePuesto IN (SELECT Clave FROM Puestos WHERE TipPersonal = TipoEmpleado) ) ) GROUP BY CveRH

OPEN CursorSolicitantes FETCH CursorSolicitantes INTO RegPartNumCurs

MIENTRAS (sqlca.sqlcode = 0 ) HAZ COMIENZA Inserta(RegPartNumCurs.CveEmpleado,RegPartNumCurs.NumCursos,PartNumCursos) /* Inserta en tabla de hash */ FETCH CursorSolicitantes INTO RegPartNumCurs TERMINA

CLOSE CursorSolicitantesTERMINA

-7-

/*****************************************************************************************************************************************************Función: Crear la lista de cursos que se programarán de acuerdo a las solicitudes y requerimientos de capacitación para un proyecto.Fecha de actualización: 09/03/94 NOTA: Considerar los cursos solicitados por prerrequisitos

*****************************************************************************************************************************************************/PROC SeleccionaCursos(Tipo,Proyecto,Campus,ListaCursos)COMIENZA DECLARE CursorCursos CURSOR FOR SELECT Codigo, Duracion, NumMinPart, NumMaxPart FROM Cursos WHERE (Codigo IN (SELECT CodCurso FROM SoliCapacit WHERE CveProyCapacit = Proyecto AND CveCampus = Campus AND Clave IN (SELECT CveSoli FROM SoliRH WHERE CveRH IN (SELECT Clave FROM RecHumanos WHERE CvePuestos IN (SELECT Clave FROM Puestos WHERE TipoEmp = Tipo ) ) AND CveEstAnalis = 'ACEPTADO' AND (CveEstPrerr = 2 OR CveEstPrerr = 3) ) ) ) OR (Codigo IN (SELECT SoliRHPrerr.CodigoCurso FROM SoliRHPrerr, SoliRH WHERE SoliRHPrerr.CveSoli = SoliRH.CveSoli AND SoliRHPrerr.CveRH = SoliRH.CveRH AND SoliRH.CveEstAnalis = 2 AND (SoliRH.CveEstPrerr = 1 OR SoliRH.CveEstPrerr = 3) AND SoliRHPrerr.Estatus = 3 AND SoliRHPrerr.CveSoli IN (SELECT Clave FROM SoliCapacit WHERE CveCampus = Campus AND CveProyCapacit = Proyecto ) AND SoliRHPrerr.CveRH IN (SELECT Clave FROM RecHumanos WHERE CvePuesto IN (SELECT Clave FROM Puestos WHERE TipoEmp = Tipo ) ) ) ) OR (Codigo IN (SELECT CodigoCurso FROM ReqCursosRH WHERE CveRequerimiento IN (SELECT Clave FROM Requerimientos

-8-

WHERE CveProyecto = Proyecto) AND CveEstAnalis = ACEPTADO AND (CveEstPrerr = 2 OR CveEstPrerr = 3) AND CveRH IN (SELECT Clave FROM RecHumanos WHERE CvePuesto IN (SELECT Clave FROM Puestos WHERE TipoEmp = Tipo) AND CveCentroTrab IN (SELECT Clave FROM CentrosTrab WHERE CveLocalidad IN (SELECT Clave FROM Localidades WHERE CveEstFederativo IN (SELECT Clave FROM EstFederativos WHERE CveCampus = Campus ) ) ) ) ) ) OR (Codigo IN (SELECT ReqCursosRHPrerr.CodigoCurso FROM ReqCursosRHPrerr, ReqCursosRH WHERE ReqCursosRHPrerr.CveRequerimiento = ReqCursosRH.CveRequerimiento AND ReqCursosRHPrerr.CveRH = ReqCursosRH.CveRH AND ReqCursosRH.CveEstAnalis = 2 AND (ReqCursosRH.CveEstPrerr = 1 OR ReqCursosRH.CveEstPrerr = 3) AND ReqCursosRHPrerr.Estatus = 3 AND ReqCursosRHPrerr.CveRequerimiento IN (SELECT Clave FROM Requerimientos WHERE CveProyecto = Proyecto) AND ReqCursosRHPrerr.CveRH IN (SELECT Clave FROM RecHumanos WHERE CvePuesto IN (SELECT Clave FROM Puestos WHERE TipoEmp = Tipo) AND CveCentroTrab IN (SELECT Clave FROM CentrosTrab WHERE CveLocalidad IN (SELECT Clave FROM Localidades WHERE CveEstFederativo IN (SELECT Clave FROM EstFederativos WHERE CveCampus = Campus ) ) ) ) ) ) OPEN CursorCursos FETCH CursorCursos INTO RegCurso MIENTRAS sqlca.sqlcode = 0 HAZ

-9-

COMIENZA Inserta(RegCurso.Codigo,RegCurso.Duracion,RegCurso.MinParticipantes,RegCurso.MaxParticipantes,ListaCursos) FETCH CursorCursos INTO RegCurso TERMINA CLOSE CursorCursosTERMINA

/*****************************************************************************************************************************************************Función: Ordenar los cursos que se van a programar de acuerdo a su seriación.Fecha de actualización: 09/03/94

*****************************************************************************************************************************************************/PROC OrdenaCursos(ApAnterior,VAR ListaCursos,TipoEmp)COMIENZA SI ListaCursos^.Liga <> NULL ENTONCES COMIENZA OrdenaCursos(ListaCursos,ListaCursos^.Liga,TipoEmp) AcomodaCurso(ApAnterior,ListaCursos,TipoEmp,ListaCursos) TERMINATERMINA

/*****************************************************************************************************************************************************Función: Ordenar un curso dentro de la lista ligada de acuerdo a su seriación con los demás cursos.Fecha de actualización: 09/03/94

*****************************************************************************************************************************************************/PROC AcomodaCurso(ApAnterior,ApCurso,TipoEmp,VAR ListaCursos)COMIENZA ApAux := ApCurso^.Liga MIENTRAS ApAux <> NULL HAZ SI EsPrerrequisito(ApCurso,ApAux,TipoEmp) ENTONCES COMIENZA MueveCurso(ApAnterior,ApCurso,ApAux,ListaCursos) ApAux := ApCurso^.Liga TERMINA OTRO ApAux := ApAux^.LigaTERMINA/*****************************************************************************************************************************************************

Función: Intercambiar un el orden de los nodos en la lista de cursos.Fecha de actualización: 09/03/94

*****************************************************************************************************************************************************/PROC MueveCurso(VAR ApAnterior,ApCurso,ApAux,VAR ListaCursos)COMIENZA SI ApAnterior = NULL ENTONCES ListaCursos := ApCurso^.Liga OTRO ApAnterior^.Liga := ApCurso^.Liga ApCurso^.Liga := ApAux^.Liga ApAux^.Liga := ApCurso ApAnterior := ApAuxTERMINA

-10-

/*****************************************************************************************************************************************************Función: Identificar si un curso es prerrequisito de otro en alguna curricula.Fecha de actualización: 17/03/94

*****************************************************************************************************************************************************/FUNCION EsPrerrequisito(ApCurso,ApAux,TipoEmp) /* Se Busca si ApCurso^.Codigo es prerrequisito de Aux^.Codigo */COMIENZA NumPrerr := 0

SELECT COUNT(*) /* Se busca si es prerrequisito en los prerrequisitos propios del curso solamente */ INTO NumPrerr FROM Prerrequisitos WHERE CodigoCurso = Aux^.Codigo AND CodigoPrerr = ApCurso^.Codigo

SI NumPrerr = 0 ENTONCES COMIENZA SI TipoEmp = SINDICALIZADO ENTONCES COMIENZA /* Se busca si es prerrequisito en curriculas de sindicalizado */ SELECT COUNT(*) INTO NumPrerr FROM CurrSindPrerr WHERE CodigoCurso = ApCurso^.Codigo AND CveCurrSind IN ( SELECT Clave FROM CurrSind WHERE CodigoCurso = ApAux^.Codigo) SI NumPrerr = 0 ENTONCES COMIENZA /* Se busca si es prerrequisito en curriculas del tronco básico para sindicalizdo */ SELECT COUNT(*) INTO NumPrerr FROM TCSindPrerr WHERE CodigoCurso = ApCurso^.Codigo AND CveTroncBasSin IN ( SELECT Clave FROM TCSind WHERE CodigoCurso = ApAux^.Codigo) TERMINA TERMINA OTRO /* Se busca prerrequisito en en curriculas de confianza */ COMIENZA SELECT COUNT(*) INTO NumPrerr FROM CurrConfPrerr WHERE CodigoCurso = ApCurso^.Codigo AND CveCurrConf IN ( SELECT Clave FROM CurrConf WHERE CodigoCurso = ApAux^.Codigo) SI NumPrerr = 0 ENTONCES /* Se busca prerrequisito en curriculas del tronco básico para confianza */ COMIENZA SELECT COUNT(*) INTO NumPrerr FROM TCConfPrerr WHERE CodigoCurso = ApCurso^.Codigo AND CveTroncBasConf IN ( SELECT Clave FROM TCConf

-11-

WHERE CodigoCurso = ApAux^.Codigo) TERMINA TERMINA TERMINA SI NumPrerr = 0 ENTONCES EsPrerrequisito := FALSO OTRO EsPrerrequisito := CIERTOTERMINA

/*****************************************************************************************************************************************************Función: Invertir una lista ligada.Fecha de actualización: 09/03/94

*****************************************************************************************************************************************************/PROC InvierteListaCursos(ApAnterior,ApCurso,VAR ListaCursos)COMIENZA SI ApCurso <> NUL ENTONCES COMIENZA InvierteListaCursos(ApCurso,ApCurso^.Liga,ListaCursos) SI ApCurso^.Liga = NULL ENTONCES ListaCursos := ApCurso ApCurso^.Liga := ApAnterior TERMINATERMINA

/*****************************************************************************************************************************************************Función: Realizar un programa de cursos, programando cursos por curso de los solicitados, para cubrir las necesidades de un proyecto en un campus.Fecha de actualización: 09/03/94

*****************************************************************************************************************************************************/PROC ProgramaCursoxCurso(Tipo,ListaCursos,Proyecto,Campus,PeriodoProyecto)COMIENZA ApCurso := ListaCursos MIENTRAS Curso <> NIL HAZ COMIENZA TotalSolicitudes := 0 EligeParticipantes(Tipo,Proyecto,Campus,ApCurso,ListaParticipantes,TotalSolicitudes) /* Este procedimiento genera una lista ligada ordenada para un campus,centro de trabajo, categoria y antigüedad. Sus campos son: ClaveEmpleado,ClaveCentroTrab, Liga y ListaGruposAfectados. TotalSolicitudes es el tamaño de la lista de participantes */ GeneraListaRecursos(ApCurso,ListaRecursosRequeridos,Campus) /* ListaRecursos es un registro de dos listas ligadas, una para tipos de equipos y una para tipos de instalaciones que requiere el curso para impartirse. Se incluye el cronograma del curso. */ GeneraGrupos(PeriodoProyecto,Proyecto, Campus, ApCurso, ListaParticipantes, ListaRecursosRequeridos, TotalSolicitudes,Tipo) /* Deja el resultado en la tabla Grupos y sus asociaciones de instalaciones, Equipos, Instructores Proveedores y part. */ ApCurso := ApCurso^.liga Libera(ListaParticipantes) Libera(ListaRecursosRequeridos.ListaEquiposRequeridos) Libera(ListaRecursosRequeridos.ListaInstalRequeridas) Libera(ListaRecursosRequeridos.InstructoresPosibles.ListaInstructores) Libera(ListaRecursosRequeridos.InstructoresPosibles.ListaProveedores) TERMINA

-12-

TERMINA

/*****************************************************************************************************************************************************Función: Este procedimiento genera una lista ligada de empleados que solicitan un curso, ordenada por Campus, centro de trabajo, categoria y

antigüedad. TotalSolicitudes contendrá el tamaño de ListaParticipantes. NOTA: Pendiente la forma de buscar una jerarquia más uniforme tomando en consideración la jerarquia de la categoría y la antigüedad del participante. Falta actualizar el estado de las solicitudes de los recursos humanos para indicar que se programaron.

Fecha de actualización: 17/03/94*****************************************************************************************************************************************************/PROC EligeParticipantes(Tipo,Proyecto,Campus,ApCurso,VAR ListaParticipantes,VAR TotalSolicitudes)COMIENZA TotalSolicitudes := 0 SI Tipo = SINDICALIZADO /* Tipo de empleado sindicalizado */ COMIENZA DECLARE CursorPart CURSOR FOR SELECT RecHumanos.Clave, CveCentroTrab,FechaIngreso,JerarquiaCat FROM RecHumanos, Categorias WHERE (RecHumanos.Clave IN (SELECT CveRH FROM SoliRH WHERE CveSoli IN (SELECT Clave FROM SoliCapacit WHERE CodCurso = ApCurso^.Codigo AND CveProyCapacit = Proyecto AND CveCampus = Campus ) AND CveEstAnalis = ACEPTADO AND (CveEstPrerr = 2 OR CveEstPrerr = 3 ) ) ) OR (RecHumanos.Clave IN (SELECT SoliRHPrerr.CveRH FROM SoliRHPrerr, SoliRH WHERE SoliRHPrerr.CveSoli = SoliRH.CveSoli AND SoliRHPrerr.CveRH = SoliRH.CveRH AND SoliRH.CveEstAnalis = 2 AND (SoliRH.CveEstPrerr = 1 OR SoliRH.CveEstPrerr = 3) AND SoliRHPrerr.Estatus = 3 AND SoliRHPrerr.CodigoCurso = ApCurso^.Codigo AND SoliRHPrerr.CveSoli IN (SELECT Clave FROM SoliCapacit WHERE CveProyCapacit = Proyecto AND CveCampus = Campus ) ) ) OR (RecHumanos.Clave IN (SELECT CveRH FROM ReqCursosRH WHERE CodigoCurso = ApCurso^.Codigo AND CveRequerimiento IN (SELECT Clave FROM Requerimientos WHERE CveProyecto = Proyecto ) AND CveEstAnalis = 'ACEPTADO' AND (CveEstPrerr = 2 OR CveEstPrerr = 3 ) AND

-13-

CveRH IN (SELECT Clave FROM RecHumanos WHERE CveCentroTrab IN (SELECT Clave FROM CentrosTrab WHERE CveLocalidad IN (SELECT Clave FROM Localidades WHERE CveEstFederativo IN (SELECT Clave FROM EstFederativos WHERE CveCampus = Campus ) ) ) ) ) ) OR (RecHumanos.Clave IN (SELECT ReqCursosRHPrerr.CveRH FROM ReqCursosRHPrerr,ReqCursosRH WHERE ReqCursosRHPrerr.CveRequerimiento = ReqCursosRH.CveRequerimiento AND ReqCursosRHPrerr.CveRH = ReqCursosRH.CveRH AND ReqCursosRH.CveEstAnalis = ACEPTADO AND (ReqCursosRH.CveEstPrerr 1 OR ReqCursosRH.CveEstPrerr = 3) AND ReqCursosRHPrerr.Estatus = 3 AND ReqCursosRHPrerr.CodigoCurso = ApCurso^.Codigo ReqCursosRHPrerr.CveRequerimiento IN (SELECT Clave FROM Requerimientos WHERE CveProyecto = Proyecto ) AND ReqCursosRHPrerr.CveRH IN (SELECT Clave FROM RecHumanos WHERE CveCentroTrab IN (SELECT Clave FROM CentrosTrab WHERE CveLocalidad IN (SELECT Clave FROM Localidades WHERE CveEstFederativo IN (SELECT Clave FROM EstFederativos WHERE CveCampus = Campus ) ) ) ) AND (RecHumanos.CvePuesto IN (SELECT Clave FROM Puestos WHERE TipoEmp = Tipo ) ) ORDER BY CveCentroTrab, JerarquiaCat, FechaIngreso TERMINA OTRO /* Tipo de empleado confianza */ COMIENZA DECLARE CursorPart CURSOR FOR

-14-

SELECT Clave, CveCentroTrab,FechaIngreso,JerarquiaNiv FROM RecHumanos, Niveles WHERE (RecHumanos.Clave IN (SELECT CveRH FROM SoliRH WHERE CveSoli IN (SELECT Clave FROM SoliCapacit WHERE CodCurso = ApCurso^.Codigo AND CveProyCapacit = Proyecto AND CveCampus = Campus ) AND CveEstAnalis = ACEPTADO AND (CveEstPrerr = 2 OR CveEstPrerr = 3 ) ) ) OR (RecHumanos.Clave IN (SELECT SoliRHPrerr.CveRH FROM SoliRHPrerr, SoliRH WHERE SoliRHPrerr.CveSoli = SoliRH.CveSoli AND SoliRHPrerr.CveRH = SoliRH.CveRH AND SoliRH.CveEstAnalis = 2 AND (SoliRH.CveEstPrerr = 1 OR SoliRH.CveEstPrerr = 3) AND SoliRHPrerr.Estatus = 3 AND SoliRHPrerr.CodigoCurso = ApCurso^.Codigo AND SoliRHPrerr.CveSoli IN (SELECT Clave FROM SoliCapacit WHERE CveProyCapacit = Proyecto AND CveCampus = Campus ) ) ) OR (RecHumanos.Clave IN (SELECT CveRH FROM ReqCursosRH WHERE CodigoCurso = ApCurso^.Codigo AND CveRequerimiento IN (SELECT Clave FROM Requerimientos WHERE CveProyecto = Proyecto ) AND CveEstAnalis = 'ACEPTADO' AND (CveEstPrerr = 2 OR CveEstPrerr = 3 ) AND CveRH IN (SELECT Clave FROM RecHumanos WHERE CveCentroTrab IN (SELECT Clave FROM CentrosTrab WHERE CveLocalidad IN (SELECT Clave FROM Localidades WHERE CveEstFederativo IN (SELECT Clave FROM EstFederativos WHERE CveCampus = Campus ) ) ) ) ) ) OR (RecHumanos.Clave IN (SELECT ReqCursosRHPrerr.CveRH

-15-

FROM ReqCursosRHPrerr,ReqCursosRH WHERE ReqCursosRHPrerr.CveRequerimiento = ReqCursosRH.CveRequerimiento AND ReqCursosRHPrerr.CveRH = ReqCursosRH.CveRH AND ReqCursosRH.CveEstAnalis = ACEPTADO AND (ReqCursosRH.CveEstPrerr 1 OR ReqCursosRH.CveEstPrerr = 3) AND ReqCursosRHPrerr.Estatus = 3 AND ReqCursosRHPrerr.CodigoCurso = ApCurso^.Codigo ReqCursosRHPrerr.CveRequerimiento IN (SELECT Clave FROM Requerimientos WHERE CveProyecto = Proyecto ) AND ReqCursosRHPrerr.CveRH IN (SELECT Clave FROM RecHumanos WHERE CveCentroTrab IN (SELECT Clave FROM CentrosTrab WHERE CveLocalidad IN (SELECT Clave FROM Localidades WHERE CveEstFederativo IN (SELECT Clave FROM EstFederativos WHERE CveCampus = Campus ) ) ) ) AND (RecHumanos.CvePuesto IN (SELECT Clave FROM Puestos WHERE TipoEmp = Tipo ) ) ORDER BY CveCentroTrab, JerarquiaNiv, FechaIgreso TERMINA OPEN CursorPart FETCH CursorPart INTO RegPart SI sqlca.sqlcode = 0 ENTONCES COMIENZA Jerarquia = 1 Inserta(RegPart.Clave,RegPart.CveCentroTrab,Jerarquia,ListaParticipantes) TotalSolicitudes := TotalSolicitudes + 1 RegPartAnt := RegPart MIENTRAS sqlca.sqlcode = 0 HAZ COMIENZA Inserta(RegPart.Clave,RegPart.CveCentroTrab,JerarquiaEmp(RegPartAnt,RegPart,Jerarquia), ListaParticipantes) TotalSolicitudes := TotalSolicitudes + 1 RegPartAnt := RegPart FETCH CursorPart INTO RegPart TERMINA TERMINA CLOSE CursorPartTERMINA

-16-

/*****************************************************************************************************************************************************Función: Generar un valor númerico que identifique la jerarquia de un empleadoFecha de actualización: 09/03/94

*****************************************************************************************************************************************************/FUNCION JerarquiaEmp(PartAnt,PartActual,Jerarquia)COMIENZA SI PartAnt.CveCentroTrab <> PartActual.CveCentroTrab ENTONCES Jerarquia := 1 OTRO COMIENZA SI PartAnt.Jerarquia <> PartActual.Jerarquia ENTONCES Jerarquia := Jerarquia + 1 OTRO Jerarquia := Jerarquia + Antigüedad(PartAnt,PartActual) TERMINA JerarquiaEmp := JerarquiaTERMINA

NOTA: Aun no se define bien la función Pendiente la función antigüedad

/*****************************************************************************************************************************************************Función : Generar la lista de tipos de instalaciones y tipos de equipo que requiere un curso con las horas en las que se requerira el cursoFecha de actualización: 05/04/94

*****************************************************************************************************************************************************/PROC GeneraListaRecursos(ApCurso,VAR ListaRecursosRequeridos,CveCampus)COMIENZA GeneraListaInstalaciones(ApCurso^.Codigo,ListaRecursosRequeridos.ListaInstalRequeridas) GeneraListaEquipos(ApCurso^.Codigo,ListaRecursosRequeridos.ListaEquiposRequeridos) GeneraListaInstructoresPosibles(ApCurso,CveCampus,ListaRecursosRequeridos.InstructoresPosibles.ListaInstructores) ListaRecursosRequeridos.InstructoresPosibles.ListaProveedores := NULLTERMINA

/*****************************************************************************************************************************************************Función : Generar la lista de tipos de instalaciones que requiere un curso y las horas en las que se requieren.Fecha de actualización: 10/03/94

*****************************************************************************************************************************************************/PROC GeneraListaInstalaciones(CveCurso,VAR ListaInstalRequeridas)COMIENZA ListaInstalRequeridas := NULL DECLARE CursorReqInstal CURSOR FOR SELECT CveTipInstalacion,HoraInicial,HoraFinal FROM ReqInstalCurs WHERE CodigoCurso = CveCurso ORDER BY CveTipInstalacion, HoraInicial

OPEN CursorReqInstal FETCH CursorReqInstal INTO RegReqInstal /* RegReqInstal es una estructura de tipo de ListaInstalRequeridas */

-17-

MIENTRAS sqlca.sqlcode = 0 HAZ COMIENZA InsertaOrden(RegReqInstal.CveTipInstalacion,RegReqInstal.HoraIni,RegReqInstal.HoraFin,ListaInstalRequeridas) /* Inserta en una lista ligada */ FETCH CursorReqInstal INTO RegReqInstal TERMINA CLOSE CursorReqInstalTERMINA

/*****************************************************************************************************************************************************Función : Generar la lista de tipos de equipos que requiere un curso, el número de equipos requeridos por grupo para el curso y las horas en las

que se requieren.Fecha de actualización: 10/03/94

*****************************************************************************************************************************************************/PROC GeneraListaEquipos(CveCurso,VAR ListaEquiposRequeridos)COMIENZA ListaEquiposRequeridos := NULL DECLARE CursorReqEqps CURSOR FOR SELECT CveTipEquipo,CantPorGrupo,HoraInicial,HoraFinal FROM ReqEqCurs WHERE CodigoCurso = CveCurso ODER BY CveTipEquipo, HoraInicial

OPEN CursorReqEqps FETCH CursorReqEqps INTO RegReqEquipo /* RegReqEquipo es una estructura de tipo de ListaEquiposRequeridos */

MIENTRAS sqlca.sqlcode = 0 HAZ COMIENZA InsertaOrden(RegReqEquipo.CveTipEquipo,RegReqEquipo.NumEqpsxGrupo,RegReqEquipo.HoraIni,RegReqEquipo.HoraFin,ListaEquiposRequeridos) /* Inserta en una lista ligada */ FETCH CursorReqEqps INTO RegReqEquipo TERMINA CLOSE CursorReqEqps ConvierteReqEqxDia(ListaEquiposRequeridos)TERMINA

/*****************************************************************************************************************************************************Función : Generar la lista de instructores posibles para un cursoFecha de actualización:

**********************************************************************************************************PROC GeneraListaInstructoresPosibles(ApCurso,ClaveCampus,VAR ListaInstructores)COMIENZA ListaInstructores := NULL GeneraListaInstrPosiblesOCM(ApCurso,ClaveCampus,VAR ListaInstructores) GeneraListaInstrPosiblesITM(ApCurso,ClaveCampus,VAR ListaInstructores)TERMINA

-18-

/*****************************************************************************************************************************************************Función : Generar la lista de instructores posibles. Los instructores aqui considerados son de ITMFecha de actualización:

*****************************************************************************************************************************************************/PROC GeneraListaInstrPosiblesITM(ApCurso,ClaveCampus,VAR ListaInstructores)COMIENZA DECLARE CursorInstructores CURSOR FOR SELECT Instructores.Clave, Instructores.CveTipInstrs, Instructores.CveRecurso, InstructorCurs.Calificacion, RecHumanosIntt.Sueldo, Instuctores.CveLocalidad, 0, 0, RecHumanosIntt.CveTipPago /* Este último campo se lee en una variable aparte, fuera del registro que contiene a todos los campos anteriores */ FROM Instructores, InstructorCurs, RecHumanosIntt WHERE Instructores.Clave = InstructorCurs.CveInstructor AND Instructores.CveRecurso = RecHumanosIntt.Clave InstructorCurs.CodigoCurso = ApCurso^.Codigo AND Instructores.CveTipInstrs = 1 /* Tipo de instructor propio */ Instructores.CveLocalidad IN ( SELECT Clave FROM Localidades WHERE CveEstFederativo IN (SELECT Clave FROM EstFederativos WHERE CveCampus = ClaveCampus) OPEN CursorInstructores FETCH CursorInstructores INTO RegInstructor, CveTipoPago /* RegInstructor es del tipo ListaInstructoresSQL */ MIENTRAS sqlca.sqlcode = 0 HAZ COMIENZA /* Los sueldos se deberán pasar a sueldo por hora */ CASO DE CveTipoPago COMIENZA 2: ListaInstructores.CostoInstruccionHr := ListaInstructores.CostoInstruccionHr / 8 /* El sueldo está descrito por dia */ 3: ListaInstructores.CostoInstruccionHr := (ListaInstructores.CostoInstruccionHr / 15) / 8 /* El sueldo está descrito por periodo de 15 dias */ 4: ListaInstructores.CostoInstruccionHr := (ListaInstructores.CostoInstruccionHr / 31) / 8 /* El sueldo está descrito por periodo mensual */ TERMINA Inserta(RegInstructor,ListaInstructores) /* Inserta en lista ligada */ FETCH CursorInstructores INTO RegInstructor, CveTipoPago TERMINA CLOSE CursorInstructoresTERMINA

/*****************************************************************************************************************************************************Función : Generar la lista de instructores posibles. Los instructores aqui considerados son de la nomina del cliente (OCM)

NOTA: El instructor es de alguno de los siguientes: 2 (comisionado permanente linea confianza) 3 (comisionado auxiliar linea confianza) 4 (comisionado auxiliar linea sindicalizado) se les debe adicionar un porcentaje de comisión

Fecha de actualización:*****************************************************************************************************************************************************/PROC GeneraListaInstrPosiblesTelmex(ApCurso,ClaveCampus,VAR ListaInstructores)

-19-

COMIENZA Comision := Parametro('PtjeComision') / 100 DECLARE CursorInstructores CURSOR FOR SELECT Instructores.Clave, Instructores.CveTipInstrs, Instructores.CveRecurso, InstructorCurs.Calificacion, RecHumanos.Sueldo, Instuctores.CveLocalidad, 0, 0, RecHumanos.CveTipPago /* Este último campo se lee en una variable aparte, fuera del registro que contiene a todos los campos anteriores */ FROM Instructores, InstructorCurs, RecHumanos WHERE Instructores.Clave = InstructorCurs.CveInstructor AND Instructores.CveRecurso = RecHumanos.Clave InstructorCurs.CodigoCurso = ApCurso^.Codigo AND Instructores.CveTipInstrs <> 1 /* Tipo de instructor diferente de propio */ Instructores.CveLocalidad IN ( SELECT Clave FROM Localidades WHERE CveEstFederativo IN (SELECT Clave FROM EstFederativos WHERE CveCampus = ClaveCampus)

OPEN CursorInstructores FETCH CursorInstructores INTO RegInstructor, CveTipoPago /* RegInstructor es del tipo ListaInstructoresSQL */ MIENTRAS sqlca.sqlcode = 0 HAZ COMIENZA /* Los sueldos se deberán pasar a sueldo por hora */ CASO DE CveTipoPago COMIENZA 2: ListaInstructores.CostoInstruccionHr := ListaInstructores.CostoInstruccionHr / 8 /* El sueldo está descrito por dia */ 3: ListaInstructores.CostoInstruccionHr := (ListaInstructores.CostoInstruccionHr / 15) / 8 /* El sueldo está descrito por periodo de 15 dias */ 4: ListaInstructores.CostoInstruccionHr := (ListaInstructores.CostoInstruccionHr / 31) / 8 /* El sueldo está descrito por periodo mensual */ TERMINA /* Adición del porcentaje de comisión */ SI (RegInstructor.CveTipInstr = 2 OR RegInstructor.CveTipInstr = 3 OR RegInstructor.CveTipInstr = 4) ENTONCES RegInstructor.CostoInstrucciónHr := RegInstructor.CostoInstrucciónHr * (1 + Comision) Inserta(RegInstructor,ListaInstructores) /* Inserta en lista ligada */ FETCH CursorInstructores INTO RegInstructor, CveTipoPago TERMINA CLOSE CursorInstructoresTERMINA

-20-

/********************************************************************************************************Función: Generar los grupos con participantes, instructores y equipos para la satisfacción de la solicitud de un curso.Fecha de actualización: 04/04/94

********************************************************************************************************/PROC GeneraGrupos(PeriodoProyecto,Proyecto,Campus,ApCurso,VAR ListaParticipantes, ListaRecursosRequeridos,TotalSolicitudes,TipoEmp)COMIENZA AbrePosiblesGrupos(PeriodoProyecto,Campus,ApCurso,GruposPosibles,ListaRecursosRequeridos, CantGposPosibles,DatosFuncionGLB.CostoMin,DatosFuncionGBL.CostoMax) CreaAsigParticPosibles(ListaParticipantes,GruposPosibles,CantGruposPosibles,PeriodoProyecto) SolicProgramadas := SolicNoProgramadas := NumReprogramanciones := 0 DebeProgramar := CIERTO NumVecesAplicacion := Parametro('CantProgRem') ApPartActual := ListaParticipantes MIENTRAS DebeProgramar HAZ COMIENZA MIENTRAS PartActual <> NIL HAZ COMIENZA EligeAsigPartCostoMin(ApPartActual,GruposPosibles,ApGrupoPosible) SI ApGrupoPosible != NULL ENTONCES COMIENZA SI CumplePorcentajesLineamientos(ApCurso,ApPartActual,ApGrupoPosible) ENTONCES COMIENZA AsignaPartAGrupo(ApPartActual,GruposPosibles, ApGrupoPosible) SI CubreMínimoPart(ApCurso,ApGrupoPosible) ENTONCES COMIENZA SI PuedeAsignarRecursos(PeriodoProyecto,ApCurso,ApGrupoPosible, ListaRecursosRequeridos,ListaRecursos,CveCampus) ENTONCES COMIENZA ApPartActual := ApPartActual^.Liga DefinirGrupoDefinitivo(ListaParticipantes,ApGrupoPosible,ApCurso, ListaRecursos,ListaRecursosRequeridos, TablaCorrespGrupos,Proyecto,TipoEmp) SolicProgramadas := SolicProgramadas + ApCurso^.MinParticipantes TERMINA OTRO COMIENZA EliminaGrupoPosible(GruposPosibles, ApGrupoPosible,ListaParticipantes) TERMINA TERMINA OTRO COMIENZA SI EstáEntreMinyMax(ApCurso,ApGrupoPosible) ENTONCES COMIENZA AsignaPartDefinitivamente(ListaParticipantes, ApPartActual,ApGrupoPosible, TablaCorrespGrupos) SolicProgramadas := SolicProgramadas + 1 TERMINA OTRO ApPartActual := ApPartActual^.Liga SI CubreMáximoPart(ApCurso,ApGrupoPosible) ENTONCES CierraGrupo(PeriodoProyecto,GruposPosibles,ApGrupoPosible,TablaCorrespGrupos, ListaRecursosRequeridos) TERMINA TERMINA TERMINA OTRO ApPartActual:= ApPartActual^.Liga TERMINA DepuraListaParticipantes(ListaParticipantes,SolicNoProgramadas) DebeProgramar := AplicarMismoMetodo(TotalSolicitudes,SolicProgramadas,SolicNoProgamadas, NumVecesAplicacion,NumReprogramaciones) SI DebeProgramar ENTONCES DepuraAsociaciones(GruposPosibles,ApCurso,ListaParticipantes) TERMINA ProgramaRemanente(PeriodoProyecto,Proyecto,Campus,ListaParticipantes,ListaRecursosRequeridos,ApCurso, GruposPosibles,TablaCorrespGrupos,CantGposPosibles,TipoEmp) TerminaProcesoCurso(GruposPosibles,TablaCorrespGrupos)TERMINA

21

/***************************************************************************************************************************************************** Nota: Esto no se codifica*****************************************************************************************************************************************************/PROC SeleccionaCursos(Tipo,Proyecto,Campus,ListaCursos)COMIENZA DECLARE CursorCursos CURSOR FOR SELECT Codigo, Duracion, NumMinPart, NumMaxPart FROM Cursos WHERE (Codigo IN (SELECT CodCurso FROM SoliCapacit WHERE CveProyCapacit = Proyecto AND CveCampus = Campus AND Clave IN (SELECT CveSoli FROM SoliRH WHERE CveRH IN (SELECT Clave FROM RecHumanos WHERE CvePuestos IN (SELECT Clave FROM Puestos WHERE TipoEmp = Tipo ) ) AND CveEstAnalis = 'ACEPTADO' AND (CveEstPrerr = 2 OR CveEstPrerr = 3) ) ) ) OR (Codigo IN (SELECT CodigoCurso FROM SoliRHPrerr WHERE CveSoli IN (SELECT CveSoli FROM SoliRH WHERE CveEstAnalis = 'ACEPTADO' AND (CveEstPrerr = 1 OR CveEstPrerr = 3)) AND CveSoli IN (SELECT Clave FROM SoliCapacit WHERE CveCampus = Campus AND CveProyCapacit = Proyecto) AND CveRH IN (SELECT Clave FROM RecHumanos WHERE CvePuesto IN (SELECT Clave FROM Puestos WHERE TipoEmp = Tipo) ) AND Estatus = 3 ) ) OR (Codigo IN (SELECT CodigoCurso FROM ReqCursosRH WHERE CveRequerimiento IN (SELECT Clave FROM Requerimientos WHERE CveProyecto = Proyecto) AND CveEstAnalis = ACEPTADO AND (CveEstPrerr = 2 OR CveEstPrerr = 3) AND CveRH IN (SELECT Clave FROM RecHumanos

22

WHERE CvePuesto IN (SELECT Clave FROM Puestos WHERE TipoEmp = Tipo) AND CveCentroTrab IN (SELECT Clave FROM CentrosTrab WHERE CveLocalidad IN (SELECT Clave FROM Localidades WHERE CveEstFederativo IN (SELECT Clave FROM EstFederativos WHERE CveCampus = Campus ) ) ) ) ) ) OR (Codigo IN (SELECT CodigoCurso FROM ReqCursosRHPrerr WHERE CveRequerimiento IN (SELECT CveRequerimiento FROM ReqCursosRH WHERE CveEstAnalis = 'ACEPTADO' AND (CveEstPrerr = 1 OR CveEstPrerr = 3)) AND CveRequerimiento IN (SELECT Clave FROM Requerimientos WHERE CveProyecto = Proyecto) AND CveRH IN (SELECT Clave FROM RecHumanos WHERE CvePuesto IN (SELECT Clave FROM Puestos WHERE TipoEmp = Tipo) AND CveCentroTrab IN (SELECT Clave FROM CentrosTrab WHERE CveLocalidad IN (SELECT Clave FROM Localidades WHERE CveEstFederativo IN (SELECT Clave FROM EstFederativos WHERE CveCampus = Campus ) ) ) ) AND Estatus = 3 ) )

OPEN CursorCursos FETCH CursorCursos INTO RegCurso

MIENTRAS sqlca.sqlcode = 0 HAZ COMIENZA Inserta(RegCurso.Codigo,RegCurso.Duracion,RegCurso.MinParticipantes,RegCurso.MaxParticipantes,ListaCursos) FETCH CursorCursos INTO RegCurso TERMINA

23

CLOSE CursorCursosTERMINA

/***************************************************************************************************************************************************** Función: Determinar si la cantidad de participantes actualmente asignados a un grupo cumple con el cupo mínimo especificado para el curso. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/FUNCION CubreMínimoPart(ApCurso,ApGrupoPosible)COMIENZA CubreMinimoPart := (ApGrupoPosible^.CantPart = ApCurso^.MinParticipantes)TERMINA

/***************************************************************************************************************************************************** Función: Determinar si la cantidad de personas asignadas a un grupo es mayor que el cupo mínimo para el curso y menor o igual al cupo máximo especificado para el curso Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/FUNCION EstaEntreMinyMax(ApCurso,ApGrupoPosible)COMIENZA EstaEntreMinyMax := ((ApGrupoPosible^.CantPart > ApCurso^.MinParticipantes) AND (ApGrupoPosible^.CantPart <= ApCurso^.MaxParticipantes))TERMINA

/***************************************************************************************************************************************************** Función: Determinar si la cantidad de personas asignadas a un grupo cumple con el máximo de participantes permitidos para el curso específico Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/FUNCION CubreMaximoPart(ApCurso,ApGrupoPosible)COMIENZA CubreMaximoPart := (ApGrupoPosible^.CantPart = ApCurso^.MaxParticipantes)TERMINA/***************************************************************************************************************************************************** Función: Eliminar de la tabla de hash GruposPosibles un grupo que no deberá considerarse posteriormente para ningún participante.

Para cada uno de los participantes hasta este momento asignados provisionalmente al grupo se liberan sus demás asociaciones. Se restablecenlos contadores de personal en capacitación por día por centro de trabajo y los contadores de personal en capacitación para el total de empleadosdel cliente. Se elimina al grupo de la tabla de grupos posibles y se eliminan todas las asociaciones de participantes relacionadas con el grupo.Se liberan las asociaciones inhibidas a participantes afectados por los lineamientos al momento de que los participantes de mayor categoria ymayor antigüedad fueron asignados al grupo que se esta eliminando actualmente. Se liberan las asociaciones a grupos con Status 'C' y 'T' paraliberar los porcentajes de personal en capacitación para un centro de trabajo y del cliente.

Fecha de actualización: 14/03/94*****************************************************************************************************************************************************/PROC EliminaGrupoPosible(GruposPosibles, VAR ApGrupoPosible, ListaParticipantes)COMIENZA RestableceTablaPartDiaCliente(ApGrupoPosible,ApGrupoPosible^.CantPart) /* Hasta este momento el No. de participantes asignados a capacitación en el grupo que se esta eliminando es igual al mímimo de participantes para el curso */ DECLARE CursorParticipantes CURSOR FOR

24

SELECT CveEmp FROM AsocParticipantes WHERE ClaveGrupoPosible = ApGrupoPosible^.Clave AND Status = 'P'

OPEN CursorParticipantes FETCH CursorParticipantes INTO CvePart

MIENTRAS (sqlca.sqlcode = 0) HAZ COMIENZA ApParticipante := BuscaParticipante(CvePart,ListaParticipantes) /* Localiza al participante dentro de la ListaParticipantes. Es una localización dentro de una lista ligada. Devuelve el apuntador al nodo donde Clave = CvePart */ RestableceTablaPartDiaCT(ApParticipante,ApGrupoPosible) SI Parametro('MenorCatAnt') = 'NO' ENTONCES COMIENZA LiberaAsocAfectadas(ApParticipante,ListaParticipantes) Libera(ApParticipante^.ListaGruposAfectados) /* Se libera la lista de grupos afectados del participante. Esto es se TERMINA libera el espacio ocupado por la lista ligada */ FETCH CursorParticipantes INTO CvePart TERMINA CLOSE CursorParticipantes

LiberaAsocPorPtjesLineamientos(ApGrupoPosible,GruposPosibles) /* Libera las asociaciones inhibidas por saturación de porcentajes en centro de trabajo y cliente */ EliminaAsocAGrupo(ApGrupoPosible^.Clave) /* Elimina todas las ocurrencias de un grupo en la tabla AsocParticipantes */ Elimina(ApGrupoPosible^.Clave,GruposPosibles) /* Elimina al grupo posible de la tabla de hash GruposPosibles. Eliminación de un nodo.*/TERMINA

NOTA: La llamada a la función subrayada podria desaparcer/***************************************************************************************************************************************************** Función: Restablecer los contadores de personal del cliente en capacitación por dia por la desintegración de un grupo propuesto. Se da por hecho que en la tabla PartDiaCliente sólo se encuentran los días hábiles para capacitación. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC RestableceTablaPartDiaCliente(ApGrupoPosible,NumPart)COMIENZA UPDATE PartDiaCliente SET CantPart = CantPart - NumPart WHERE DiaJuliano >= ApGrupoPosible^.FechaIni AND DiaJuliano <= ApGrupoPosible^.FechaFinTERMINA

/***************************************************************************************************************************************************** Función: Restablecer los contadores de personal en capacitación para un centro de trabajo por la desasignación de un participante a un grupo propuesto. Se da por hecho que en la tabla PartDiaCentroTrabajo sólo se encuentran los días hábiles para capacitación. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC RestableceTablaPartDiaCT(ApParticipante,ApGrupoPosible)COMIENZA UPDATE PartDiaCentoTrabajo SET CantPart = CantPart - 1 WHERE CveCT = ApParticipante^.ClaveCentroTrab AND (DiaJuliano >= ApGrupoPosible^.FechaIni AND DiaJuiano <= ApGrupoPosible^.FechaFin)

25

TERMINA

/***************************************************************************************************************************************************** Función: Liberar las asociaciones de un participante que se encuentran inhibidas. Liberar las asociaciones de participantes afectados por lineamientos con la asignación provisional del participante actualmente analizado al grupo indicado con CveGrupo. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC LiberaAsocAfectadas(ApParticipante,ListaParticipantes)COMIENZA LiberaAsocInhibidasParticipante(ApParticipante^.ClaveEmpleado) /* Todas las asociaciones inhibidas del participante se liberan en la tabla dentro AsocParticipantes */ ApGrupoAfectado := ApParticipante^.ListaGruposAfectados MIENTRAS ApGrupoAfectado <> NIL HAZ COMIENZA ApPartAfectado := ApParticipante^.Liga MIENTRAS ApPartAfectado <> NIL AND ApPartAfectado^.ClaveCentroTrab = ApParticipante^.ClaveCentroTrab HAZ COMIENZA SI PuedeLiberarseAsoc(ApParticipante,ApPartAfectado,ApGrupoAfectado^.ClaveGrupo,ListaParticipantes) ENTONCES CambiaStatusDeAsoc(ApPartAfectado^.ClaveEmpleado,ApGrupoAfectados^.ClaveGrupo,'L') SI TieneAsocProvisional(ApPartAfectado^.ClaveEmpleado) ENTONCES CambiaStatusDeAsoc(ApPartAfectado^.ClaveEmpleado,ApGrupoAfectados^.ClaveGrupo,'I') ApPartAfectado := ApPartAfectado^.Liga TERMINA ApGrupoAfectado := ApGrupoAfectado^.Liga TERMINATERMINA

/***************************************************************************************************************************************************** Función: Poner en estado libre las asociaciones inhibidas de un participante. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC LiberaAsocInhibidasParticipante(CveEmpleado)COMIENZA UPDATE AsocParticipantes SET Status = 'L' WHERE CveEmp = CveEmpledo AND Status = 'I'TERMINA

/***************************************************************************************************************************************************** Función: Determinar si un empleado tiene una asociación provisional a un grupo. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/FUNCION TieneAsocProvisional(CveEmpleado)COMIENZA SELECT Status FROM AsocParticipantes WHERE CveEmp = CveEmpleado AND Status = 'P'

TieneAsocProvisional := (sqlca.sqlcode = 0)

26

TERMINA

/***************************************************************************************************************************************************** Función: Eliminar de la tabla AsocParticipantes todos las asociaciones a un grupo propuesto Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC EliminaAsocAGrupo(ClaveGrupo)COMIENZA DELETE FROM AsocParticipantes WHERE ClaveGrupoPosible = ClaveGrupoTERMINA

27

/***************************************************************************************************************************************************** Función: Determinar que una asociación afectada tiene un sólo participante que la afecta. Si existe por lo menos otro participante que la afecta la función devuelve FALSO. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/FUNCION PuedeLiberarseAsoc(ApParticipante,ApPartAfectado,CveGrupoAfectado,ListaParticipantes)COMENZA SELECT ClaveGrupoPosible FROM AsocParticipantes WHERE CveEmp = ApPartAfectado^.ClaveEmpleado AND ClaveGrupoPosible = CveGrupoAfectado AND Status = 'A'

SI sqlca.sqlcode = 0 ENTONCES COMIENZA NingunOtroAfectante := CIERTO OtroAfectante := BuscaCentroDeTrabajo(ApPartAfectado^.ClaveCentroTrab, ListaParticipantes) /* La busqueda regresa una apuntador al primer nodo de la lista de participantes cuya ClaveCentroTrab es igual al centro de trabajo buscado */ MIENTRAS NingunOtroAfectante AND (OtroAfectante <> ApParticipante) HAZ COMIENZA ListaGposAfectados := OtroAfectante^.ListaGruposAfectados MIENTRAS ListaGposAfectados <> NIL AND NingunOtroAfectante HAZ COMIENZA SI ListaGposAfectados^.ClaveGrupo = CveGrupoAfectado ENTONCES NingunOtroAfectante := FALSO ListaGposAfectados := ListaGposAfectados^.Liga TERMINA OtroAfectante := OtroAfectante^.Liga TERMINA PuedeLiberarseAsoc := NingunOtroAfectante TERMINA OTRO PuedeLiberarseAsoc := FALSOTERMINA

/***************************************************************************************************************************************************** Función: Cambia el status de una asociación a un grupo para un participante. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC CambiaStatusDeAsoc(ClaveEmpleado,ClaveGrupo,NvoStatus)COMIENZA UPDATE AsocParticipantes SET Status = NvoStatus WHERE CveEmp = ClaveEmpleado AND ClaveGrupoPosible = ClaveGrupoTERMINA/***************************************************************************************************************************************************** Función: Liberar asociaciones de participantes a grupos cuya FechaIni y FechaFin correspondan con las fechas del grupo parámetro. Fecha de actualización: 14/03/94*****************************************************************************************************************************************************/PROC LiberaAsocPorPtjesLineamientos(ApGrupoPosible,GruposPosibles)COMIENZA PARA Cont := 0 HASTA MAXCUBETAS-1 HAZ /* MAXCUBETAS es 1009 */

28

COMIENZA ApGpoActual := GruposPosibles[Cont] MIENTRAS ApGpoActual <> NIL HAZ COMIENZA SI (ApGpoActual^.FechaIni = ApGrupoPosible^.FechaIni) AND (ApGpoActual^.FechaFin = ApGrupoPosible^.FechaFin) ENTONCES LiberaAsocxPtjeClienteYCT(ApGpoActual^.Clave) ApGpoActual := ApGpoActual^.Liga TERMINA TERMINATERMINANOTA: Considerar los beneficios obtenidos por la aplicación de esta acción en contra del procesamineto que requiere

/***************************************************************************************************************************************************** Función: Liberar las asociaciones con estado 'C' y 'T' para un grupo. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC LiberaAsocxPtjeClienteYCT(CveGrupo)COMIENZA DECLARE CursorParticipantes CURSOR FOR SELECT CveEmp FROM AsocParticipantes WHERE (ClaveGrupoPosible = CveGrupo) AND ((Status = 'T') OR (Status = 'C'))

OPEN CursorParticipantes FETCH CursorParticipantes INTO CvePart

MIENTRAS (sqlca.sqlcode = 0) HAZ COMIENZA SI TieneAsocProvisional(CvePart) ENTONCES CambiaStatusDeAsoc(CvePart,CveGrupo,'I') OTRO CambiaStatusDeAsoc(CvePart,CveGrupo,'L') FETCH CursorParticipantes INTO CvePart TERMINA

CLOSE CursorParticipantesTERMINA

29

/***************************************************************************************************************************************************** Función: Cerrar un grupo cuyo cupo máximo se ha saturado. Si en el plantel en que el grupo actualmente analizado se puede abrir otro grupo entonces solo se cierra el grupo real y al grupo posible se inicializa su contador de participantes a 0. Si en el plantel ya no es posible abrir más grupos, se cierra el grupo real, se elimina al grupo posible y se eliminan todas las asociaciones de participantes vinculados con éste que aun no se han considerado. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC CierraGrupo(PeriodoProyecto,GruposPosibles,VAR ApGrupoPosible,TablaCorrespGrupos,ListaRecursosRequeridos)COMIENZA Elimina(ApGrupoPosible^.Clave,TablaCorrespGrupos) /* Elimina de la tabla de correspondencia entre grupos propuestos y grupos reales al grupo que se saturó. Se busca el nodo correspondiente identificandolo con la clave del grupo propuesto y se elimina de la tabla de hash TablaCorrespGrupos. */

SI PuedeExistirNvoGpo(PeriodoProyecto,ApGrupoPosible,ListaRecursosRequeridos^.ListaInstalRequeridas) ENTONCES ApGrupoPosible^.CantPart := 0 OTRO COMIENZA EliminaAsocAGrupo(ApGrupoPosible^.Clave) /* Se eliminan de la tabla AsocParticipantes todas las ocurrencias de un grupo */ Elimina(ApGrupoPosible^.Clave,GruposPosibles) /* Elimina al grupo posible de la tabla de hash GruposPosibles */ TERMINATERMINA

/***************************************************************************************************************************************************** Función: Verificar si existe por lo menos una posibilidad de abrir un nuevo grupo en la sede del grupo propuesto. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/FUNCION PuedeExistirNvoGpo(PeriodoProyecto,ApGrupoPosible,ListaInstalacionesRequeridas)COMIENZA ExisteReqInstal := CIERTO InstalacionRequerida := ListaInstalacionesRequeridas MIENTRAS InstalacionRequerida <> NIL AND ExisteReqInstal HAZ COMIENZA ExisteReqInstal := BuscaInstalDisponible(PeriodoProyecto,ApGrupoPosible,InstalacionRequerida,PeriodoProyecto) InstalacionRequerida := InstalacionRequerida^.Liga TERMINA PuedeExistirNvoGpo := ExisteReqInstalTERMINA

30

/***************************************************************************************************************************************************** Función: Busca por lo menos una instalación disponible en un plantel y periodo indicados en ApGrupoPosible y del tipo indicado en TipoInstalacion. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/FUNCION BuscaInstalDisponible(PeriodoProyecto,ApGrupoPosible,ApInstalReq)COMIENZA GeneraListaInventarioInstal(ApInstalReq^.CveTipInstalacion,ApGrupoPosible^.CvePlantel,ListaInventarioInstal) /* ListaInventarioInstal es una lista ligada con claves del inventario de instalaciones */ Instalacion := ListaInventarioInstal ExisteUnaDisponible := FALSO RegFechas.FechaIni := ApGrupoPosible^.FechaIni RegFechas.FechaFin := ApGrupoPosible^.FechaFin MIENTRAS Instalacion <> NIL AND NO(ExisteUnaDisponible) HAZ COMIENZA ExisteUnaDisponible := EsDisponibleInstal(PeriodoProyecto,ApInstalReq,Instalacion^.Clave,RegFechas) Instalacion := Instalacion^.Liga TERMINA Libera(ListaInventarioInstal) /* Libera el espacio de la lista ligada ListaInventarioInstal */ BuscaInstalDisponible := ExisteUnaDisponibleTERMINA

/***************************************************************************************************************************************************** Función: Eliminar de la ListaParticipantes a todos aquellos a los que se han eliminado todas sus posibilidades de asignación a un grupo para evitar que cuando se regrese al inicio de la lista se consideren inútilmente. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC DepuraListaParticipantes(VAR ListaParticipantes,VAR SolicNoProgramadas)COMIENZA Participante := ListaParticipantes MIENTRAS Participante <> NIL HAZ SI TieneTodasAsocCanceladas(Participante^.ClaveEmpleado) ENTONCES COMIENZA SolicNoProgramadas := SolicNoProgramadas + 1 Aux := Participante Participante := Participante^.Liga Elimina(Aux^.ClaveEmpleado,ListaParticipantes) /* Elimina un nodo de la lista ligada ListaParticipantes */ TERMINA OTRO Participante := Participante^.LigaTERMINA

31

/***************************************************************************************************************************************************** Función: Devuelve verdadero si todas las asociaciones de un participante se encuentran canceladas. Este caso se da cuando el participante ya no se encuentra en la tabla de AsocParticipantes. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/FUNCION TieneTodasAsocCanceladas(CveParticipante)COMIENZA SELECT CveEmp FROM AsocParticipantes WHERE CveEmp = CveParticipante

TieneTodasAsocCanceladas := NO(sqlca.sqlcode = 0)TERMINA

/***************************************************************************************************************************************************** Función: Liberar e inicializar las listas ligadas, tablas de hash y bases se datos que deban estar limpias para la programación de un nuevo curso. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC TerminaProcesoCurso(GruposPosibles, TablaCorrespGrupos)COMIENZA Libera(GruposPosibles) /* Liberación de memoria de una tabla de hash */ Libera(TablaCorrespGrupos) /* Liberación de memoria de una tabla de hash */ BorrarTablaAsocParticipantes() /* Limpia la base de datos AsocParticipantes */TERMINA

/***************************************************************************************************************************************************** Función: Verificar si es conveniente utilizar nuevamente el modelo matemático para programar a los participantes del remanente. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/FUNCION AplicarMismoMetodo(TotalSolicitudes,SolicProgramadas,SolicNoProgamadas,VAR NumVecesAplicacion, VAR NumRerprogramaciones)COMIENZA PorcentajePermitido := Parametro('PtjeRemPart') PorcentajeReal := (100 * (TotalSolicitudes - SolicProgramadas - SolicNoProgamadas)) / TotalSolicitudes NumVecesAplicacion := NumVecesAplicacion - 1 NumRerprogramaciones := NumRerprogramaciones + 1 AplicarMismoMetodo := (PorcentajeReal > PorcentajePermitido AND (NumVecesAplicacion + 1) > 0 )TERMINANota para control de división por cero. TotalSolicitudes es el tamaño de la lista ligada de los participantes que solicitan un curso, solo si la listafuera nula esta variable podria tener un valor cero sin embargo en tal caso el programa no podria llegar a este procedimiento.

32

/***************************************************************************************************************************************************** Función: Analizar a los grupos posibles que tienen asignaciones provisionales muy proximas al mínimo de manera que mantengan como estan y se permita distribuir a los demás participantes en éstos. Para los grupos posibles que tengan muy pocas asociaciones provisionales se les eliminan para que se distribuyan. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC DepuraAsociaciones(GruposPosibles,ApCurso,ListaParticipantes)COMIENZA DECLARE CursorGrupos CURSOR FOR SELECT UNIQUE ClaveGrupoPosible FROM AsocParticipantes WHERE Status = 'P' ORDER BY ClaveGrupoPosible

OPEN CursorGrupos FETCH CursorGrupos INTO CveGrupo

MIENTRAS (sqlca.sqlcode = 0) HAZ COMIENZA SI NO(CumplePtjeMinPart(ApCurso,CveGrupo,CantPart)) ENTONCES LiberaGrupo(CveGrupo,CantPart,ListaParticipantes,GruposPosibles) FETCH CursorGrupos INTO CveGrupo TERMINA CLOSE CursorGruposTERMINA

/***************************************************************************************************************************************************** Función: Verificar si un grupo tiene asociados provisionalmente un porcentaje aceptado de participantes. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/FUNCION CumplePtjeMinPart(ApCurso,CveGrupo,VAR CantPart)COMIENZA SELECT COUNT(*) INTO CantPart FROM AsocParticipantes WHERE ClaveGrupoPosible = CveGrupo AND Status = 'P'

PtjePart := 100 * CantPart / ApCurso^.MinParticipantes PtjePermitido := Parametro('PtjeMinCur') CumplePtjeMinPart := (PtjePart >= PtjePermitido)TERMINANota para division por cero. ApCurso^.MinParticipantes no puede ser cero a menos que los datos en la base de datos esten mal. Un grupo no puede,lógicamente tener un mínimo de participantes igual a cero esto significa que aunque el grupo este vacio puede permanecer abierto.

33

/***************************************************************************************************************************************************** Función: Liberar todas las asociaciones provisionales a un grupo liberando los respectivos contadores de personal en capacitación por centro de trabajo y para el cliente. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC LiberaGrupo(CveGrupo,CantPart,ListaParticipantes,GruposPosibles)COMIENZA ApGrupoPosible := Busca(CveGrupo,GruposPosibles) /* Busca un grupo en la tabla de hash GruposPosibles */ RestableceTablaPartDiaCliente(ApGrupoPosible,CantPart) DECLARE CursorParticipantes CURSOR FOR SELECT CveEmp FROM AsocParticipantes WHERE ClaveGrupoPosible = CveGrupo AND Status = 'P'

OPEN CursorParticipantes FETCH CursorParticipantes INTO CvePart

MIENTRAS (sqlca.sqlcode = 0) HAZ COMIENZA ApParticipante := BuscaParticipante(CvePart,ListaParticipantes) /* Localiza al participante dentro de la ListaParticipantes. Es una localización dentro de una lista ligada. Devuelve el apuntador al nodo donde Clave = CvePart */ RestableceTablaPartDiaCT(ApParticipante,ApGrupoPosible) SI Parametro('MenorCatAnt') = 'NO' ENTONCES COMIENZA LiberaAsocAfectadas(ApParticipante,ListaParticipantes) Libera(ApParticipante^.ListaGruposAfectados) TERMINA FETCH CursorParticipantes INTO CvePart TERMINA CLOSE CursorParticipantes

LiberaAsocPorPtjesLineamientos(ApGrupoPosible,GruposPosibles) /* Libera las asociaciones inhibidas por saturación de porcentajes en centro de trabajo o cliente */ EliminaAsocProvAGrupo(CveGrupo) /* Elimina de la tabla de AsocParticipantes las asociaciones provisionales al grupo */ ApGrupoPosible^.CantPart := 0TERMINA

/*****************************************************************************************************************************************************Función: Elimina las asociaciones provisionales a un grupo de la tabla AsocParticipantes.

Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC EliminaAsocProvAGrupo(ClaveGrupo)COMIENZA DELETE FROM AsocParticipantes WHERE (ClaveGrupoPosible = ClaveGrupo) AND (Status = 'P')TERMINA

34

/*****************************************************************************************************************************************************Elige el grupo de costo mínimo para un participante. En caso de que todas las asociaciones del participante estén inhibidas o afectadasel apuntador al grupo posible sera NULL.Fecha de actualización: 14/03/94*****************************************************************************************************************************************************/PROC EligeAsigPartCostoMin(ApPartActual,GruposPosibles,VAR ApGrupoPosible)COMIENZA CostoMin := INFINITO $DECLARE CursorAsocionesPart CURSOR FOR SELECT * FROM AsocParticipantes WHERE CveEmp = ApPartActual^.ClaveEmpledo AND Status = "L" $OPEN CursorAsociacionesPart $FETCH CursorAsociacionesPart INTO $RegAsociacion SI sqlca.sqlcode = 0 ENTONCES COMIENZA MIENTRAS (sqlca.sqlcode = 0) HAZ COMIENZA SI RegAsociacion.Costo < CostoMin ENTONCES COMIENZA CostoMin := RegAsociacion.Costo CveGrupo := RegAsociacion.ClaveGrupoPosible TERMINA $FETCH CursorAsociacionesPart INTO $RegAsociacion TERMINA ApGrupoPosible := Busca(CveGrupo,GruposPosibles) TERMINA OTRO ApGrupoPosible := NULL $CLOSE CursorAsociacionesPartTERMINA

/***************************************************************************************************************************************************** Función: Determinar si la asociación de un participante a un grupo se encuentra en estado libre. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/FUNCION EsLibreAsoc(CveEmpleado,CveGrupo)COMIENZA SELECT Status INTO Estado FROM AsocParticipantes WHERE CveEmp = CveEmpleado AND ClaveGrupoPosible = CveGrupo SI sqlca.sclcode = 0 ENTONCES EsLibreAsoc := (Estado = 'L') OTRO EsLibreAsoc := FALSOTERMINA

35

*****************************************************************************************************************************************************Se verifican las tablas de contadores de personal en capacitación por dia para el total del cliente y los contadores por centro de trabajo. Lascantidades para cada dia se comparan con los porcentajes permitidos para cada dia del periodo comprendido para la impartición del curso el grupoindicado por RegAsigPartCostoMinFecha de actualización: 14/03/94****************************************************************************************************************************************/FUNCION CumplePorcentajesLineamientos(ApCurso,ApParticipante,ApGrupoPosible)COMIENZA Cumple := CIERTO SI NO(CumplePtjeLineamientoxCT(ApCurso,ApParticipante,ApGrupoPosible) ENTONCES COMIENZA

AfectaAsocxPtjeLineamientoCT(ApParticipante,ApGrupoPosible) /* Todas las asociaciones de los part. a ese Centro de trabajo quedan afectadas constatus ´T´ */

Cumple := FALSO TERMINA SI NO(CumplePtjeLineamientoCliente(ApCurso,ApParticipante,ApGrupoPosible) ENTONCES COMIENZA AfectaAsocxPtjeLineamCliente(ApParticipante,ApGrupoPosible) /* Inhibe la asoc. porque el cliente está saturado en capac. */ Cumple := FALSO TERMINA CumplePorcentajesLineamientos := CumpleTERMINANOTA: Las llamadas a las funciones subrayadas podrian desaparecer

/***************************************************************************************************************************************************** Función: Inhibir por lineamientos de porcentaje para un centro de trabajo las asociaciones a un grupo. El status para inhibición por la saturación del porcentaje para un centro de trabajo es 'T'.Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC AfectaAsocxPtjeLineamientoCT(ApPartActual,ApGrupo)COMIENZA ApParticipante := ApPartActual MIENTRAS ApParticipante <> NIL AND ApParticipante^.ClaveCentroTrab = ApPartActual^.ClaveCentroTrab HAZ COMIENZA SI EsLibreAsoc(ApParticipante^.ClaveEmpleado,ApGrupo^.Clave) ENTONCES CambiaStatusDeAsoc(ApParticipante^.ClaveEmpleado,ApGrupo^.Clave,'T') ApParticipante := ApParticipante^.Liga TERMINATERMINA

36

/***************************************************************************************************************************************************** Función: Inhibir por lineamientos de porcentaje para el cliente las asociaciones a un grupo.El status para inhibición por la saturación delporcentaje para el cliente es 'C'. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC AfectaAsocxPtjeLineamCliente(ApPartActual,ApGrupo)COMIENZA ApParticipante := ApPartActual MIENTRAS ApParticipante <> NIL HAZ COMIENZA SI EsLibreAsoc(ApParticipante^.ClaveEmpleado,ApGrupo^.Clave) ENTONCES CambiaStatusDeAsoc(ApParticipante^.ClaveEmpleado,ApGrupo^.Clave,'C') ApParticipante := ApParticipante^.Liga TERMINATERMINA

/*****************************************************************************************************************************************************Se verifican las tablas de contadores de personal en capacitación por dia para el total del cliente y los contadores por centro de trabajo. Lascantidades para cada dia se comparan con los porcentajes permitidos para cada dia del periodo comprendido para la impartición del curso. Se consideraque la tabla PartDiaCentroTrabajo tiene almacenados sólo los días hábiles, por lo cual es necesario que al definir el calendario civil, se eliminenlos días no habiles de esta tabla y se inserten cuando un día festivo se cambie a hábilNOTA:El valor devuelto por las llamadas Parametro(´PtjeExcDiaCT´), Parametro(´PtjePartCT´) y Parametro(´PtjeCobLinCT´) se manejan como númeroFecha de actualización: 09/03/94****************************************************************************************************************************************/FUNCION CumplePtjeLineamientoxCT(ApCurso,ApParticipante,ApGrupo)COMIENZA SELECT COUNT(*) /* Se cuenta cuántos empleados hay en un Centro de Trabajo */ INTO CantTotalPartxCT FROM RecHumanos WHERE CveCentroTrab = ApParticipante^.ClaveCentroTrab

$DECLARE CursorDiasxCT CURSOR FOR SELECT * FROM PartDiaCentroTrabajo WHERE DiaJuliano BETWEEN ApGrupo^.FechaIni AND ApGrupo^.FechaFin AND CveCT = ApParticipante^.ClaveCentroTrab $OPEN CursorDiasxCT $FETCH CursorDiasxCT INTO $RegPartDiasxCT PorcentajePermitido := Parametro(´PtjePartCT´) CantDiasCorrectos := 0 Exito := CIERTO MIENTRAS (sqlca.sqlcode = 0) AND (Exito) HAZ COMIENZA SI CumplePorcentajeDia(RegPartDiasxCT.CantPart,CantTotalPartxCT,PorcentajePermitido) ENTONCES CantDiasCorrectos := CantDiasCorrectos + 1 OTRO SI NO(CumplePtjePermitidoDeExceso(RegPartDiasxCT.CantPart,CantTotalPartxCT,PorcentajePermitido,Parametro(´PtjeExcDiaCT´)) ENTONCES Exito := FALSO $FETCH CursorDiasxCT INTO $RegPartDiasxCT TERMINA $CLOSE CursorDiasxCT

37

SI Exito ENTONCES CumplePtjeLineamientoxCT := CumplePtjeCobertura(CantDiasCorrectos,ApCurso,Parametro(´PtjeCobLinCT´)) OTRO CumplePtjeLineamientoxCT := FALSOTERMINA

/*****************************************************************************************************************************************************Revisa si en el día en el que se está revisando (en RegPartDiasxCT.DiaJuliano) se excede en cuanto al lineamiento que dice que no debe asistir más deun cierto porcentaje de un centro de trabajo simultáneamente.Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/FUNCION CumplePorcentajeDia(CantPart,CantTotalPart,PorcentajePermitido)COMIENZA PorcentajeReal := CantPart * 100 / CantTotalPart CumplePorcentaje := PorcentajeReal <= PorcentajePermitidoTERMINA

nota para division por cero. CantTotalPart toma los valores de la cantidad de personal en un centro de trabajo o la cantidad total de empleado deTelmex. Estos valores no pueden ser cero, a menos que haya un error en la lectura de la base de datos cuando se leen estos datos.

/****************************************************************************************************************************************Cuando se excede la cantidad de participantes permitidos para un centro de trabajo, se revisa que el exceso no sea mayor que un cierto porcentaje, queel mismo usuario marca dentro de los parámetros.Fecha de actualización: 09/03/94****************************************************************************************************************************************/FUNCION CumplePtjePermitidoDeExceso(CantPart,CantTotalPart,PorcentajePermitido,PorcentajePermitidoExceso)COMIENZA TotalPartPermitidos := CantTotalPart * PorcentajePermitido / 100 CantPartExcesoPermitidos := TotalPartPermitidos * PorcentajePermitidoExceso / 100 CumplePorcentaje := (CantPart - TotalPartPermitidos) <= CantPartExcesoPermitidosTERMINA

38

/****************************************************************************************************************************************Revisa si la cantidad de días en los que no se cubrió el lineamiento está dentro del rango permitido por el usuarioFecha de actualización: 09/03/94****************************************************************************************************************************************/FUNCION CumplePtjeCobertura(CantDiasCorrectos,ApCurso,PorcentajePermitido)COMIENZA CantDiasIncorrectos := ApCurso^.Duracion - CantDiasCorrectos PorcentajeEjercido := CantDiasIncorrectos * 100 / ApCurso^.Duracion CumplePtjeCobertura := PorcentajeEjercido <= PorcentajePermitidoTERMINA/****************************************************************************************************************************************************Inhibe todas las demás asociaciones posibles de un participante a otros grupos posibles, debido a que ya fue asignado provisionalmente a un grupoFecha de actualización: 09/03/94****************************************************************************************************************************************************/PROC InhibeOtrasPosibDelPart(ClaveEmpleado)COMIENZA UPDATE AsocParticipantes SET Status = ´I´ WHERE CveEmp = ClaveEmpleado AND Status = ´L´TERMINA

/****************************************************************************************************************************************Se verifican las tablas de contadores de personal en capacitación por dia para el total del cliente y los contadores para todo Telmex. Las cantidadespara cada dia se comparan con los porcentajes permitidos para cada dia del periodo comprendido para la impartición del curso.Se considera el total, sumando sindcalizados y confianza.Se considera que la tabla PartDiaCliente tiene almacenados sólo los días hábiles, por lo cual es necesario que al definir el calendario civil, seeliminen los días no habiles de esta tabla y se inserten cuando un día festivo se cambie a hábilNOTAS: El valor devuelto por las llamadas Parametro(´PtjeExcDiaCl´), Parametro(´PtjePartCl´) y Parametro (´PtjeCobLinCl´) se manejan como número La Tabla de PartDiaCliente deberá contener consolidada la información de todos los campusFecha de actualización: 09/03/94****************************************************************************************************************************************/FUNCION CumplePtjeLineamientoCliente(ApCurso,ApParticipante,ApGrupo)COMIENZA SELECT COUNT(*) /* Se cuenta cuántos empleados tiene el cliente */ INTO CantTotalPartCliente FROM RecHumanos

$DECLARE CursorDiasxCT CURSOR FOR SELECT * FROM PartDiaCliente WHERE DiaJuliano BETWEEN ApGrupo^.FechaIni AND ApGrupo^.FechaFin

$OPEN CursorDiasCliente $FETCH CursorDiasCliente INTO $RegPartDiasCliente PorcentajePermitido := Parametro(´PtjePartCl´) CantDiasCorrectos := 0 Exito := CIERTO MIENTRAS (sqlca.sqlcode = 0) AND (Exito) HAZ COMIENZA SI CumplePorcentajeDia(RegPartDiasCliente.CantPart,CantTotalPartCliente,PorcentajePermitido) ENTONCES

39

CantDiasCorrectos := CantDiasCorrectos + 1 OTRO SI NO(CumplePtjePermitidoDeExceso(RegPartDiasCliente.CantPart,CantTotalPartCliente,PorcentajePermitido,Parametro(´PtjeExcDiaCl´)) ENTONCES Exito := FALSO $FETCH CursorDiasCliente INTO $RegPartDiasCliente TERMINA $CLOSE CursorDiasCliente SI Exito ENTONCES CumplePtjeLineamientoCliente := CumplePtjeCobertura(CantDiasCorrectos,ApCurso,Parametro (´PtjeCobLinCl´)) OTRO CumplePtjeLineamientoCliente := FALSOTERMINA

/****************************************************************************************************************************************************Después de elegir la asociación del participante de costo mínimo, hace la asignación provisional.Nota: Grupos Posibles es una tabla de hash y los otros dos parámetros son apuntadores a registros de listas ligadasFecha de actualización: 09/03/94****************************************************************************************************************************************************/PROC AsignaPartAGrupo(ApPartActual,GruposPosibles,ApGrupo)COMIENZA CambiaStatusDeAsoc(ApPartActual^.ClaveEmpleado,ApGrupo^.Clave,'P') /* Cambia el status de la asociación a provisional */ ApGrupo^.CantPart := ApGrupo^.CantPart + 1 InhibeOtrasPosibDelPart(ApPartActual^.ClaveEmpleado) IF Parametro(´MenorCatAnt´) = ´NO´ ENTONCES /* No se admite que se capacite primero alguén con < categ. y antig. */ InhibePosibOtrosPart(ApPartActual,GruposPosibles,ApGrupo) /* Inhibe posibles asociaciones de otros part. de menor categoría y antigüedad en fechas anteriores */ IncrementaPartxCT(ApPartActual^.ClaveCentroTrab,ApGrupo^.FechaIni,ApGrupo^.FechaFin) IncrementaPartxCliente(ApGrupo^.FechaIni,ApGrupo^.FechaFin)TERMINA

/****************************************************************************************************************************************************Crea una lista de grupos que el participante afecta para otros empleados del mismo C.T. con menor categoría y antigüedad. Esta lista de gruposafectados, contiene las claves de los grupos con fechas anteriores al grupo en el que está siendo asignado el empleado actual y la lista cuelga delpropio registro del participante actual de la lista ligada de partcipantes, lo cual quiere decir, que en tal lista, cada participante tendrá su propialista de grupos que afecta. Además inhibe las asociaciones de los otros participantes menores del mismo centro de trabajo a esos grupos afectados.Fecha de actualización: 09/03/94****************************************************************************************************************************************************/PROC InhibePosibOtrosPart(ApPartActual,GruposPosibles,ApGrupo)COMIENZA $DECLARE CursorGrupos CURSOR FOR SELECT ClaveGrupoPosible FROM AsocParticipantes WHERE CveEmp = ApPartActual^.ClaveEmpleado AND Status = 'I'

$OPEN CursorGrupos $FETCH CursorGrupos INTO CveGrupo

40

MIENTRAS (sqlca.sqlcode = 0) HAZ COMIENZA SI TieneFechaAnterior(CveGrupo,ApGrupo^.FechaIni,GruposPosibles) ENTONCES COMIENZA Inserta(CveGrupo,ApPartActual^.ListaGruposAfectados) /* Inserta en una lista ligada */ AfectaParticipantes(ApPartActual,CveGrupo) TERMINA $FETCH CursorGrupos INTO CveGrupo TERMINA $CLOSE CursorGruposTERMINA

/***************************************************************************************************************************************************** Función: Afecta la asociación a un grupo a los participantes de menor categoría y antigüedad que el participante actual. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC AfectaParticipantes(ApPartActual,CveGrupo)COMIENZA ApPartAfectado := ApPartActual^.Liga MIENTRAS (ApPartAfectado <> NIL) AND (ApPartAfectado^.ClaveCentroTrab = ApPartActual^.ClaveCentroTrab) HAZ COMIENZA AfectaAsociacion(ApPartAfectado^.ClaveEmpleado,CveGrupo) ApPartAfectado := ApPartAfectado^.Liga TERMINATERMINA

/***************************************************************************************************************************************************** Función: Afecta la asociación de un participante a un grupo siempre y cuando el estado actual de ésta no sea provisional. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC AfectaAsociacion(ClaveEmpleado,CveGrupo)COMIENZA UPDATE AsocParticipantes SET Status = 'A' WHERE CveEmp = ClaveEmpleado AND ClaveGrupoPosible = CveGrupo AND Status <> 'P'TERMINA/****************************************************************************************************************************************************Revisa si el curso que se extrajo del cursor para el participante actual, tiene un fecha anterior que pudiera afectar a participantes con menorcategoría y antigüedad.Fecha de actualización: 09/03/94****************************************************************************************************************************************************/FUNCION TieneFechaAnterior(ClaveGrupoPosible,FechaIniGrupoActual,GruposPosibles)COMIENZA Grupo := Busca(ClaveGrupoPosible,GruposPosibles) /* Func. de localizar en un TDA Tabla de Dispersión (Hash). Regresa un apunt.*/ SI Grupo != NULL ENTONCES TieneFechaAnterior := Grupo^.FechaIni < FechaIniGrupoActual OTRO TieneFechaAnterior := FALSOTERMINA

41

/****************************************************************************************************************************************************Se incrementa la cantidad de participantes en el Centro de Trabajo en cuestión en cada uno de los dias que comprende el periodoFecha de actualización: 09/03/94****************************************************************************************************************************************************/FUNCION IncrementaPartxCT(ClaveCentroTrab,FechaIni,FechaFin)COMIENZA UPDATE PartDiaCentroTrab SET CantPart = CantPart + 1 WHERE CveCT = ClaveCentroTrab AND DiaJuliano BETWEEN FechaIni AND FechaFinTERMINA

/****************************************************************************************************************************************************Se incrementa la cantidad de participantes del cliente en cada uno de los dias que comprende el periodoFecha de actualización: 09/03/94****************************************************************************************************************************************************/FUNCION IncrementaPartxCliente(FechaIni,FechaFin)COMIENZA UPDATE PartDiaCliente SET CantPart = CantPart + 1 WHERE DiaJuliano BETWEEN FechaIni AND FechaFinTERMINA

42

/****************************************************************************************************************************************NOTAS: Al definir un grupo como definitivo se deben efectuar las siguientes acciones:

### Todos los participantes hasta este punto asignados al grupo se deben asignar definitivamente al grupo.### Las asociaciones inhibidas por las asignaciones definitivas se deben cancelar.### Se debe manifestar la indisponibilidad para las fechas asociadas al curso a los participantes inscritos en él### Se debe manifestar la indisponibilidad de instalaciones, equipos e instructores en las fechas y horarios asignados al grupo### El grupo se debe incluir el programa de cursos junto con todos sus participantes hasta ahora inscritos y recursos asignados.### El estado del grupo toma el valor definitivo

Se cambian los status provisional a definitivo e inserta el grupo y los recursos en las tablas definitivas del programa, actualizando además,la disponibilidad de todos ellos.Fecha de actualización: 14/03/94****************************************************************************************************************************************/PROC DefinirGrupoDefinitivo(VAR ListaParticipantes,ApGrupo,ApCurso,VAR ListaRecursos,ListaRecursosRequeridos,TablaCorrespGrupos,Proyecto, TipoEmp)COMIENZA CreaGrupoDefinitivo(ListaRecursos.Instructor.FechaIni,ListaRecursos.Instructor.FechaFin, ListaRecursos.Instructor.HoraIni, ListaRecursos.Instructor.HoraFin,ApCurso^.Codigo,TablaCorrespGrupos,ApCorrespGrupo,Proyecto,TipoEmp) AsignaPartsAGrupoDefinitivo(ListaParticipantes,ApCorrespGrupo,ApGrupo) /* Inserta en el grupo definitivo a los participantes del grupo posible y los elimina de AsocParticipantes. Además actualiza la indisp. de los participantes.*/ AsignaRecursosAGrupoDefinitivo(ApCorrespGrupo^.ClaveGrupoDefinitivo,ListaRecursos,ListaRecursosRequeridos.InstructoresPosibles.ListaProveedores, ApCurso^.Codigo) /* Inserta en el grupo definitivo las instalaciones, equipos e instructor del grupo posible. Además actualiza su indisp. */ Libera(ListaRecursos) /* Libera la memoria de la lista de recursos */TERMINA

/****************************************************************************************************************************************Se inserta un grupo en la tabla de grupos, la cual contiene los grupos definitivos. Además, debe crear un nodo en TablaCorrespGrupos, que tiene laclave del grupo posible y la del definitivo.Fecha de actualización: 09/03/94****************************************************************************************************************************************/PROC CreaGrupoDefinitivo(FechaIni,FechaFin,HoraIni,HoraFin,CodigoCurso,TablaCorrespGrupos,VAR ApCorrespGrupo,Proyecto,TipoEmp)COMIENZA LeeFolio(´GruposDeCurso´,ClaveGrupo)

INSERT INTO GruposDeCurso VALUES (ClaveGrupo, 1, TipoEmp, FechaIni, FechaFin, HoraIni, HoraFin , CodigoCurso, Proyecto) Inserta(ClaveGrupo,ApGrupo^.Clave,TablaCorrespGrupos) ApCorrespGrupo := Busca(ApGrupo^.Clave,TablaCorrespGrupos) /* Esta función sólo se invoca en el caso de que el inserta no regrese el apuntador al nodo que insertó. Es una busqueda en una tabla de hash */ ActualizaFolio(ClaveGrupo+1,´GruposDeCurso´)TERMINA

/****************************************************************************************************************************************Inserta en el grupo definitivo a los participantes del grupo posible y los elimina de AsocParticipantes. Además actualiza la indisp. de losparticipantes y elimina a los participantes de la lista de participantes

43

Fecha de actualización: 09/03/94***************************************************************************************************************************************/PROC AsignaPartsAGrupoDefinitivo(VAR ListaParticipantes,ApCorrespGrupo,ApGrupoPosible)COMIENZA $DECLARE CursorAsocPart CURSOR FOR SELECT CveEmp FROM AsocParticipantes WHERE ClaveGrupoPosible = ApCorrespGrupo^.ClaveGrupoPosible AND Status = ´P´

$OPEN CursorAsocPart $FETCH CursorAsocPart INTO CveEmpleado

MIENTRAS (sqlca.sqlcode = 0) HAZ COMIENZA ApPart := Busca(CveEmpleado,ListaParticipantes) /* Busqueda en una lista ligada */ AsignaParticipante(CveEmpleado,ApCorrespGrupo^.ClaveGrupoDefinitivo) /* Asigna al RH al grupo definitivo */ ActualizaIndispPart(ApCorrespGrupo^.ClaveGrupoDefinitivo,CveEmpleado,ApGrupoPosible^.FechaIni,ApGrupoPosible^.FechaFin) EliminaAsocDelPart(CveEmpleado) IF Parametro(´MenorCatAnt´) = ´NO´ ENTONCES /* No se admite que se capacite primero alguén con < categ. y antig. */ EliminaAsocAfectadas(ApPart) Elimina(ApPart^.ClaveEmpleado,ListaParticipantes) /* Elimina el nodo de la lista ligada. Al eliminar al participante, se debe eliminar su lista de grupos afectados */ $FETCH CursorAsocPart INTO CveEmpleado TERMINA $CLOSE CursorAsocPartTERMINA

/****************************************************************************************************************************************Inserta en el grupo definitivo al partcipante actual.Fecha de actualización: 09/03/94****************************************************************************************************************************************/PROC AsignaParticipante(CveEmp,ClaveGrupo)COMIENZA INSERT INTO GruposRH VALUES (CveEmp,ClaveGrupo,1)TERMINA

44

/****************************************************************************************************************************************Inserta los periodos en los que el participante queda indisponible por que quedó asignado al grupo definitivamenteFecha de actualización: 09/03/94****************************************************************************************************************************************/PROC ActualizaIndispPart(CveGrupo,CveEmp,FechaIni,FechaFin)COMIENZA Motivo := "Capacitacion, grupo " + CveGrupo /* Convertir la clave del grupo a cadena y concatenarlo en Motivo */

INSERT INTO PerIndipRH VALUES (CveEmp,FechaIni,FechaFin,Motivo)TERMINA

/****************************************************************************************************************************************Elimina todas las asociaciones del participante sin importar el status que tengan, debido a que ya quedó asignado a un grupo definitivo.Fecha de actualización: 09/03/94****************************************************************************************************************************************/PROC EliminaAsocDelPart(CveParticipante)COMIENZA DELETE FROM AsocParticipante WHERE CveEmp = CveParticipanteTERMINA

/****************************************************************************************************************************************Elimina todas las asociaciones de los participantes de menor categoría y antigüedad del mismo centro de trabajo, a grupos de fecha anterior al actual,debido a que ya no podrán ir a esos, si el usuario obliga a que el lineamiento se respeteFecha de actualización: 09/03/94****************************************************************************************************************************************/PROC EliminaAsocAfectadas(ApParticipante)COMIENZA ApGrupoAfectado := ApParticipante^.ListaGruposAfectados MIENTRAS ApGrupoAfectado <> NIL HAZ COMIENZA ApPartAfectado := ApParticipante^.Liga MIENTRAS ApPartAfectado <> NIL AND ApPartAfectado^.ClaveCentroTrab = ApParticipante^.ClaveCentroTrab HAZ COMIENZA EliminaAsociacionAfectada(ApPartAfectado^.ClaveEmpleado,ApGrupoAfectado^.ClaveGrupo) ApPartAfectado := ApPartAfectado^.Liga TERMINA ApGrupoAfectado := ApGrupoAfectado^.Liga TERMINATERMINA

45

/****************************************************************************************************************************************Elimina la asociación del participante que se afectó por el lineamiento de que primero deben ir los de mayor categoría y antigüedad.Fecha de actualización: 09/03/94****************************************************************************************************************************************/PROC EliminaAsociaciónAfectada(ClaveEmpleado,CveGrupo)COMIENZA DELETE FROM AsocParticipante WHERE CveEmp = ClaveEmpleado AND ClaveGrupoPosible = CveGrupo AND Status = 'A'TERMINA

/****************************************************************************************************************************************Inserta en el grupo definitivo las instalaciones, equipos e instructor del grupo posible . Además actualiza su indisponibilidadFecha de actualización: 14/03/94****************************************************************************************************************************************/PROC AsignaRecursosAGrupoDefinitivo(ClaveGrupo,ListaRecursos,ListaProvPosibles,CodigoCurso)COMIENZA AsignaInstructor(ListaRecursos^.Instructor,ClaveGrupo,ListaProvPosibles,CodigoCurso) AsignaInstalaciones(ListaRecursos^.ListaInstalaciones,ClaveGrupo) AsignaEquipos(ListaRecurso^.ListaEquipos,ClaveGrupo)TERMINA

/***************************************************************************************************************************************************** Función: Asignar un instructor definitivamente a un grupo y actualizar los periodos de indisponibilidad de éste. Fecha de actualización: 14/03/94*****************************************************************************************************************************************************/PROC AsignaInstructor(Instructor,ClaveGrupo,ListaProvPosibles,CodigoCurso)COMIENZA SI (Instructor.CveTipProced = 1 OR Instructor.CveTipProced = 2) ENTONCES AsignacionInstructor(Instructor,ClaveGrupo) OTRO AsignaProveedor(Instructor,ClaveGrupo,ListaProvPosibles,CveCurso)TERMINA

46

/***************************************************************************************************************************************************** Función: Asignar un proveedor a un grupo y actualizar los periodos de indisponibilidad de éste. NOTA: Como un proveedor puede tener varios grupos asignados en un mismo periodo como se debe manifestar ésto. Fecha de actualización: 14/03/94*****************************************************************************************************************************************************/PROC AsignaProveedor(Instructor,ClaveGrupo, ListaProveedores, CodigoCurso)COMIENZA LeeFolio(´PerIndispProv´, Clave)

INSERT INTO ProveedorGrupos (CveGrupo,CveProveedor,CveEstCap,FechaIni,FechaFin,HoraIni,HoraFin) VALUES (ClaveGrupo,Instructor.Clave,1,Instructor.FechaIni,Instructor.FechaFin,Instructor.HoraIni,Instructor.HoraFin)

Motivo := "Impartición de capacitacion, grupo " + ClaveGrupo /* Convertir la clave del grupo a cadena y concatenarlo en Motivo */

INSERT INTO PerIndispProv VALUES (Clave, Instructor.Clave, CodigoCurso, Instructor^.FechaIni, Instructor^.FechaFin, Instructor^.HoraIni, Instructor^.HoraFin, Motivo) ActualizaFolio(Clave + 1,´PerIndispProv´)

ApProveedor := Busca(Instructor.Clave,ListaProveedores) Inserta(Instructor.FechaIni, Instructor.FechaFin, ApProveedor^.ListaPerIndisp)TERMINA

/***************************************************************************************************************************************************** Función: Asignar un instructor a un grupo y actualizar los periodos de indisponibilidad de éste. Fecha de actualización: 14/03/94*****************************************************************************************************************************************************/PROC AsignacionInstructor(Instructor,ClaveGrupo)COMIENZA INSERT INTO InstructorGrupos VALUES (Instructor.Clave,ClaveGrupo,Instructor^.FechaIni,Instructor^.FechaFin,Instructor.HoraIni,Instructor.HoraFin)

Motivo := "Impartición de capacitacion, grupo " + ClaveGrupo /* Convertir la clave del grupo a cadena y concatenarlo en Motivo */

INSERT INTO PerIndispInstr VALUES (Instructor.Clave,Instructor^.FechaIni,Instructor^.FechaFin, Motivo)TERMINA

/***************************************************************************************************************************************************** Función: Asignar instalaciones a un grupo y actualizar los periodos de indisponibilidad de las instalaciones asignadas. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC AsignaInstalaciones(ListaInstalaciones,ClaveGrupo)COMIENZA Motivo := "Ocupada para capacitacion, grupo" + ClaveGrupo /* Convertir la clave del grupo a cadena y concatenarlo en Motivo */ Instalacion := ListaInstalaciones MIENTRAS Instalacion <> NIL HAZ COMIENZA INSERT INTO GruposInstaReal VALUES (ClaveGrupo,Instalacion^.Clave,Instalacion^.FechaIni,Instalacion^.FechaFin,Instalacion^.HoraIni,Instalacion^.HoraFin)

47

INSERT INTO PerIndispInstal VALUES (Instalacion^.Clave,Instalacion^.FechaIni,Instalacion^.HoraIni,Instalacion^.FechaFin,Instalacion^.HoraFin,Motivo) Instalacion := Instalacion^.Liga TERMINATERMINA

/***************************************************************************************************************************************************** Función: Asignar equipos a un grupo y actualizar los periodos de indisponibilidad de los equipos asignados. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC AsignaEquipos(ListaEquipos,ClaveGrupo)COMIENZA Motivo := "Ocupado para capacitacion, grupo" + ClaveGrupo /* Convertir la clave del grupo a cadena y concatenarlo en Motivo */ Equipo := ListaEquipos HoraIni := HORASINICLASES HoraFin := HORASINICLASES + HORASPORDIA + 1 MIENTRAS Equipo <> NIL HAZ COMIENZA INSERT INTO GruposEquipReal VALUES (ClaveGrupo,Equipo^.Clave,Equipo^.FechaIni,Equipo^.FechaFin,HoraIni,HoraFin)

INSERT INTO PerIndispEquip VALUES (Equipo^.Clave,Equipo^.FechaIni,Equipo^.FechaFin,Motivo) Equipo := Equipo^.Liga TERMINATERMINA

/****************************************************************************************************************************************En este procedimiento se incluye al participante directamente en el programa de cursos, incribiendolo en el grupo que ya esta formado definitivamente.Su asociación al grupo se declara definitiva y sus asociaciones inhibidas se cancelan. Se manifiesta la indisponibilidad del participante para lafecha que comprende el curso. Este procedimiento se puede usar iterativmante para el procedimiento en que el grupo se declara definitivo. Insertaal participante y curso en la tabla Grupo/RHFecha de actualización: 09/03/94****************************************************************************************************************************************/PROC AsignaPartDefinitivamente(VAR ListaParticipantes,VAR ApPartActual,ApGrupoPosible,TablaCorrespGrupos)COMIENZA ApAux := ApPartActual ApPartActual := ApPartActual^.Liga ApCorrespGrupos := Busca(ApGrupoPosible^.Clave,TablaCorrespGrupos) AsignaParticipante(ApAux^.ClaveEmpleado,ApCorrespGrupos^.ClaveGrupoDefinitivo) ActualizaIndispPart(ApAux^.ClaveEmpleado,ApGrupoPosible^.FechaIni,ApGrupoPosible^.FechaFin) EliminaAsocDelPart(ApAux^.ClaveEmpleado) SI Parametro(´MenorCatAnt´) = ´NO´ ENTONCES /* No se admite que se capacite primero alguien con < categ. y antig. */ EliminaAsocAfectadas(ApAux) Elimina(ApAux^.ClaveEmpleado,ListaParticipantes) /* Al eliminar al participante, se debe eliminar su lista de grupos afectados */TERMINA

48

/****************************************************************************************************************************************Al terminar de programar, se quedaron partcicipantes sin asignación, se tratan de llenar todos los grupos posible, uno a uno.Fecha de actualización: 09/03/94****************************************************************************************************************************************/

PROC ProgramaRemanente(PeriodoProyecto,Proyecto,Campus,VAR ListaParticipantes,ListaRecursosRequeridos,ApCurso,GruposPosibles,TablaCorrespGrupos, CantGposPosible,TipoEmp)COMIENZA DepuraAsociacionesRem(PeriodoProyecto,Campus,GruposPosibles,ApCurso,ListaParticipantes,ListaRecursosRequeridos,TablaCorresGrupos,Proyecto,TipoEmp) LiberaTodasAsocRem(GruposPosibles) SI Parametro('MenorCatAnt') = 'NO' ENTONCES LiberaListasGposAfectados(ListaParticipantes) CveGrupo := 0 MIENTRAS (CveGrupo <= CantGruposPosibles) AND (ListaParticipantes <> NIL) HAZ COMIENZA ApGrupo := Busca(CveGrupo,GruposPosibles) SI ApGrupo <> NIL ENTONCES LlenaGrupo(PeriodoProyecto,Proyecto,Campus,ListaParticipantes,ListaRecursosRequeridos,ApCurso,ApGrupo,GruposPosibles, TablaCorrespGrupos,TipoEmp) CveGrupo := CveGrupo +1 TERMINATERMINA

/***************************************************************************************************************************************************** Función: Analizar a los grupos posibles que tienen asignaciones provisionales muy próximas al mínimo de manera que se mantengan como estan y se permita distribuir a los demás participantes en éstos. Para los grupos posibles que tengan muy pocas asociaciones provisionales se les eliminan para que se distribuyan. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC DepuraAsociacionesRem(PeriodoProyecto,CveCampus,GruposPosibles,ApCurso,VAR ListaParticipantes,ListaRecursosRequeridos, TablaCorresGrupos, Proyecto,TipoEmp)COMIENZA DECLARE CursorGrupos CURSOR FOR SELECT UNIQUE ClaveGrupoPosible FROM AsocParticipantes WHERE Status = 'P' ORDER BY ClaveGrupoPosible

OPEN CursorGrupos FETCH CursorGrupos INTO CveGrupo

MIENTRAS (sqlca.sqlcode = 0) HAZ COMIENZA SI NO(CumplePtjeMinPart(ApCurso,CveGrupo,CantPart)) ENTONCES LiberaGrupoRem(CveGrupo,CantPart,ListaParticipantes,GruposPosibles) OTRO COMIENZA ApGrupoPosible := Busca(CveGrupo,GruposPosibles) SI PuedeAsignarRecursos(PeriodoProyecto,ApCurso,ApGrupoPosible,ListaRecursosRequeridos,ListaRecursos,CveCampus) ENTONCES

49

DefinirGrupoDefinitivo(ListaParticipantes,ApGrupoPosible,ApCurso,ListaRecursos,TablaCorrespGrupos,Proyecto,TipoEmp) OTRO EliminaGrupoPosible(GruposPosibles, ApGrupoPosible,ListaParticipantes) TERMINA FETCH CursorGrupos INTO CveGrupo TERMINA CLOSE CursorGruposTERMINA

/***************************************************************************************************************************************************** Función: Libera las asociaciones provisionales a un grupo dado. No se elimina al grupo simplemente se liberan las asociaciones provisionales, que son mínimas para que los participantes se distribuyan en los otros grupos. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC LiberaGrupoRem(CveGrupo,CantPart,ListaParticipantes,GruposPosibles)COMIENZA ApGrupoPosible := Busca(CveGrupo,GruposPosibles) /* Busca un grupo en la tabla de hash GruposPosibles */ RestableceTablaPartDiaCliente(ApGrupoPosible,CantPart) DECLARE CursorParticipantes CURSOR FOR SELECT CveEmp FROM AsocParticipantes WHERE ClaveGrupoPosible = CveGrupo AND Status = 'P'

OPEN CursorParticipantes FETCH CursorParticipantes INTO CvePart

MIENTRAS (sqlca.sqlcode = 0) HAZ COMIENZA ApParticipante := Busca(CvePart,ListaParticipantes) /* Localiza al participante dentro de la ListaParticipantes. Es una localización dentro de una lista ligada. Devuelve el apuntador al nodo donde Clave = CvePart */ RestableceTablaPartDiaCT(ApParticipante,ApGrupoPosible) SI Parametro('MenorCatAnt') = 'NO' ENTONCES COMIENZA LiberaAsocAfectadas(ApParticipante,ListaParticipantes) Libera(ApParticipante^.ListaGruposAfectados) TERMINA FETCH CursorParticipantes INTO CvePart TERMINA CLOSE CursorParticipantes

LiberaAsocPorPtjesLineamientos(ApGrupoPosible,GruposPosibles) /* Libera las asociaciones inhibidas por saturación de porcentajes en centro de trabajo o cliente */ ApGrupoPosible^.CantPart := 0TERMINA

/*****************************************************************************************************************************************************Con todas las provisionales debe actualizar la cantidad de part x centro de trabajo y cliente. También debe inicializar con 0, la cant. de part. algrupo y debe liberar todas las asociaciones de AsocParticipantes.

50

Fecha de actualización: 09/03/94*****************************************************************************************************************************************************PROC LiberaTodasAsocRem(GruposPosibles)COMIENZA $DECLARE CursorAsoc CURSOR FOR SELECT * FROM AsocParticipantes WHERE Status = ´P´ $OPEN CursorAsoc $FETCH CursorAsoc INTO $RegAsoc MIENTRAS (sqlca.sqlcode = 0) HAZ COMIENZA ApGrupo := Busca(RegAsoc.ClaveGrupoPosible,GruposPosibles) ActualizaProvxCT(RegAsoc.CveEmp,ApGrupo^.FechaIni,ApGrupo^.FechaFin) DecrementaPartxCliente(ApGrupo^.FechaIni,ApGrupo^.FechaFin) ApGrupo^.CantPart := 0 $FETCH CursorAsocPart INTO $RegAsoc TERMINA $CLOSE CursorAsocLiberaAsocRem()TERMINA

51

/****************************************************************************************************************************************Decrementa el número de participantes para el centro de trabajo, en el periodo del grupoFecha de actualización: 09/03/94****************************************************************************************************************************************/PROC ActualizaProvxCT(ClaveEmpleado,FechaIni,FechaFin)COMIENZA UPDATE PartDiaCentroTrabajo SET CantPart = CantPart - 1 WHERE DiaJuliano BETWEEN FechaIni AND FechaFin AND CveCT = (SELECT ClaveCentroTrab FROM RecHumanos WHERE Clave = ClaveEmpleado))

TERMINA

/****************************************************************************************************************************************Decrementa el número de participantes para el centro de trabajo, en el periodo del grupoFecha de actualización: 09/03/94****************************************************************************************************************************************/PROC DecrementaPartxCliente(FechaIni,FechaFin)COMIENZA UPDATE PartDiaCliente SET CantPart = CantPart - 1 WHERE DiaJuliano BETWEEN FechaIni AND FechaFinTERMINA

/****************************************************************************************************************************************Pone el status en ´L´ para todas las asociaciones que existen, es decir se liberan todas las asociaciones existentes.Fecha de actualización: 09/03/94****************************************************************************************************************************************/PROC LiberaAsocRem()COMIENZA UPDATE AsocPart SET Status = ´L´TERMINA

/**************************************************************************************************************************************** Función: Liberar la lista de grupos afectados de cada uno de los participantes de la lista. Fecha de actualización: 09/03/94****************************************************************************************************************************************/PROC LiberaListasGposAfectados(ListaParticipantes)COMIENZA ApPart := ListaParticipantes MIENTRAS ApPart <> NIL HAZ COMIENZA Libera(ApPart^.ListaGruposAfectados) /* Liberación de memoria de una lista ligada */ ApPart := ApPart^.Liga TERMINATERMINA

52

/***************************************************************************************************************************************************** Función: Llenar un grupos al máximo de participantes si es posible y cubrir todas las posibilidades de aulas en el plantel del grupo propuesto Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC LlenaGrupo(PeriodoProyecto,Proyecto,Campus,ListaParticipantes,ListaRecursosRequeridos,ApCurso,ApGrupo,GruposPosibles,TablaCorrespGrupos,TipoEmp)COMIENZA CveGpoPosible := ApGrupo^.Clave PtjePart := 100 * ApGrupo^.CantPart / ApCurso^.MinParticipantes /* nota division por cero: ApCurso^.MinParticipantes no puede ser cero */ PtjePermitido := Parametro('PtjeMinCur') SI (ApGrupo^.CantPart > ApCurso^.MinPArticipantes) 0R (PtjePart >= PtjePermitido) ENTONCES LlenaGrupoYaDefinitivo(PeriodoProyecto,ListaParticipantes,ListaRecursosRequeridos,ApCurso,ApGrupo,GruposPosibles, TablaCorrespGrupos) OTRO LlenaGrupoVacio(PeriodoProyecto,Proyecto,Campus,ListaParticipantes,ListaRecursosRequeridos,ApCurso,ApGrupo,GruposPosibles, TablaCorrespGrupos, TipoEmp) ApGrupo := Busca(CveGpoPosible,GruposPosibles) MIENTRAS ApGrupo <> NIL COMIENZA LlenaGrupoVacio(PeriodoProyecto,Proyecto,Campus,ListaParticipantes,ListaRecursosRequeridos,ApCurso,ApGrupo,GruposPosibles, TablaCorrespGrupos, TipoEmp) ApGrupo := Busca(CveGpoPosible,GruposPosibles) TERMINATERMINA

/***************************************************************************************************************************************************** Función: Completar el cupo de un grupo que ya tiene asignados recursos para la impartición del curso. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC LlenaGrupoYaDefinitivo(PeriodoProyecto,ListaParticipantes,ListaRecursosRequeridos,ApCurso,ApGrupo,GruposPosibles, TablaCorrespGrupos)COMIENZA EsGrupoDefinitivo := VERDADERO

DECLARE CursorParticipantes CURSOR FOR SELECT * FROM AsocParticipantes WHERE ClaveGrupoPosible = ApGrupo^.Clave AND Status = 'L' ORDER BY Costo OPEN CursorParticipantes FETCH CursorParticipantes INTO RegAsocPart MIENTRAS (sqlca.sqlcode = 0) AND (EsGrupoDefinitivo) HAZ COMIENZA ApPartActual := Busca(RegAsocPart.CveEmp,ListaParticipantes) SI CumplePorcentajesLineaminetos(ApCurso,ApPartActual,ApGrupo) ENTONCES COMIENZA AsignaPartAGrupo(ApPArtActual,GruposPosibles,ApGrupo) AsignaPartDefinitivamente(ListaParticipantes,ApPartActual,ApGrupo,TablaCorrespGrupos) TERMINA SI CubreMaximoPart(ApCurso,ApGrupo) ENTONCES

53

COMIENZA EsGrupoDefinitivo := FALSO CierraGrupo(PeriodoProyecto,GruposPosibles,ApGrupo,TablaCorrespGrupos,ListaRecursosRequerridos) TERMINA FETCH CursorParticipantes INTO RegAsocPart TERMINA CLOSE CursorParticipantesTERMINA

/***************************************************************************************************************************************************** Función: Llena el grupo al máximo si es posible con todas las asociaciones que dan a ese grupo. Estas asociaciones se ordenas del costo mínimo al máximo Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC LlenaGrupoVacio(PeriodoProyecto,Proyecto,Campus,ListaParticipantes,ListaRecursosRequeridos,ApCurso,ApGrupo,GruposPosibles, TablaCorrespGrupos, TipoEmp)COMIENZA Estado := 1 DECLARE CursorParticipantes CURSOR FOR SELECT * FROM AsocParticipantes WHERE ClaveGrupoPosible = ApGrupo^.Clave AND Status = 'L' ORDER BY Costo

OPEN CursorParticipantes FETCH CursorParticipantes INTO RegAsocPart

MIENTRAS (sqlca.sqlcode = 0) AND (ApGrupo^.CantPart < ApCurso^.MaxParticipantes) HAZ COMIENZA Estado = sqlca.sqlcode ApPartActual := Busca(RegAsoc.CveEmp,ListaParticipantes) SI CumplePorcentajesLineamientos(ApCurso,ApPartActual,ApGrupo) AsignaPartAGrupo(ApPartActual,GruposPosibles,ApGrupo) FETCH CursorParticipantes INTO RegAsocPart TERMINA CLOSE CursorParticipantes SI ApGrupo^.CantPart < ApCurso^.MinParticipantes - (Parametro(´PtjeMinCur´)*ApCurso^.MinParticipantes/100) ENTONCES EliminaGrupoPosible(GruposPosibles,ApGrupo,ListaParticipantes) OTRO SI PuedeAsignarRecursos(PeriodoProyecto,ApCurso,ApGrupo,ListaRecursosRequeridos,ListaRecursos,Campus) ENTONCES COMIENZA DefinirGrupoDefinitivo(ListaParticipantes,ApGrupo,ApCurso,ListaRecursos,TablaCorrespGrupos,Proyecto,TipoEmp) SI Estado = 0 ENTONCES COMIENZA Elimina(ApGrupo^.Clave,TablaCorrespGrupos) Elimina(ApGrupo^.Clave,GruposPosibles) TERMINA OTRO CierraGrupo(PeriodoProyecto,GruposPosibles,ApGrupo,TablaCorrespGrupos,ListaRecursosRequerridos) TERMINA OTRO EliminaGrupoPosible(GruposPosibles,ApGrupo,ListaParticipantes)

54

TERMINA

/****************************************************************************************************************************************Toma el número de folio de la tabla correspondiente para asignar el siguiente número consecutivo de esa tabla. Esto se hace cuando la lleva primariaes un serialFecha de actualización: 09/03/94****************************************************************************************************************************************/PROC LeeFolio(NombreDeTabla,NumeroFolio)COMIENZA SELECT NumFolio INTO NumeroFolio FROM Folios WHERE NombreTabla = NombreDeTablaTERMINA

/****************************************************************************************************************************************Guarda el número de folio actualizado en la tabla correspondiente. Esto se hace cuando la lleva primaria es un serialFecha de actualización: 09/03/94****************************************************************************************************************************************/PROC ActualizaFolio(NumeroFolio,NombreDeTabla)COMIENZA UPDATE Folios SET NumFolio = NumeroFolio WHERE NombreTabla = NombreDeTablaTERMINA

/***************************************************************************************************************************************************** Función: Crear las asociaciones de los participantes con los grupos posibles de acuerdo a las fechas de los grupos y las disponibilidades de

los participantes. Para cada uno de los grupos propuestos se trata de crear una asociación entre el grupo y cada uno de los recursos humanos de la lista de

participantes.Fecha de actualización: 17/03/94

*****************************************************************************************************************************************************/PROC CreaAsigParticPosibles(ListaParticipantes,GruposPosibles,NumGposPosibles,PeriodoProyecto,TipoEmp)COMIENZA ObtenDatosFunción(PeriodoProyecto) ApPartActual := ListaParticipantes MIENTRAS ApPartActual <> NIL HAZ COMIENZA CveGrupo := 0 MIENTRAS CveGrupo <= NumGposPosibles HAZ COMIENZA ApGrupo := Busca(CveGrupo,GruposPosibles) AsociaPartAGrupo(ApGrupo,ApPartActual,TipoEmp) CveGrupo := CveGrupo + 1 TERMINA

55

ApPartActual := ApPartActual^.Liga TERMINATERMINA

/*****************************************************************************************************************************************************Función: Obtener los datos necesarios para la definición de la función de costo para las asociaciones participante grupo.

Inicialmente se definen éstas datos en base a valores que se dan por default, posteriormente se toman los valores definidos por el usuario en la configuración de la etapas y se redefine la función con éstos nuevos valores.

NOTA: Todas las variables locales de este módulo son de tipo real.Fecha de actualización: 11/04/94

*****************************************************************************************************************************************************/PROC ObtenDatosFuncion(PeriodoProyecto)COMIENZA DatosFuncionGLB.RangoMaxFecha := 2 ObtenDatosBasicosFuncion(PeriodoProyecto) z1 := FCostoAsocPart(PeriodoProyecto.FechaIni,DatosFuncionGLB.CostoMaxGpo,0) y1 := FCostoCur(PeriodoProyecto.FechaIni+1,z1-DIFERENCIAMIN) AhorroBasico := DatosFuncionGLB.CostoMaxGpo - y1 y2 := FCostoCur(PeriodoProyecto.FechaIni+2,z1-DIFERENCIAMIN) PendienteAhorro := y2 - y1 AhorroDeseado := Parametro('Ahorro') DatosFuncionGLB.RangoMaxFecha := 2 + ((AhorroDeseado - AhorroBasico)/PendienteAhorro) ObtenDatosBasicosFuncion(PeriodoProyecto)TERMINA

/***************************************************************************************************************************************************** Función: Obtener el costo de una asociación a un grupo dados la fecha, el costo y los viaticos asociados al grupo. La función describe un plano

cuya fórmula general es Ax +By +Cz +D = 0, donde el eje x representa a la fechas de los grupos, el eje y representa el costo estimado del grupo yz representa la función de costo de una asociación Grupo-participante. Los viáticos lo que representan es un desplazamiento del plano descritosobre el eje z, con esto la función real es : z = ((-Ax -By -D)/C)+ CostoViáticosFecha de actualización: 11/04/94

*****************************************************************************************************************************************************/FUNCION FCostoAsocPart(Fecha,Costo,Viaticos)COMIENZA SI (DatosFuncionGLB.C) = 0 ENTONCES FCostoAsocPart := INFINITO OTRO FCostoAsoc := ((-(DatosFunciónGLB.A * Fecha) - (DatosFuncionGLB.B * Costo) - DatosFuncionGLB.D)/ DatosFuncionGLB.C) + ViaticosTERMINA

/***************************************************************************************************************************************************** Esta función corresponde a la dada por el despeje de la variable de costo en la función FCostoAsoc, cuando los viáticos son cero.

Fecha de actualización: 11/04/94*****************************************************************************************************************************************************/FUNCION FCostoCur(Fecha,CostoAsoc)COMIENZA FCostoCur := ((-DatosFuncionGLB.D - (DatosFuncionGLB.A * Fecha) - (DatosFuncionGLB.C * CostoAsoc))/DatosFuncionGLB.BTERMINA

56

/*****************************************************************************************************************************************************Función: Obtener los datos necesarios para la definición de la función de costo para las asociaciones participante grupo.Fecha de actualización: 17/03/94

*****************************************************************************************************************************************************/PROC ObtenDatosBasicos(PeriodoProyecto)COMIENZA DatosFuncionGLB.RangoMaxCosto := 2 a1 := PeriodoProyecto.FechaFin - PeriodoProyecto.FechaIni a3 := DatosFuncionGLB.RangoMaxFecha - 1 b2 := DatosFuncionGLB.CostoMaxGpo - DatosFuncionGLB.CostoMinGpo b3 := DatosFuncionGLB.RangoMaxCosto - 1 DatosFuncionGLB.A := -b2 * a3 DatosFuncionGLB.B := -a1 * b3 DatosFuncionGLB.C := a1 * b2 DatosFuncionGLB.D := (PeriodoProyecto.FechaIni * DatosFuncionGLB.A) + (DatosFuncionGLB.CostoMinGpo * DatosFuncionGLB.B) + DatosfuncionGLB.CTERMINA

/*****************************************************************************************************************************************************Función: Verifica si el participante está disponible en el periodo comprendido entre la fecha inicial y la fecha final del grupo, si es asi crea

una asociación entre el participante y el grupo. Para crear la asociación participante-grupo se calcula el costo de la asociación de acuerdo a la función de costo-fecha. Para verificar la disponibilidad de un participante se da un margen de dias antes y después de que comience y termine el curso para que se translade en caso de ser necesario.

NOTA: Dado que muchos de los recursos humanos de OCM, ITM los solicita como instructores, al verificar que un participante este disponible en unperiodo dado, se debe verificar también que si es instructor no tenga periodos de indisponibilidad como instructor.

Fecha de actualización: 11/04/94*****************************************************************************************************************************************************/PROC AsociaPartAGrupo(ApGrupo,ApPart,TipoEmp)COMIENZA EsDispInstr := CIERTO DiasParaMov := Parametro('DiasTraslado') /* Dias necesarios para el movimiento de un recurso humano de una localidad a otra */ SI EsInstructor(ApPart^.ClaveEmpleado,CveInstr) ENTONCES EsDispInstr := EsDisponibleInstructor(CveInstr,ApGrupo^.FechaIni,ApGrupo^.FechaFin) SI EsDisponibleRecHumT(ApPart^.ClaveEmpleado,ApGrupo^.FechaIni-DiasParaMov,ApGrupo^.FechaFin+DiasParaMov) AND NO(EsPeriodoCritico(ApPart^.ClaveEmpleado,ApGrupo^.FechaIni-DiasParaMov,ApGrupo^.FechaFin+DiasParaMov) AND EsDispInstr = CIERTO) ENTONCES COMIENZA NumCursosSoli := BuscaNumCursosPart(ApPart^.CveEmpleado,GLBPartNumCursos) ObtenLocalidadPart(ApPart^.ClaveCentroTrab,CveLocOrigen) CostoViaticos := FViaticos(ApGrupo^.FechaIni,ApGrupo^.FechaFin,CveLocOrigen,ApGrupo^.CveLocalidad,TipoEmp)/*** CostoAsociacion := FCostoAsocPart(ApGrupo^.FechaIni,ApPart^.Jerarquia,NumCursosSoli,ApGrupo^.CostoEstim,CostoViaticos) ****/ CostoAsociacion := FCostoAsocPart(ApGrupo^.FechaIni,ApGrupo^.CostoEstim,CostoViaticos) INSERT INTO AsocParticipantes VALUES(ApPart^.ClaveEmpleado,ApGrupo^.Clave,CostoAsociacion,'L') TERMINATERMINA

/*****************************************************************************************************************************************************

57

Función: Verificar si un recurso humano de OCM es instructor.Fecha de actualización: 08/04/94

*****************************************************************************************************************************************************/FUNCION EsInstructor(CveRecHum,VAR CveInstr)COMIENZA CveInstr := 0

SELECT Clave INTO CveInstr FROM Instructores WHERE CveRecurso = CveRecHum

SI CveInstr != 0 ENTONCES EsInstructor := CIERTO OTRO EsInstructor := FALSOTERMINA

/*****************************************************************************************************************************************************Función: Verificar que un recurso humano de OCM no tenga periodos de indisponibilidad que se intersecten con el perido comprendido entre la

fecha inicial y la fecha final indicados.Fecha de actualización: 08/04/94

*****************************************************************************************************************************************************/FUNCION EsDisponibleRecHumT(ClaveEmpleado,FechaInicio,FechaFinal)COMIENZA NumPeriodos := 0

SELECT COUNT(*) INTO NumPeriodos FROM PerIndispRH WHERE (FechaIni <= FechaFinal AND FechaFin >= FechaInicio) (CveRH = ClaveEmpleado)

SI NumPeriodos = 0 ENTONCES EsDisponibleRecHumT := CIERTO OTRO EsDisponibleRecHumT := FALSOTERMINA

/*****************************************************************************************************************************************************Función: Verificar que la especialidad o unidad de negocio a la que pertenece un recurso humano no tenga periodos críticos que se intersecten con

el periodo comprendido entre la fecha inicio y fecha fin indicados.Fecha de actualización: 08/04/94

*****************************************************************************************************************************************************/FUNCION EsPeriodoCritico(ClaveEmpleado,FechaInicio,FechaFinal)COMIENZA SELECT CveTipPersonal, CveNivelCategoria INTO TipoPersonal, NivelCategoria FROM Puestos WHERE Clave = (SELECT CvePuesto FROM RecHumanos WHERE Clave = ClaveEmpleado)

58

SI TipoPersonal = SINDICALIZADO ENTONCES EsPeriodoCritico := EsPeriodoCriticoEspec(NivelCategoria,FechaInicio,FechaFinal) OTRO EsPeriodoCritico := EsPeriodoCriticoUniNeg(NivelCategoria,FechaInicio,FechaFinal)TERMINA

/*****************************************************************************************************************************************************Función: Verificar si existen periodos críticos para una la especialidad a la que pertenece una categoría, que se intersecten con el periodo

comprendido entre la fecha inicial y la fecha final indicadas.Fecha de actualización: 29/03/94

*****************************************************************************************************************************************************/FUNCION EsPeriodoCriticoEspec(CveCategoria,FechaInicio,FechaFinal)COMIENZA NumPeriodos := 0

SELECT COUNT(*) INTO NumPeriodos FROM PerCritEspec WHERE (CveEspec = ( SELECT CveEspecialidad FROM Categorias WHERE Clave = CveCategoria)) AND (FechaIni <= FechaFinal AND FechaFin >= FechaInicio)

SI NumPeriodos = 0 ENTONCES EsPeriodoCriticoEspec := FALSO OTRO EsPeriodoCriticoEspec := CIERTOTERMINA

/*****************************************************************************************************************************************************Función: Verificar si existen periodos críticos para la unidad de negocio a la que pertenece un nivel, que se intersecten con el periodo

comprendido entre la fecha inicial y la fecha final indicadas.Fecha de actualización: 29/03/94

*****************************************************************************************************************************************************/FUNCION EsPeriodoCriticoUniNeg(CveNivel,FechaInicio,FechaFinal)COMIENZA NumPeriodos := 0

SELECT COUNT(*) INTO NumPeriodos FROM PerCritUniNeg WHERE (CveUniNeg = ( SELECT CveUnidNegocio FROM Niveles WHERE Clave = CveNivel)) AND (FechaIni <= FechaFinal AND FechaFin >= FechaInicio)

59

SI NumPeriodos = 0 ENTONCES EsPeriodoCriticoUniNeg := FALSO OTRO EsPeriodoCriticoUniNeg := CIERTOTERMINA

/*****************************************************************************************************************************************************Función: Obtener las localidades donde se encuentra un centro de trabajo de un participanteFecha de actualización: 09/03/94

*****************************************************************************************************************************************************/PROC ObtenLocalidPart(ClaveCentroTrab, VAR CveLocOrigen)COMIENZA SELECT CveLocalidad INTO CveLocOrigen FROM CentrosTrab WHERE Clave = ClaveCentroTrab

TERMINA

/*****************************************************************************************************************************************************Función: obtener el cálculo de los costos de viáticos de tranporte y hospedaje para el translado y permanencia de un participante de su localidad

de origen a la localidad destino que es en la que se impartirá el curso.Fecha de actualización: 09/03/94

*****************************************************************************************************************************************************/FUNCION FViaticos(FechaIni,FechaFin,CveLocOrigen,CveLocDestino,TipoEmp)COMIENZA SI DebePagarViaticos(CveLocOrigen,CveLocDestino) ENTONCES COMIENZA DuracionCurso := FechaFin - FechaIni + 1 /* El uno que se suma es para contar el dia de inicio */

SELECT SUM(Importe) INTO CostosFijosxDia FROM CuotasTipPersonal WHERE CveTipPersonal = TipoEmp

SELECT Importe INTO CostoHospedajexDia FROM TarifasHospedaje WHERE CveLocalidad = CveLocDestino

CostoTransporte := FCostoTrasp(CveLocOrigen,CveLocDestino) FViaticos := DuracionCurso * (CostosFijosxDia + CostoHospedajexDia) + 2 * CostoTransporte + CostosFijosxDia/2 /* Se suman la mitad de los costos fijos por dia, por el dia en que se regresa */ TERMINA OTRO FViaticos := 0 /* De la localidad origen a la localidad destino no se pagan viáticos */TERMINA

60

/*****************************************************************************************************************************************************Función: Verificar si para transladarse de una localidad origen a una localidad destino se pagan viáticos.Fecha de actualización: 09/03/94

*****************************************************************************************************************************************************/FUNCION DebePagarViaticos(CveLocOrigen,CveLocDestino)COMIENZA SELECT * FROM LocSinViaticos WHERE Origen = CveLocOrigen AND Destino = CveLocDestino

SI sqlca.sqlcode = 0 ENTONCES DebePagarViaticos := CIERTO OTRO DebePagarViaticos := FALSOTERMINA

/*****************************************************************************************************************************************************Función: Obtener el costo de viáticos por concepto de transportación de una localidad origen a una localidad destino. En caso de que no exista una

ruta indirecta ni directa para trasladarse de la localidad origen a la localidad destino, se asigna un costo muy elevado para que la función total de la asignación (de participantes o instructores no lo asigne a un lugar en donde no existe nisguna ruta para trasladarse

Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/FUNCION FCostoTrasp(CveLocOrigen,CveLocDestino)COMIENZA SELECT Importe INTO Costo FROM TarifasIndirecta WHERE Origen = CveLocOrigen AND Destino = CveLocDestino

SI sqlca.sqlcode = 0 ENTONCES FCostoTrasp := Costo OTRO FCostoTrasp := INFINITOTERMINA

61

/***************************************************************************************************************************************************** Función: Determinar las posibles fechas y planteles para la impartición del curso de acuerdo a la disponibilidad de los recursos que requiere el curso. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC AbrePosiblesGrupos(PeriodoProyecto,Campus,ApCurso,GruposPosibles,ListaRecursosRequeridos,VAR CantGruposPosibles,VAR CostoMinGpo,VAR CostoMaxGpo)COMIENZA DuracionCurso := DuracionEndias(ApCurso^.Duracion) DefineFechas(DuracionCurso,PeriodoProyecto, ListaFechas) DefinePlanteles(PeriodoProyecto,ListaFechas,ListaRecursosRequeridos^.ListaInstalaciones,Campus,GruposPosibles,CantGruposPosibles,CostMinGpo, CostoMaxGpo) Libera(ListaFechas)TERMINA

/***************************************************************************************************************************************************** Función: Convierte la duración de un curso dado en horas a dias dependiendo del numero maximo de horas que se dan de clase en undia. Devuelve el número de dias que dura un curso. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/FUNCION DuracionEndias(DuracionEnHoras)COMIENZA SI (DuracionEnHoras MOD HORASPORDIA > 0) ENTONCES Dias := (DuracionEnHoras DIV HORASPORDIA) + 1 OTRO Dias := DuracionEnHoras DIV HORASPORDIA DuracionEndias := DiasTERMINA

/***************************************************************************************************************************************************** Función: Definir las posibles fechas en las que se podría impartir un curso dentro de un periodo, minimizando las interrupciones. Los días de inicio se generan de acuerdo a un arreglo constante que contiene los días de la semana en que puede iniciar un curso de modo que se minimizan las interrupciones. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC DefineFechas(DuracionCurso,PeriodoProyecto,VAR ListaFechas)COMIENZA InicioCurso := PeriodoProyecto.FechaIni MIENTRAS ((InicioCurso + DuracionCurso ) <= PeriodoProyecto.FechaFin) HAZ COMIENZA /* Se analizan todas las posibles fechas para inicio del curso*/ FinCurso := EsPermitidaFechaCurso(InicioCurso,DuracionCurso,PeriodoProyecto) SI FinCurso > 0 ENTONCES Inserta(InicioCurso,FinCurso,ListaFechas) /*Insertar en una lista ligada */ InicioCurso := InicioCurso +1 TERMINATERMINA/***************************************************************************************************************************************************** Función: Verificar que la fecha InicioCurso sea un día hábil y que el curso tenga el mínimo de interrupciones Valor devuelto : Fecha de finalización del curso o -1 si el inicio del curso no es válido. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/

62

FUNCION EsPermitidaFechaCurso(InicioCurso,DuraciónCurso,PeriodoProyecto)COMIENZA DíasHábiles := 1 /* El dia en el que comienza el curso se debe contar también */ IndAux := InicioCurso - PeriodoProyecto.FechaIni SI(DiasInicio[DuraciónCurso MOD 5][((InicioCurso - PeriodoProyecto.FechaIni) + PeriodoProyecto.DiaSemFechaIni) MOD 7] = 1) ENTONCES COMIENZA SI(EsFestiva(IndAux - 1,PeriodoProyecto) = FALSO AND Calendario.Arreglo[IndAux] = DIAHABIL AND EsFestiva(IndAux +1,PeriodoProyecto) = FALSO ) ENTONCES COMIENZA MIENTRAS (DíasHábiles < DuraciónCurso) AND (IndAux < Calendario.Tamaño) HAZ COMIENZA SI Calendario.Arreglo[IndAux] = DIAHABIL ENTONCES DíasHábiles := DíasHábiles +1 IndAux := IndAux +1 TERMINA SI (EsFestiva(IndAux - 1,PeridoProyecto) = FALSO AND Calendario.Arreglo[IndAux] = DIAHABIL AND EsFestiva(IndAux +1,PeriodoProyecto) = FALSO) ENTONCES EsPermitidaFechaCurso := PeriodoProyecto.FechaIni + IndAux OTRO EsPermitidaFechaCurso := -1 TERMINA OTRO EsPermitidaFechaCurso := -1 TERMINA OTRO EsPermitidaFechaCurso := -1TERMINA

/***************************************************************************************************************************************************** Función: Verificar si una fecha es dia festivo o no. La fecha a analizar es dada por la fecha de inicio del periodo del proyecto más el número de dias dados en FechaIndice. Cuando el dia que se analizará es un dia anterior a la fecha de inicio del proyecto o la fecha posterior a la fecha de finalización del proyecto, se busca la fecha en la tabla de dias festivos puesto que el Calendario usado en el programa no contiene estas dos fechas. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/FUNCION EsFestiva(FechaIndice,PeriodoProyecto)COMIENZA SI ((PeriodoProyecto.FechaIni + FechaIndice) < PeriodoProyecto.FechaIni) OR ((PeriodoProyecto.FechaIni + FechaIndice) > PeriodoProyecto.FechaFin) ENTONCES COMIENZA SELECT Fecha FROM DiasFestivos WHERE Fecha = (PeriodoProyecto.FechaIni + FechaIndice)

SI sqlca.sqlcode = 0 ENTONCES EsFestiva := CIERTO OTRO EsFestiva := FALSO TERMINA OTRO SI Calendario.Arreglo[FechaIndice] = DIAINHABIL EsFestiva := CIERTO

63

OTRO EsFestiva := FALSOTERMINA

/******************************************************************************************************** Funcion: Determinar los planteles en los que se puede impartir un curso, a partir de la existencia y disponibilidad de las instalaciones que requiere el curso para impartirse. Fecha de actualización: 09/03/94********************************************************************************************************/PROC DefinePlanteles(PeriodoProyecto,ListaFechas,ListaInstalReq,Campus,GruposPosibles,VAR NumGrupos, VAR CostoMinGpo, VAR costoMaxGpo)COMIENZA CostoMinGpo := 1 CostoMaxGpo := 0

DECLARE CursorPlanteles CURSOR FOR SELECT Clave, CveLocalidad FROM Planteles WHERE CveCampus = Campus

NumGrupos = 0

OPEN CursorPlanteles FETCH CursorPlanteles INTO CvePlantel, CveLocalidad MIENTRAS (sqlca.sqlcode = 0) HAZ COMIENZA SI ExistenInstalaciones(ListaInstalReq,CvePlantel) ENTONCES /* Para cada una de los planteles existenten en en campus se verifica cual cuaenta con las instalaciones requeridas para la impartición del curso*/ COMIENZA ApFecha := ListaFechas CostoCurso := 0 MIENTRAS ApFecha <> NIL HAZ COMIENZA InstalReq := ListaInstalReq Disponibilidad := CIERTO MIENTRAS InstalReq != NIL AND Disponibilidad = CIERTO HAZ COMIENZA GeneraListaInventarioInstal( InstalReq^.CveTipInstalacion,CvePlantel, ListaInventarioInstal) InventInstal := ListaInventarioInstal CuentaInstal := 0 Costo :=0 MIENTRAS InventInstal <> NIL HAZ COMIENZA SI EsDisponibleInstal(PeriodoProyecto,InstalReq,InventInstal^.Clave,ApFecha) ENTONCES COMIENZA Costo := Costo+InventInstal^.Costo*((InstalReq^.HoraFin - InstalReq^.HoraIni) CuentaInstal := CuentaInstal +1 TERMINA InventInstal := InventInstal^.Liga TERMINA SI CuentaInstal > 0 ENTONCES CostoCurso := CostoCurso + (Costo/CuentaInstal) OTRO Disponibilidad := FALSO Libera(ListaInventarioInstal) InstalReq := InstalReq^.Liga TERMINA SI Disponibilidad = CIERTO ENTONCES COMIENZA SI CostoCurso < CostoMinGpo ENTONCES CostoMinGpo := CostoCurso SI CostoCurso > CostoMaxGpo ENTONCES CostoMaxGpo := CostoCurso Inserta(NumGrupos,ApFecha^.FechaIni,ApFecha^.FechaFin,CvePlantel,CveLocalidad, 0,CostoCurso,GruposPosibles) NumGrupos := NumGrupos + 1 TERMINA ApFecha := ApFecha^.Liga TERMINA TERMINA FETCH CursorPlanteles INTO CvePlantel, CveLocalidad TERMINA CLOSE CursorPlantelesTERMINA

/***************************************************************************************************************************************************** Función: Verificar si un plantel posee todas las instalaciones que se requieren para impartir un curso Valor devuelto: CIERTO si el plantel posee todas las instalaciones, FALSO en caso contrario. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/FUNCION ExistenInstalaciones(ListaInstalReq,ClavePlantel)COMIENZA InstalReq := ListaInstalReq Suficientes := CIERTO MIENTRAS InstalReq <> NIL AND Suficientes = CIERTO HAZ COMIENZA SELECT * FROM InvenInsta WHERE CvePlantel = ClavePlantel AND CveTipInsta = InstalReq^.CveTipInstalacion

SI sqlca.sqlcode <> 0 ENTONCES Suficientes = FALSO InstalReq := InstalReq^.Liga TERMINA ExistenInstalaciones := SuficientesTERMINA

/***************************************************************************************************************************************************** Función: Generar una lista de las instalaciones de un tipo inventariadas en un plantel. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/PROC GeneraListaInventarioInstal (CveTipInstalacion,ClavePlantel,VAR ListaInventarioInstal)COMIENZA DECLARE CursorInvent CURSOR FOR SELECT Clave,0,Costo,0 FROM InvenInsta WHERE CveTipInsta = CveTipInstalación AND CvePlantel = ClavePlantel

OPEN CursorInvent FETCH CursorInvent INTO RegInsta /* RegInsta es de tipo ListaInventarioInstalSQL */

MIENTRAS sqlca.sqlcode = 0 HAZ COMIENZA Inserta(RegInsta.Clave,RegInsta.Costo, ListaInventarioInstal) FETCH CursorInvent INTO RegInsta TERMINA CLOSE CursorInventTERMINA

66

/***************************************************************************************************************************************************** Función: Verificar si una instalación esta disponible dentro un periodo de tiempo. Valor devuelto: CIERTO si la instalación está disponible durante el periodo que se requiere para el curso, FALSO en otro caso. Fecha de actualización: 09/03/94*****************************************************************************************************************************************************/FUNCION EsDisponibleInstal(PeriodoProyecto,ApInstalReq,CveInstalacion,ApFecha)COMIENZA Disponible := CIERTO FechaUso.FechaIni := ApFecha^.FechaIni + (FechaIniUso(ApInstalReq^.HoraIni,ApFecha^.FechaIni,PeriodoProyecto) ) FechaUso.HoraIni := (ApInstalReq^.HoraIni MOD HORASPORDIA) + HORAINICLASES - 1 FechaUso.FechaFin := ApFecha^.FechaIni + (FechaFinUso(ApInstalReq^.HoraFin,ApFecha^.FechaIni,PeriodoProyecto)) FechaUso.HoraFin := (ApInstalReq^.HoraFin MOD HORASPORDIA) + HORAINICLASES - 1

SELECT COUNT(*) INTO NumPeriodos FROM PerInsdispInstal WHERE CveInstal = CveInstalacion AND (FechaIni < FechaUso.FechaFin OR (FechaIni = FechaUsoFechaFin AND HoraInicial < HoraIni)) AND (FechaFin > FechaUso.FechaIni OR (FechaFin = FechaUso.FechaIni AND HoraFinal > HoraFin))

SI NumPeriodos = 0 ENTONCES EsDisponibleInstal := CIERTO OTRO EsDisponibleInstal := FALSOTERMINA

/***************************************************************************************************************************************************** Función: Corresponder una hora inicial de uso de un recurso con una fecha real con respecto a la fecha de inicio de un curso. Fecha de actualización: 11/03/94*****************************************************************************************************************************************************/FUNCION FechaIniUso(HoraIniUso,FechaIniCurso,PeriodoProyecto)COMIENZA FechaIniRelativa := HoraIniUso DIV (HORASPORDIA + 1) MIENTRAS EsFestiva((PeriodoProyecto.FechaIni -(FechaIniCurso+FechaIniRelativa)),PeriodoProyecto) HAZ FechaIniRelativa := FechaIniRelativa + 1 FechaIniUso := FechaIniRelativaTERMINA

/***************************************************************************************************************************************************** Función: Corresponder una hora final de uso de un recurso con una fecha real con respecto a la fecha de inicio de un curso. Fecha de actualización: 11/03/94*****************************************************************************************************************************************************/FUNCION FechaFinUso(HoraFinUso,FechaIniCurso,PeriodoProyecto)COMIENZA FechaFinRelativa := HoraFinUso DIV (HORASPORDIA + 1) MIENTRAS EsFestiva((PeriodoProyecto.FechaIni -(FechaIniCurso+FechaFinRelativa)),PeriodoProyecto) HAZ FechaFinRelativa := FechaFinRelativa + 1 FechaFinUso := FechaFinRelativaTERMINA

67

/***************************************************************************************************************************************************** Función: Realizar la asignación de recursos (instalaciones, equipos e instructores) a un grupo. La asignación de recursos puede tomar los recursos de proveedores, propios o combinados, esto depende de los lineamientos que se reflejan en

los parámetros que se que se configuran para la programación automatica. El parámetros que especifica la fuente de donde se obtendran losrecursos tiene el nmónico FteCapRecMat (fuente de capacitación y recursos materiales) y puede adoptar los siguentes valores:

1: Los recursos para la capacitación se obtendrán únicamente de los recursos del cliente o del instituto 2: Los recursos que se asignen a los grupos deberán ser proporcionados por los proveedores 3: Los recursos que se asignen a los grupos podrán ser del instituto, del cliente o de proveedor, el orden en que se asignarán serán primero los recursos del cliente y propios y posteriormente los recursos de proveedor.

4: Los recursos que se asignen a los grupos podrán ser del instituto, del cliente o de proveedor, el orden en que se asignarán serán primero losrecursos proporcionados por el proveedor y posteriormente los recursos del instituto y del cliente.

La función devuelve CIERTO cuando la asignación de los recursos fue satisfactoria o que los parámetros de la programación indiquen que no esobligatoria la asignación de los recursos para que el grupo permanezca abierto.

Fecha de actualización:*********************************************************************************************************************************************/FUNCION PuedeAsignarRecursos(PeriodoProyecto,ApCurso,ApGrupo,ListaRecRequeridos,VAR ListaRecAsignados,CveCampus)COMIENZA Exito := CIERTO ListaRecAsignados.ListaInstalaciones := NULL ListaRecAsignados.ListaEquipos := NULL ListaRecAsignados.Instructor.Clave := 0 FteDeRecursos := Parametro('FteCapRecMat') CASO DE FteDeRecursos COMIENZA 1: AsignaRecursosPropios(FteDeRecursos,PeriodoProyecto,ApCurso,ApGrupo,ListaRecRequeridos,ListaRecAsignados) 2: AsignaRecursosProveedor(FteDeRecursos,PeriodoProyecto,ApCurso,ApGrupo,ListaRecRequeridos,ListaRecAsignados,CveCampus) 3: AsignaRecursosPropios(FteDeRecursos,PeriodoProyecto,ApCurso,ApGrupo,ListaRecRequeridos,ListaRecAsignados) AsignaRecursosProveedor(FteDeRecursos,PeriodoProyecto,ApCurso,ApGrupo,ListaRecRequeridos,ListaRecAsignados,CveCampus) 4: AsignaRecursosProveedor(FteDeRecursos,PeriodoProyecto,ApCurso,ApGrupo,ListaRecRequeridos,ListaRecAsignados,CveCampus) AsignaRecursosPropios(FteDeRecursos,PeriodoProyecto,ApCurso,ApGrupo,ListaRecRequeridos,ListaRecAsignados) TERMINA SI (ListaRecAsignados.ListaInstalaciones = NULL AND Parametro('AsigInstal') = 'SI') OR (ListaRecAsignados.ListaEquipos = NULL AND Parametro('AsigEq') = 'SI') OR (ListaRecAsignados.Instructor.Clave = 0 AND Parametro('AsigInstr') = 'SI') ENTONCES COMIENZA Libera(ListaRecAsignados.ListaInstalaciones) Libera(ListaRecAsignados.ListaEquipos) ListaRecAsignados.Instructor.Clave := 0 PuedeAsignarRecursos := FALSO TERMINA OTRO PuedeAsignarRecursos := CIERTOTERMINA

/*************************************************************************************************************************************************** Función: Asigna los recursos necesarios para impartir un curso tomandolos del inventario de instalaciones, equipos e instructores propiedad del

instituto y del cliente. La lista de recursos asignados puede ya traer algunos recursos asignados de proveedor, en este caso se asignan los

68

recursos faltantes y se busca una nueva asignación de recursos sustituyendo totalmente los ya asignados, de éstas dos opciones se toma la mejor encaso de que se permita la sustitución de recursos.

Fecha de actualización:*****************************************************************************************************************************************************/PROC AsignaRecursosPropios(FteDeRecursos,PeriodoProyecto,ApCurso,ApGrupo,ListaRecRequeridos,ListaRecAsignados)COMIENZA AsignaInstalacionesPropias(FteDeRecursos,PeriodoProyecto,ApGrupo,ListaRecRequeridos.ListaInstalRequeridas,ListaRecAsignados.ListaInstalaciones) AsignaEquiposPropios(FteDeRecursos,PeriodoProyecto,ApGrupo,ListaRecRequeridos.ListaEquiposRequeridos,ListaRecAsignados.ListaEquipos) AsignaInstructorPropio(FteDeRecursos,ApCurso,ApGrupo,ListaRecRequeridos.InstructoresPosibles.ListaInstructores,ListaRecAsignados.Instructor)

SI FteDeRecursos = 4 AND Parametro('SustituirRec') ENTONCES COMIENZA ListaRecAsigAux.ListaInstalaciones := NULL ListaRecAsigAux.ListaEquipos:= NULL ListaRecAsigAux.Instructor.Clave := 0 AsignaInstalacionesPropias(1,PeriodoProyecto,ApGrupo,ListaRecRequeridos.ListaInstalRequeridas, ListaRecAsigAux.ListaInstalaciones) AsignaEquiposPropios(1,PeriodoProyecto,ApGrupo,ListaRecRequeridos.ListaEquiposRequeridos, ListaRecAsigAux.ListaEquipos) AsignaInstructorPropio(1,ApCurso,ApGrupo,ListaRecRequeridos.InstructoresPosibles.ListaInstructores,ListaRecAsigAux.Instructor) ComparaPropuestas(ListaRecRequeridos,ListaRecAsignados,ListaRecAsigAux,ListaRecAsignados) TERMINA TERMINA

/*****************************************************************************************************************************************************Función: Verificar si un requerimiento de un tipo de instalación ya ha sido cubierto. La función devuelve verdadero cuando el requerimiento yaesta cubierto y FALSO cuando el requerimiento no ha sido cubierto.

*****************************************************************************************************************************************************/FUNCION InstalTipoAsignada(ApInstalReq,ListaInstalAsignadas,ApGrupo,PeriodoProyecto)COMIENZA ObtenDatosDeUsoInstal(ApInstalReq,ApGrupo,PeriodoProyecto,FechaHoraUso) Exito := FALSO ApInstal := ListaInstalAsignadas MIENTRAS ApInstal <> NULL And Exito = FALSO HAZ COMIENZA SI (ApInstal^.FechaIni = FechaHoraUso.FechaIni AND ApInstal^.FechaFin = FechaHoraUso.FechaFin AND ApInstal^.HoraIni = FechaHoraUso.HoraIni AND ApInstal^.HoraFin = FechaHoraUso.HoraFin AND ApInstal^.CveTipInstal = ApInstalReq^.CveTipInstalacion) ENTONCES Exito := CIERTO ApInstal := ApInstal^.Liga TERMINA InstalTipoAsignada := ExitoTERMINA

/***************************************************************************************************************************************************** Función: Asignar instalaciones necesarias para la impartición de un curso tomando el inventario propiedad del cliente y del instituto. Fecha de actualizacion:*****************************************************************************************************************************************************/PROC AsignaInstalacionesPropias(FteDeRecursos,PeriodoProyecto,ApGrupo,ListaInstalReq,VAR ListaInstalAsignadas)

69

COMIENZA ExistenInstalaciones := CIERTO ApInstalRequerida := ListaInstalReq Fecha.FechaIni := ApGrupo^.FechaIni Fecha.FechaFin := ApGrupo^.FechaFin MIENTRAS ApInstalRequerida <> NULL AND ExistenInstalaciones HAZ COMIENZA SI (FteDeRecursos = 1 OR FteDeRecursos = 3 OR (FteDeRecursos = 4 AND (InstalTipoAsignada(ApInstalRequerida,ListaInstalAsignadas,ApGrupo,PeriodoProyecto) = FALSO) ENTONCES COMIENZA Asignado := AsignaInstalTipoYaAsignada(PeriodoProyecto,ApGrupo,ApInstalRequerida,Fecha,ListaInstalAsignadas) SI (Asignado = FALSO) ENTONCES COMIENZA GeneraLtaInvenInstalPropias(ApInstalRequerida,ApGrupo^.CvePlantel,VAR ListaInstalExistentes) ApInstalacion := ListaInstalExistentes MIENTRAS ApInstalacion <> NIL AND Asignado = FALSO HAZ COMIENZA SI EsDisponibleInstal(PeriodoProyecto,ApInstalRequerida,ApInstalacion^.Clave,Fecha) ENTONCES COMIENZA ObtenDatosDeUsoInstal(ApInstalRequerida,ApGrupo,PeriodoProyecto,FechaHoraUso) Inserta(ApInstalRequerida^.CveTipInstalacion, ApInstalacion^.Clave, FechaHoraUso.FechaIni, FechaHoraUso.FechaFin, FechaHoraUso.HoraIni, FechaForaUso.HoraFin, ApInstalacion^.CveTipProced, ApInstalacion^.Costo, ApInstalacion^.Calificación, ListaInstalAsignadas) /* Inserta en lista ligada */ Asignado := CIERTO TERMINA ApInstalacion := ApInstalacion^.Liga TERMINA TERMINA SI Asignado = FALSO AND (FteDeRecursos = 1 OR FteDeRecursos = 4) ENTONCES ExistenInstalaciones = FALSO Libera(ListaInstalExistentes) TERMINA ApInstalRequerida := ApInstalRequerida^.Liga TERMINA SI ExistenInstalaciones = FALSO ENTONCES Libera(ListaInstalaciones)TERMINA

/***************************************************************************************************************************************************** Función: Tratar de asignar una instalación de un tipo requerido tomandola de las instalaciones del mismo tipo que ya fueron asignadas al grupo.

Fecha de actualización:*****************************************************************************************************************************************************/FUNCION AsignaInstalTipoYaAsignada(PeriodoProyecto,ApGrupo,ApInstalRequerida,Fecha,VAR ListaInstalAsignadas)COMIENZA InstalAsignada := FALSO ApInstalAsig := ListaInstalAsignadas MIENTRAS ApInstalAsig <> NULL AND InstalAsignada = FALSO HAZ COMIENZA SI ApInstalAsig^.CveTipInsta = ApInstalRequerida^.CveTipInstalacion AND (ApInstalAsig^.CveTipProced = 1 OR ApInstalAsig^.CveTipProced = 2) ENTONCES SI EsDisponibleInstal(PeriodoProyecto,ApInstalRequerida,ApInstalAsig^.Clave,Fecha) ENTONCES

70

COMIENZA ObtenDatosDeUsoInstal(ApInstalRequerida,ApGrupo,PeriodoProyecto,FechaHoraUso) CostoUso:= CostoPorHoraUsoInstal(ApInstalAsig^.Clave) * (ApInstalRequerida^.HoraFin - ApInstalRequerida^.HoraIni + 1) Inserta(ApInstalRequerida^.CveTipInstalacion, ApInstalAsig^.Clave, FechaHoraUso.FechaIni, FechaHoraUso.FechaFin, FechaHoraUso.HoraIni, FechaForaUso.HoraFin, ApInstalAsig^.CveTipProced, CostoUso, ApInstalAsig^.Calificación, ListaInstalaciones) InstalAsignada := CIERTO TERMINA ApInstalAsig := ApInstalAsig^.Liga TERMINA AsignaInstalTipoYaAsignada := InstalAsignadaTERMINA

/*****************************************************************************************************************************************************Función: Buscar en el inventario de instalaciones el costo por hora de una instalación.Fecha de actualización:

*****************************************************************************************************************************************************/FUNCION CostoPorHoraUsoInstal(ClaveInstalacion)COMIENZA CostoInstal := 0

SELECT Costo INTO CostoInstal FROM InvenInsta WHERE Clave = ClaveInstalacion

CostoPorHoraUsoInstal := CostoInstalTERMINA

71

/********************************************************************************************************************************************* Función: Obtener las fechas y horas reales de uso de una instalación. Éstas dependen de las horas en que se requieren y de las fechas en

las que se impartirá el curso es decir la fecha de inicio y la fecha del finalización del grupo propuesto. Fecha de actualización:*********************************************************************************************************************************************/PROC ObtenDatosDeUsoInstal(ApInstalReq,ApGrupo,PeriodoProyecto,VAR FechaHoraUso)COMIENZA DiaIni := FechaIniUso(ApInstalReq^.HoraIni,ApGrupo^.FechaIni,PeriodoProyecto) DiaFin := FechaFinUso(ApInstalReq^.HoraFin,ApFecha^.FechaIni,PeriodoProyecto) FechaHoraUso.FechaIni := ApGrupo^.FechaIni + DiaIni FechaHoraUso.HoraIni := (ApInstalReq.HoraIni MOD HORASPORDIA) + HORAINICLASES - 1 FechaHoraUso.FechaFin := ApGrupo^.FechaIni + DiaFin FechaHoraUso.HoraFin := (ApInstalReq.HoraFin MOD HORASPORDIA) + HORAINICLASES - 1TERMINA

/*********************************************************************************************************************************************Función: Generar el inventario de instalaciones de un tipo dado, ubicadas en un plantel y que son propiedad del ITM y TELMEX.

La lista del inventario de instalaciones se crea en orden de costo ascendente. Fecha de actualización:*********************************************************************************************************************************************/PROC GeneraLtaInvenInstalPropias(ApInstalReq,CvePlantel,VAR ListaInventarioInstal)COMIENZA ListaInventarioInstal := NULL HorasUsoInstal := ApInstalReq^.HoraFin - ApInstalReq^.HoraIni + 1 DECLARE CursorInvent CURSOR FOR SELECT Clave, CveTipProced, Costo, Calificacion FROM InvenInsta WHERE CveTipInsta = ApInstalReq^.CveTipInstalación AND CvePlantel = ClavePlantel AND (CveTipProcedInv = 1 OR CveTipProcedInv = 2) AND Estado ='A' /* El tipo de procedencia es 1 ITM 2 TELMEX. Estado = 'A' Estado activo */ ORDER BY Costo ASC, Calif DESC

OPEN CursorInvent FETCH CursorInvent INTO RegInventInsta

MIENTRAS sqlca.sqlcode = 0 HAZ COMIENZA Inserta(RegInventInsta.Clave, RegInventInsta.CveTipProced, RegInventInsta.Costo * HorasUsoInstal, RegInventInsta.Calificacion, ListaInventarioInstal) FETCH CursorInvent INTO RegInventInsta TERMINA CLOSE CursorInventTERMINA

72

/*****************************************************************************************************************************************************Función: Asignar equipos requeridos para la impartición de un curso tomando el inventario administrado de manera directa por el instituto.Fecha de actualización:

*****************************************************************************************************************************************************/PROC AsignaEquiposPropios(FteDeRecursos,PeriodoProyecto,ApGrupo,ListaEqpsReq,VAR ListaEquipos)COMIENZA ExistenEquipos := CIERTO ApEqpRequerido := ListaEqpsReq MIENTRAS ApEqpRequerido <> NULL AND ExistenEquipos = CIERTO HAZ COMIENZA SI FteDeRecursos = 4 ENTONCES NumEquiposAsig := NumEqpsAsigTipo(PeriodoProyecto,ApGrupo,ApEqpRequerido,ListaEquipos) OTRO NumEquiposAsig := 0 SI NumEquiposAsig < ApEqpRequerido^.NumEqpsxGrupo ENTONCES COMIENZA GeneraLtaInvenEqpsPropios(ApEqpRequerido^.CveTipEquipo,ApGrupo^.CvePlantel,ListaEqpsExistentes) ApEquipo := ListaEqpsExistentes MIENTRAS ApEquipo <> NULL AND NumEquiposAsig < ApEqpRequerido^.NumEqpsxGrupo HAZ COMIENZA SI EstaDisponibleEquipo(PeriodoProyecto,ApEquipo^.Clave,ApEqpRequerido,ApGrupo^.FechaIni) ENTONCES COMIENZA Inserta(ApEquipo^.Clave,ApEqpRequerido^.FechaIni,ApEqpRequerido.FechaFin,ListaEquipos) NumEquiposAsig := NumEquiposAsig + 1 TERMINA ApEquipo := ApEquipo^.Liga TERMINA SI NumEquiposAsig < ApEqpRequerido^.NumEqpsxGrupo AND (FteDeRecursos = 1 OR FteDeRecursos = 4 )ENTONCES ExistenEquipos := FALSO Libera(ListaEqpsExistentes) TERMINA ApEqpRequerido := ApEqpRequerido^.Liga TERMINA SI ExistenEquipos = FALSO ENTONCES Libera(ListaEquipos)TERMINA

73

/***************************************************************************************************************************************************** Función: Verificar cuantos equipos de un tipo ya han sido asignados a un grupo, es decir cuantos equipos de un tipo dado existen para cubrir un

requerimientoFecha de actualización:

*****************************************************************************************************************************************************/FUNCION NumEqpsAsigTipo(PeriodoProyecto,ApGrupo,ApEqpReq,ListaEqpsAsig)COMIENZA NumEqps := 0 ApEqp := ListaEqpsAsig MIENTRAS ApEqp <> NULL HAZ COMIENZA SI (ApEqp^.FechaIni = ApEqpReq^.FechaIni AND ApEqp^.FechaFin = ApEqpReq^.FechaFin AND ApEqp^.CveTipEquipo = ApEqpReq^.CveTipEquipo) ENTONCES NumEqps := NumEqps + 1 ApEqp := ApEqp^.Liga TERMINA NumEqpsAsigTipo := NumEqpsTERMINA

/*****************************************************************************************************************************************************Función: Generar el inventario de equipos existentes en un plantel cuya procedencia se ITM o TELMEXFecha de actualización:

*****************************************************************************************************************************************************/PROC GeneraLtaInvenEqpsPropios(ApEqpReq,CvePlantel,VAR ListaInvenEqps)COMIENZA DiasDeUso := ApEqpReq^.FechaFin - ApEqpReq^.FechaIni + 1 ListaInvenEqps := NULL DECLARE CursorInvent CURSOR FOR SELECT Clave, CveTipProcedInv, Costo FROM InvenEq WHERE CveTipEquipo = ApEqpReq^.CveTipoEquipo AND CvePlantel = CvePlantel AND (CveTipProced = 1 OR CveTipProced = 2) ORDER BY Costo /* El tipo de procedencia es 1 ITM 2 TELMEX. */ OPEN CursorInvent FETCH CursorInvent INTO RegInventEqp

MIENTRAS sqlca.sqlcode = 0 HAZ COMIENZA Inserta(RegInventEqp.Clave, RegInventEqp.CveTipProced, RegInventEqp.Costo * DiasDeUso, ListaInvenEqps) FETCH CursorInvent INTO RegInventEqp TERMINA CLOSE CursorInventTERMINA

74

/*********************************************************************************************************************************************Función: Verificar si un equipo del inventario esta disponible para ser asignado a un grupo.Fecha de actualización:

*********************************************************************************************************************************************/FUNCION EstaDisponibleEquipo(PeriodoProyecto,CveEquipo,ApEqpRequerido,FechaIniGpo)COMIENZA NumPeriodos := 0 SELECT COUNT(*) INTO NumPeriodos FROM PerIndispEquip WHERE CveEq = CveEquipo AND ((FechaIni >= ApEqpRequerido.FechaIni AND FechaFin <= ApEqpRequerido.FechaFin) OR (FechaFin >= ApEqpRequerido.FechaIni AND FechaFin <= ApEqpRequerido.FechaFin) OR (FechaIni <= ApEqpRequerido.FechaFin AND FechaIni >= ApEqpRequerido.FechaIni)) SI NumPeriodos = 0 ENTONCES EstaDisponibleEquipo := CIERTO OTRO EstaDisponibleEquipo := FALSOTERMINA

/*********************************************************************************************************************************************Función: Obtener las fechas reales, con respecto al inicio del curso y las horas en que se solicita un equipo, en las que se desea que un

equipo del inventario esté disponible.Fecha de actualización:

*********************************************************************************************************************************************/PROC ObtenDatosDeUsoEqp(ApEqpRequerido,PeriodoProyecto,FechaIniGpo,VAR FechaUso)COMIENZA DiaIniRel := FechaIniUso(ApEqpRequerido^.HoraIni,FechaIniGpo,PeriodoProyecto) DiaFinRel := FechaFinUso(ApEqpRequerido^.HoraFin,FechaIniGpo,PeriodoProyecto) FechaUso.FechaIni := FechaIniGpo + DiaIniRel FechaUso.FechaFin := FechaIniGpo + DiaFinRelTERMINA

75

/*********************************************************************************************************************************************Función: Asignar instructor a un grupoFecha de actualización:

*********************************************************************************************************************************************/PROC AsignaInstructorPropio(FteDeRecurso,ApCurso,ApGrupo,ListaInstructores,VAR InstrAsignado)COMIENZA SI (FteDeRecursos = 1 OR FteDeRecursos = 3 OR (FteDeRecursos = 4 AND InstrAsignado.Clave = 0)) ENTONCES COMIENZA DiasParaMov := Parametro('DiasTranslado') CalculaCostoAsigGpoInstr(ApCurso,ListaInstructores,ApGrupo) OrdenaLtaInstrPorCostoMin(ListaInstructores) /* Es ordenar una lista ligada en orden ascendente de acuerdo a un campo */ Asignado := FALSO ApInstructor := ListaInstructores MIENTRAS ApInstructor <> NULL AND Asignado = FALSO HAZ SI EstaDisponibleInstr(ApInstructor,ApGrupo^.FechaIni - DiasParaMov,ApGrupo^.FechaFin + DiasParaMov) ENTONCES COMIENZA Asignado := CIERTO InstrAsignado.Clave := ApInstructor^.Clave InstrAsignado.FechaIni := ApGrupo^.FechaIni InstrAsignado.FechaFin := ApGrupo^.FechaFin InstrAsignado.HoraIni := HORAINICLASES InstrAsignado.HoraFin := (ApCurso^.Duracion MOD HORASPORDIA) + HORAINICLASES SI ApIntructor^.CveTipInstr = 1 ENTONCES /* Tipo de instructor propio */ InstrAsignado.CveTipProced := 1 /* Tipo de procedencia ITM */ OTRO InstrAsignado.CveTipProced := 2 /* Tipo de procedencia Telmex */ InstrAsignado.Importe := (ApInstructor^.CostoInstruccionHr * ApCurso^.Duracion) + ApInstructor^.Viaticos InstrAsignado.Calificacion := ApInstructor^.Calificacion TERMINA OTRO ApInstructor := ApInstructor^.Liga TERMINATERMINA

76

/***************************************************************************************************************************************************** Función: Calcular los costos de asignación de todos los instructores posibles de un curso a un grupo dado. Estos costos se obtienen aplicando

la función de asignación de instructor que depende de la calidad del instructor, los costos de los viáticos y el costo por concepto de sueldo uhonorarios del instructor por la impartición del curso.Fecha de actualización:

*****************************************************************************************************************************************************/PROC CalculaCostoAsigGpoInstr(ApCurso,ListaInstructores,ApGrupo)COMIENZA FactorCosto := Parametro('FactorCInstr')/100 FactorCalidad := 1 - FactorCosto ApInstructor := ListaInstructores DatosFuncionGLB.CostoMaxInstr := 0

MIENTRAS ApInstructor <> NULL HAZ COMIENZA SI ApInstructor^.CveTipInstr = 1 ENTONCES /* Un intructor propio es un recurso humano cuyo tipo de personal es confianza */ TipoEmp := 2 /* Tipo de personal confianza */ OTRO TipoEmp := ObtenTipoEmpTelmex(ApInstructor^.CveRecurso) ApInstructor^.Viaticos := FViaticos(ApGrupo^.FechaIni,ApGrupo^.FechaFin,ApInstructor^.CveLocOrigen,ApGrupo^.CveLocalidad,TipoEmp) SI ((ApInstructor^.Viaticos + (ApInstructor^.CostoInstruccionHr * ApCurso^.Duracion)) > DatosFuncionGLB.CostoMaxInstr) ENTONCES DatosFuncionGLB.CostoMaxInstr := ApInstructor^.Viaticos + (ApInstructor^.CostoInstruccionHr * ApCurso^.Duracion) ApInstructor := ApInstructor^.Liga TERMINA

ApInstructor := ListaInstructores MIENTRAS ApInstructor <> NULL HAZ COMIENZA ApInstructor^.CostoAsig := FCostoAsigInstr(FactorCalidad,FactorCosto,ApInstructor^.Viaticos + (ApInstructor^.CostoInstruccionHr * ApCurso^.Duracion),ApInstructor^.Calificacion,DatosFuncionGLB.CostoMaxInstr) ApInstructor := ApInstructor^.Liga TERMINATERMINA/*********************************************************************************************************************************************

Función: Obtener el tipo de empleado bajo el cual se clasifica un recurso humano de OCMFecha de actualización:

*********************************************************************************************************************************************/PROC ObtenTipoEmpTelmex(CveRecurso)COMIENZA SELECT CveTipPersonal INTO TipEmp FROM Puestos WHERE Clave = (SELECT CvePuesto FROM RecHumanos WHERE Clave = CveRecurso)

ObtenTipoEmpTelmex := TipoEmpTERMINA

77

/*********************************************************************************************************************************************Función: Calcular el valor del costo de asignación de un instructor a un grupo aplicando la función dependiante del costo del curso por

concepto de cotización del instructor y la calidad del instructor, estos parametros se encuantran parametrizados.Fecha de actualización:

*********************************************************************************************************************************************/FCostoAsigInstr(FactorCalidad,FactorCosto,CostoDeInstruccion,IndiceDeCalidad,CostoMaxInstr)COMIENZA SI ((FactorCalidad * IndiceDeCalidad) + CostoMaxInstr) = 0 ENTONCES FCostoAsigInstr := INFINITO OTRO FCostoAsigInstr := (FactorCosto * CostoDeInstruccion)) / ((FactorCalidad * IndiceDeCalidad) + CostoMaxInstr)

TERMINA

/*********************************************************************************************************************************************Función: Verificar si un instructor esta disponible dentro de un periodo de tiempo especificado entre el intervalo de FechaIni y FechaFinNOTA: Si un instructor es propio (CveTipInstr = 1) todos sus periodos de indisponibilidad se encuentran agrupados en la tabla de

indisponibilidades asociadas al instructor. Cuando el instructor es un recurso humano del cliente (OCM) sus periodos de indisponibilidad seagrupan por los periodos de indisponibilidad como instructor, periodos de indisponibilidad como recurso humano y periodos de insdisponibilidad de suunidad de negocio o especialidad.

Fecha de actualización:*********************************************************************************************************************************************/FUNCION EstaDisponibleInstr(ApInstructor,FechaIni,FechaFin)COMIENZA SI ApInstructor^.CveTipInstr = 1 ENTONCES EstaDisponibleInstr := EsDisponibleInstructor(ApInstructor^.Clave,FechaIni,FechaFin) OTRO EstaDisponibleInstr := (EsDisponibleRecHumT(ApInstructor^.CveRecurso,FechaIni,FechaFin) AND NOT(EsPeriodoCritico(ApInstructor^.CveRecurso,FechaIni,FechaFin) AND EsDisponibleInstructor(ApInstructor^.Clave,FechaIni,FechaFin))TERMINA

/*********************************************************************************************************************************************Función: Verificar si un instructor esta o no disponible en el periodo comprendido entre FechaInicio y FechaFinal.Fecha de actualización:

*********************************************************************************************************************************************/

FUNCION EsDisponibleInstructor(CveInstr,FechaInicio,FechaFinal)COMIENZA NumPeriodos := 0 SELECT COUNT(*) INTO NumPeriodos FROM PerIndispInstr WHERE (FechaIni <= FechaFinal AND FechaFin >= FechaInicio) (CveInstruc = CveInstr)

SI NumPeriodos = 0 ENTONCES EsDisponibleInstructor := CIERTO OTRO EsDisponibleInstructor := FALSO

78

TERMINA

/*****************************************************************************************************************************************************Función: Verificar si todos los requerimiento de equipo se han satisfechoFecha de actualización:

*****************************************************************************************************************************************************/FUNCION TodosEquiposAsignados(PeriodoProyecto,ApGrupo,ListaEquiposReq,ListaEquiposAsig)COMIENZA FaltanEquipos := FALSO ApEqpReq := ListaEquiposReq MIENTRAS ApEqpReq <> NULL AND FaltanEquipos = FALSO COMIENZA NumEquiposAsig := NumEqpsAsigTipo(PeriodoProyecto,ApGrupo,ApEqpReq,ListaEquiposAsig) SI NumEqpsAsig < ApEqpReq^.NumEqpsxGrupo ENTONCES FaltanEquipos := CIERTO ApEqpReq := ApEqpReq^.Liga TERMINA TodosEquiposAsignados := NO(FaltanEquipos)TERMINA

/*****************************************************************************************************************************************************Función:Fecha de actualización:

*****************************************************************************************************************************************************/FUNCION TodasInstalAsignadas(PeriodoProyecto,ApGrupo,ListaInstalReq,ListaInstalAsig)COMIENZA FaltanInstalaciones := FALSO ApInstalReq := ListaInstalReq MIENTRAS ApInstalReq <> NULL AND FaltanInstalaciones = FALSO HAZ COMIENZA SI (InstalTipoAsignada(ApInstalReq,ListaInstalAsig,ApGrupo,PeriodoProyecto) = FALSO ENTONCES FaltanInstalaciones := CIERTO ApInstalReq := ApInstalReq^.Liga TERMINA TodasInstalAsignadas := NO(FaltanInstalaciones)TERMINA

79

/***************************************************************************************************************************************************** Función: Crear la lista de proveedores de capacitación posibles para impartir un curso. Los proveedores se eligen de una localidad, de un estado

federativo o de todo el campus dependiendo del parámetro de coberturaFecha de actualización:

*****************************************************************************************************************************************************/PROC ObtenProvPosibles(CveCampus,CveLocalidad,ApCurso, VAR ListaProveedores)COMIENZA Cobertura := Parametro('CoberturaRec') CASO DE (Cobertura) COMIENZA 1: SI(ListaProveedores <> NULL) ENTONCES Libera(ListaProveedores) ObtenProvPosLocalidad(CveLocalidad,ApCurso,ListaProveedores)

2: SI(ListaProveedores <> NULL) ENTONCES Libera(ListaProveedores) ObtenProvPosEdoFederativo(CveLocalidad,ApCurso,ListaProveedores) 3: SI(ListaProveedores = NULL) ENTONCES ObtenProvPosCampus(CveCampus,Apcurso,ListaProveedores) TERMINATERMINA

/*****************************************************************************************************************************************************Función: Obtener el tipo de cotización de un proveedor que genera el costo mínimoFecha de actualización:

*****************************************************************************************************************************************************/PROC ObtenCostoCotizMinProv(ApProv,ApCurso)COMIENZA CostoPorCotiz := INFINITO TipoCotizAux := 0

DECLARE CursorCotizaciones CURSOR FOR SELECT CveTipCotizacion, Importe FROM CotizacionesProvCurs WHERE CveProveedor = ApProveedor^.Clave AND ClaveCurso = ApCurso^.Codigo

OPEN CursorCotizaciones FETCH CursorCotizaciones INTO TipoCotiz,Costo

MIENTRAS sqlca.sqlcode = 0 HAZ COMIENZA CASO TipoCotiz COMIENZA 1: CostoAux := Costo * ApCurso^.Duracion 2: CoxtoAux := Costo * ApCurso^.MaxParticipantes 3: CostoAux := Costo TERMINA SI CostoAux < CostoPorCotiz ENTONCES COMIENZA CostoProCotiz := CostoAux TipoCotizAux := TipoCotiz

80

TERMINA FETCH CursorCotizaciones INTO TipoCotiz,Costo TERMINA CLOSE CursorCotizaciones ApProveedor^.CveTipCotiz := TipoCotizAux ApProveedor^.CostoPorCotiz := CostoPorCotizTERMINA

/*****************************************************************************************************************************************************Función: Generar una lista de recursos requeridos a un grupo. Esta lista solo contiene los recursos que faltan de asignar al grupo.Fecha de actualización:

*****************************************************************************************************************************************************/PROC GeneraListaReqGpo(ApGrupo,PeriodoProyecto,ListaRecReq,ListaRecAsig, VAR ListaRecGpo)COMIENZA GeneraListaInstalReqGpo(ListaRecReq.ListaInstalRequeridas,ListaRecAsig.ListaInstalaciones,ListaReqGpo.ListaInstalRequeridas,ApGrupo, PeriodoProyecto) GeneraListaEqpReqGpo(ListaRecReq.ListaEquiposRequeridos,ListaRecAsig.ListaEquipos,ListaReqGpo.ListaEquiposRequeridos,ApGrupo,PeriodoProyecto)TERMINA

/***************************************************************************************************************************************************** Función: Generar una lista de instalaciones requeridas para un grupo. La lista contendrá solo los requerimientos de instalaciones que no hayan

sido cubiertas aun para el grupo.Fecha de actualización:

*****************************************************************************************************************************************************/PROC GeneraListaInstalReqGpo(ListaInstalReqCurso,ListaInstalAsigGpo,VAR ListaInstalReqGpo,ApGrupo,PeriodoProyecto)COMIENZA ListaInstalReqGpo := NULL ApInstalReqCurso := ListaInstalReqCurso MIENTRAS ApInstalReqCurso <> NULL HAZ COMIENZA SI InstalTipoAsignada(ApInstalReqCurso,ListaInstalAsigGpo,ApGrupo,PeriodoProyecto) = FALSO ENTONCES Inserta(ApInstalReqCurso^.CveTipInstalacion, ApInstalReqCurso^.HoraIni, ApInstalReqCurso^.HoraFin, ListaInstalReqGpo) ApInstalReqCurso := ApInstalReqCurso^.Liga TERMINATERMINA

81

/***************************************************************************************************************************************************** Función: Generar una lista de equipos requeridos para un grupo. La lista contendrá solo los requerimientos de equipo que no hayan sido cubiertos

aun para el grupo.Fecha de actualización:

*****************************************************************************************************************************************************/PROC GeneraListaEqpReqGpo(ListaEqpReqCurso,ListaEqpAsigGpo, VAR ListaEqpReqGpo,ApGrupo,PeriodoProyecto)COMIENZA ListaEqpReqGpo := NULL ApEqpReqGpo := ListaEqpRecurso MIENTRAS ApEqpReqCurso <> NULL HAZ COMIENZA NumEqpAsig := NumEqpsAsigTipo(PeriodoProyecto,ApGrupo,ApEqpReqCurso,ListaEqpAsigGpo) SI NumEqpAsig < ApEqpReqCurso^.NumEqpsxGrupo ENTONCES Inserta(ApEqpReqCurso^.CveTipEquipo,ApEqpReqCurso^.NumEqpsxGrupo-NumEqpAsig,ApEqpReqCurso^.HoraIni,ApEqpReqCurso^.HoraFin, ListaEqpReqGpo) ApEqpReqCurso := ApEqpReqCurso^.Liga TERMINATERMINA

/***************************************************************************************************************************************************** Función: Comparar dos listas de recursos asignados y legir la mejor. Para elegir la mejor lista de recursos asignados se aplican funciones

matemáticas en las que se considera el numero de recursos asignados en comparación con los requeridos, es costo de los recursos asignados y lacalidad de éstos.Fecha de actualización:

*****************************************************************************************************************************************************/PROC ComparaPropuestas(ListaRecRequeridos,VAR ListaRecAsig1,VAR ListaRecAsig2, VAR ListaRecAsigReal)COMIENZA /* Se preparan los costos y la calificación en los valores extremos para los casos en que las propuestas no tengan instructor asignado */ SI ListaRecAsig1.Instructor.Clave = 0 ENTONCES COMIENZA ListaRecAsig1.Instructor.Importe := INFINITO ListaRecAsig1.Instructor.Calificacion := 0 TERMINA SI ListaRecAsig2.Instructor.Clave = 0 ENTONCES COMIENZA ListaRecAsig1.Instructor.Importe := INFINITO ListaRecAsig1.Instructor.Calificacion := 0 TERMINA

NumEqpReq := CuentaEquiposRequeridos(ListaRecRequeridos.ListaEquiposRequeridos) NumInstalReq := TamLista(ListaRecRequeridos.ListaInstalRequeridos) /* Cuenta el número de nodos de la lista ligada */ NumEqpAsig1 := CuentaEqpsAsignados(ListaRecAsig1.ListaEquipos,CostoGlbEqpAsig1) NumEqpAsig2 := CuentaEqpsAsignados(ListaRecAsig2.ListaEquipos,CostoGlbEqpAsig2) ObtenDatosCompInstalAsig(ListaRecAsig1.ListaInstalaciones, CalifPromInstal1, CostoInstal1, NumInstalAsig1) ObtenDatosCompInstalAsig(ListaRecAsig2.ListaInstalaciones, CalifPromInstal2, CostoInstal2, NumInstalAsig2) CostoInstruccion1 := ListaRecAsig1.Instructor.Importe CostoInstruccion2 := ListaRecAsig2.Instructor.Importe

SI CostoInstruccion1 >= CostoInstruccion2 ENTONCES CMaxInstruccion := CostoInstruccion1 OTRO

82

CMaxInstruccion := CostoInstruccion2

SI CostoInstal1 >= CostoInstal2 ENTONCES CMaxInstal := CostoInstal1 OTRO CMaxInstal := CostoInstal2

FactorCostoIntr := Parametro('FactorCInstr')/100 FactorCostoInstal := Parametro('FactorCInsta')/100

FactorNormalIntr := FCostoAsigInstr(1-FactorCostoInstr,FactorCostoInstr,CostoInstruccion1,ListaRecAsig1.Instructor.Calificacion,CMaxInstruccion) FactorNormalAux := FCostoAsigInstr(1-FactorCostoInstr,FactorCostoInstr,CostoInstruccion2,ListaRecAsig2.Instructor.Calificacion,CMaxInstruccion) SI FactorNormalAux > FactorNormalInstr ENTONCES FactorNormalInstr := FactorNormalAux

FactorNormalEqp := FactorDispCostoEq(NumEqpReq, NumEqpAsig1, CostoGlbEqpAsig1) FactorNormalAux := FactorDispCostoEq(NumEqpReq, NumEqpAsig2, CostoGlbEqpAsig2) SI FactorNormalAux > FactorNormalEqp ENTONCES FactorNormalEqp := FactorNormalAux

FactorNormalInstal := FactorDispCostoInstal(NumInstalReq, NumInstalAsig1, CostoInstal1, CalifPromInstal1, CMaxInstal) FactorNormalAux := FactorDispCostoInstal(NumInstalReq, NumInstalAsig2, CostoInstal2, CalifPromInstal2, CMaxInstal) SI FactorNormalAux > FactorNormalInstal ENTONCES FactorNormalInstal := FactorNormalAux

FactorCalidadPropuesta1 := FDispCostoEqNormal(FactorNormalEq, NumEqpReq, NumEqpAsig1, CostoGlbEqpAsig1) + FDispCostoInstalNormal(FactorNormalInstal, NumInstalReq, NumInstalAsig1, CostoInstal1,CalifPromInstal1) + FCostoAsigInstrNormal(FactorNormalInstr, CostoInstruccion1, ListaRecAsig1.Instructor.Calificacion, CMaxInstruccion)

FactorCalidadPropuesta2 := FDispCostoEqNormal(FactorNormalEq, NumEqpReq, NumEqpAsig2, CostoGlbEqpAsig2) + FDispCostoInstalNormal(FactorNormalInstal, NumInstalReq, NumInstalAsig2, CostoInstal2, CalifPromInstal2) + FCostoAsigInstrNormal(FactorNormalInstr, CostoInstruccion2, ListaRecAsig2.Instructor.Calificacion, CMaxInstruccion)

SI FactorCalidadPropuesta1 >= FactorCalidadPropuesta2 ENTONCES COMIENZA ListaRecAsigReal.ListaInstalaciones := ListaRecAsig1.ListaInstalaciones ListaRecAsigReal.ListaEquipos := ListaRecAsig1.ListaEquipos CopiaMem(ListaRecAsig1.Instructor,ListaRecAsigReal.Instructor) /* CopiaMem(Origen,Destino) copiar los campos de los registros */ Libera(ListaRecAsig2.ListaInstalaciones) Libera(ListaRecAsig2.ListaEquipos) ListaRecAsig2.Instructor.Clave := 0

TERMINA OTRO COMIENZA ListaRecAsigReal.ListaInstalaciones := ListaRecAsig2.ListaInstalaciones ListaRecAsigReal.ListaEquipos := ListaRecAsig2.ListaEquipos CopiaMem(ListaRecAsig2.Instructor,ListaRecAsigReal.Instructor) /* CopiaMem(Origen,Destino) copiar los campos de los registros */ Libera(ListaRecAsig1.ListaInstalaciones) Libera(ListaRecAsig1.ListaEquipos) ListaRecAsig1.Instructor.Clave := 0

TERMINA

83

TERMINA

/***************************************************************************************************************************************************** Función: Cuenta los equipos requeridos para la inparticion de un curso. Esta es la suma de los equipos solicitados por requerimiento

Fecha de actualización:*****************************************************************************************************************************************************/FUNCION CuentaEquiposRequeridos(ListaEquiposRequeridos)COMIENZA NumEquipos := 0 ApEqpReq := ListaEquiposRequeridos MIENTRAS ApEqpReq <> NULL HAZ COMIENZA NumEquipos := NumEquipos + ApEqpReq^.NumEqpsxGrupo ApEqpReq := ApEqpReq^.Liga TERMINA CuentaEquiposRequeridos := NumEquiposTERMINA

/***************************************************************************************************************************************************** Función: Cuenta los equipos asignados a un grupo y da el costo total de éstos.

Fecha de actualización:*****************************************************************************************************************************************************/FUNCION CuentaEqpsAsignados(ListaEquipos, VAR CostoGlbEqpAsig)COMIENZA NumEquipos := 0 CostoGlbEqpAsig := 0 ApEquipo := ListaEquipos MIENTRAS ApEquipo <> NULL HAZ COMIENZA NumEquipos := NumEquipos + 1 CostoGlbEqpAsig := CostoGlbEqpAsig + ApEquipo^.Importe ApEquipo := ApEquipo^.Liga TERMINA CuentaEqpsAsignados := NumEquiposTERMINA/***************************************************************************************************************************************************** Función: Dar el costo, el promedio de las calificaciones y el numero de instalaciones asignadas.

Fecha de actualización:*****************************************************************************************************************************************************/

PROC ObtenDatosCompInstalAsig(ListaInstalaciones, VAR CalifPromInstal, VAR CostoInstal, VAR NumInstalAsig)COMIENZA CalifPromInstal := 0 CostoInstal := 0 NumInstalAsig := 0 SI ListaInstalaciones <> NULL ENTONCES COMIENZA ApInstal := ListaInstalaciones MIENTRAS ApInstal <> NULL HAZ COMIENZA

84

CalifPromInstal := ApInstal^.Calificacion + CalifPromInstal CostoInstal := ApInstal^.Importe + CostoInstal NumInstalAsig := NumInstalAsig + 1 ApInstal := ApInstal^.Liga TERMINA CalifPromInstal := CalifPromInstal / NumInstalAsig TERMINATERMINA

/***************************************************************************************************************************************************** Función: obtener el cálculo de los costos de viáticos de transporte y hospedaje para el translado y permanencia de un proveedor de su localidad

de origen a la localidad destino que es en la que se impartirá el curso.Fecha de actualización: 09/03/94

*****************************************************************************************************************************************************/FUNCION FViaticosProv(FechaIni,FechaFin,CveLocOrigen,CveLocDestino,TipoFiscal)COMIENZA SI DebePagarViaticos(CveLocOrigen,CveLocDestino) ENTONCES COMIENZA DuracionCurso := FechaFin - FechaIni + 1 /* El uno que se suma es para contar el dia de inicio */

SELECT SUM(Importe) INTO CostosFijosxDia FROM CuotasTipPersonal WHERE CveTipoFuscal = Tipofiscal

SELECT Importe INTO CostoHospedajexDia FROM TarifasHospedaje WHERE CveLocalidad = CveLocDestino

CostoTransporte := FCostoTrasp(CveLocOrigen,CveLocDestino) FViaticosProv := DuracionCurso * (CostosFijosxDia + CostoHospedajexDia) + 2 * CostoTransporte + CostosFijosxDia/2 /* Se suman la mitad de los costos fijos por dia, por el dia en que se regresa */ TERMINA OTRO FViaticos := 0 /* De la localidad origen a la localidad destino no se pagan viáticos */TERMINA

C-1

CCCNombre de la tabla Nombre físico

Areas de ITM AreasITM

Actividades de trabajo ActTrabajo

Actualizaciones a cursos ActualizacionCurs

Acuerdos y lineamientos AcuerdosLineam

Areas de conocimiento AreasConoc

Areas de estudio AreasEstudio

Areas productivas AreasProduc

Campus Campus

Categorias Categorias

Centros de trabajo CentrosTrab

Componentes de la carta descriptiva CompCartaDesc

Conocimientos instructores ConocesInstruc

Conocimientos y habilidades ConocHab

Costos adicionales de grupos CostosAdicionales

Curriculas del personal de confianza CurrConf

Curriculas del personal de confianza/Prerrequisitos del curso CuurConfPrerr

Curriculas del personal sindicalizado CurrSind

Curriculas del personal sindicalizado-Prerrequisitos del curso CurrSindPrerr

Cursos Cursos

Cursos/Tipos de personal CursTipPersonal

Direcciones Dots

Escuelas de formación EscuelasForm

Especialidades Especialidades

Estados de actividades EstActividad

Estados de ordenes de trabajo EstOrdenTrab

Estados de un curso EstCurs

Estatus analisis solicitudes EstatusAnalis

Estatus analisis prerrequisitos EstatusPrerr

Estatis de proyectos de capacitación EstProyCapacit

Apéndice.Diccionario de datos

Apéndice C. Diccionario de datos

C-2

Estatus de requerimientos EstatusReq

Estudios realizados EstudiosRealiz

Exámes Examenes

Exámenes/Grupos ExamenGrupos

Exámenes/Preguntas ExamenPregunta

Funciones y procedimientos de trabajo FuncProcTrab

Funciones y procedimienos de trabajo/Categorias FuncProcCategorias

Funciones y procedimienos de trabajo/Niveles FuncProcNiveles

Grupos de curso GruposDeCurso

Grupos/Recursos humanos del cliente GruposRH

Grupos con equipo real GruposEquipReal

Grupos con instalaciones improvisadas GruposInstalImprov

Grupos con instalaciones reales GruposInstalReal

Historia de los prerrequisitos del plan de carrera del personalsindicalizado

HistPrerrSind

Historia de los prerrequisitos del plan del carrera para el personal deconfianza

HistPrerrConf

Historia de los prerrequisitos del tronco básico del personal sindicalizado HistPrerrTBSind

Historia de los prerrequisitos del tronco básico para el personal deconfianza

HistPrerrTBConf

Historial de capacitación del istructor HistInstructor

Historial de capacitación del participante HistParticip

Historial de capacitación del proveedor HistProveedor

Historia de la curricula de confianza HistCurrConf

Historial de la curricula sidicalizada HistCurrSind

Historial del tronco básico de confianza HistTroncBasConf

Historial del tronco básico sindicalizado HistTroncBasSind

Historial laboral del personal de confianza HistLabConf

Historial laboral del personal sindicalizado HistLabSind

Instalaciones improvisadas InstalImprov

Institucones educativas InstitEduc

Instructores Instructores

Instructores/Cursos InstructorCurs

Instructores/Grupos InstructorGrupos

Inventario de equipos InvenEq

Inventario de quipos/Proveedores InvenInstalProv

Localidades Localidades

Materiales de participantes MaterialPartic

Materiales didacticos MaterialDidac

Materiales didacticos/temas MatDidacTemas

Apéndice C. Diccionario de datos

C-3

Modalidades de capacitación ModalCapac

Necesidades de material para cursos NecMaterialCurs

Niveles Niveles

Niveles de escolaridad NivEscolar

Niveles del curso NivelCurs

Niveles de ITM NivelesITM

Niveles jerarquicos NivJerarq

Objetivos particulares ObjetivosPart

Objetivos particulares Cursos ObjetivosPartCurs

Opciones de respuesta OpcionesResp

Ordenes de servicio OrdenesServ

Ordenes de viaticos OrdenesViat

Origen de requerimientos OrigenRequerim

Periodos criticos de las unidades de negocio PerCritUniNeg

Periodo critico por especialidad PerCitEspec

Periodos de indisponibilidad de equipo PerIndispEquip

Periodos de indisponibilidad de instalaciones PerIndispInstal

Periodos de indisponibilidad de instructores PerIndispInstr

Periodos de insdisponibilidad de proveedores PerIndispProv

Periodos indisponibilidad de recursos humanos PerIndispRH

Planteles Planteles

Preguntas Preguntas

Proveedores Proveedores

Proveedores/Cursos ProveedorCurs

Proveedores/Grupos ProveedorGrupos

Proveedores/Tipos de proveedores ProvTipoProv

Proyectos de capacitación ProyCapacit

Proyectos de capacitación/centros de trabajo ProyCentrosTrab

Proyectos de cpapacitación/Centros de trabajo/Niveles impactados ProyCenTrabNiv

Proyectos de cpapacitación/Centros de trabajo/Categoriasimpactados

ProyCenTrabCateg

Proyectos de capacitación proveedores ProyProveedor

Proyectos de capacitación/Lideres ProLideres

Proyectos de capacitación/Responsables ProyResp

Recursos humanos de ITM RecHumanosITM

Recursos humanso del cliente RecHumanos

Requerimientos Requerimientos

Requerimientos/Categorias ReqCategorias

Requerimientos /Cursos ReqCursos

Apéndice C. Diccionario de datos

C-4

Requerimientos/Cursos/RH ReqCursosRH

Requerimientos/Cursos/RH/Prerrequisitos ReqCursosRHPrerr

Requerimientos/Niveles ReqNiveles

Requerimientos de equipo para cursos ReqEqCurs

Resultados de las evaluaciones de los instructores ResultEvalInstr

Resultados de las evaluaciones de los participantes ResultEValParticip

Resultados de las evaluaciones de los proveedores ResultEvalProv

Solicitudes de capacitación SoliCapacit

Solicitudes de capacitación/Categorias SoliCapacitCateg

Solicitudes de capacitación/Niveles SoliCapacitniv

Solicitudes de capacitación /Recursos humanos SoliRH

Solicitudes de capacitación/Recursos humanos/Prerrequisitos SoliRHPrerr

Subdirecciones Sots

Subtemas SubtemasDeCurso

Tecnologias/Temas TecnologiasTemas

TecnologiasEducativas TecnolEducat

Temas de curso TemasDeCurso

TemasGenericos TemasGen

Tipos de cobertura TipCobertura

Tipos de cursos TipCurs

Tipos de equipo TipEquipos

Tipos de evaluación TipEvalua

Tipos de instalaciones TipInstalaciones

Tipos de instructores TipInstructores

Tipos de movimientos TipMovimiento

Tipos de participantes TipParticip

Tipos de personal TipPersonal

Tipos de preguntas TipPreguntas

Tipos de procedencia TipProced

Tipos de proveedor TipProveedor

Tipos de proyectos TipTpoyectos

Tronco básico del personal de confianza TroncoBasConf

Tronco básico del personal de confianza/Prerrequisitos del curso TroncoBasconfPrerr

Tronco básico del personal sindicalizado TroncoBasSind

Tronco básico del personal sindicalizado/Prerrequisitos de curso TroncBasSindPrerr

Unidades de negocio UnidNegocio

C-5

Nombre de la tabla Campo Tipo Llaveprima-

ria

Llaveforánea

AreasITM Clave Smallint(3) P

Descrip Char(50)Acttrabajo Clave integer(8) P

Descrip char(50)Importancia Real (2,2)Frecuencia Real (2,2)GradoConoc Real(2,2)CveFuncProcTrab integer(8)

ActualizacionCurs Clave Integer (8) P

Fecha DateDescripComp char(80)CveComponente Integer(8)CveCompCartaDesc Smallint(2) P

CveTipoMovimiento Smallint(2) P

CodigoCurso integer(8) P

AcuerdosLineam Clave integer(8) P

Descrip Char(40)CveProyCapacit Integer(5) P

AreasConoc Clave Smallint(2) P

Descrip Char(40)CveEscuelaForma Smallint (2) P

AreasEstudio Clave Smallint(40) P

Descrip Char(40)AreasProduc Clave Smallint(2) P

Descrip Char(40)Campus Clave Smallint(3) P

Nombre Char (20)Dirección Char (50)Estado Char (30)Municipio Char (40)

Categorias Clave Smallint(3) P

Nombre Char (40)Status BooleanCveEspecialidad Smallint(3)

CentrosTrab Clave Integer (5) P

CveEdificio Integer(5)AreaTrabajo Integer(5)Oficina Integer(5)Nombre char (50)Domicilio Char (80)CodigoPostal Char (5)CveLocalidad Integer (5) P

CompCartaDesc Clave Serial (2)Descrip Char (40)

ConocesInstruc CveInstructor Integer(8) P P

CveAreaEstudio Smallint (4)ConocHab Clave integer (8) P

Descrip Char (50)CveActTrabajo Integer(8) P

CodigoCurso Integer(8) P

CostosAdicionales CveGrupo integer(8) P P

Descrip Char(40) P

Monto Real (7,2)

Apéndice C. Diccionario de datos

C-6

CurrConf Clave Serial(8) P

FechaVigor DateCveNivel Smallint(3)CodigoCurso Integer(8) P

CurrConfPrerr CveCurrConf integer(8) P P

CodigoCurso Integer(8) P P

CurrSind Clave integer(8) P

FechaVigor DateCveCategoria Smallint(3) P

CodigoCurso Integer(8) P

CurrSindPrerr CveCurrSind integer(8) P P

CodigoCurso Integer(8) P P

Cursos Codigo integer(8) P

Nombre Char (50)ObjGral MemoDuracion Real (3,2)NumMaxPartic Smallint(3)NumMinPartic Smallint(3)Creditos Smallint(2)Teorico smallint(3)Practico Smallint(3)FechaRevision dateCostoMaximo real (7,2)CostoEstandar real (7,2)CveModalCapac Smallint(2) P

CveEscuelaForm Smallint(2) P

CveEstCurs Smallint(2) P

CveTipCobertura Smallint(2) P

CveTemGen Integer (5) P

CveTipCurs Smallint(2) P

CveNivEscolar Smallint(2) P

CveNivelTax Smallint(2) P

CveNivelCurs Smallint(2) P

CursTipPersonal CodigoCurso integer(8) P P

CveTipPersonal Smallint(2) P P

Dots Clave Smallint(2) P

Nombre Char (50)EscuelasForm Clave Smallint (2) P

Nombre Char (50)CveJefe Integer(8) P

CveResponsable Integer(8)CveTipoProced Smallint(2) P

Especialidades Clave Smallint(3) P

Nombre Char (50)CveAreaProduc Smallint(2) P

EstActividad Clave Smallint(2) P

Descrip Char(20)EstOrdenTrab Clave Smallint(1) P

Descrip Char(40)EstCurs Clave Smallint(2) P

Descrip Char(20)EstatusAnalis Clave Serial(1) P

Descripcion Char(30)EstatusPrerr Clave Serial(1) P

Descripción Char(30)EstProyCapacit Clave Smallint(2) P

Descrip Char(40)

Apéndice C. Diccionario de datos

C-7

EstatusReq Clave Smallint(2) P

Descrip Char(40)EstudiosRealiz Clave Integer(5) P

CveInstitucion Integer(5) P

CveInstructor Integer(8) P

Nombre Char(40)Descrip Memo

Examenes Clave Integer(8) P

Vigente BooleanComentario MemoCveTipoEvalua Smallint(2) P

ExamenGrupos CveExamen Integer(8) P P

CveGrupo Integer(8) P P

ExamenPregunta CveExamen Integer(8) P P

CvePregunta Integer(8) P P

FuncProcTrab Clave Integer(8) P

Descrip Char(80)FuncProcCategorias CveFuncProcTrab Integer(8) P P

CveCategoria Smallint(3) P P

FuncProcNiveles CveFuncProcTrab Integer(8) P P

CveNivel Smallint(3) P P

GruposDeCurso Clave Integer(8) P

FechaInicio DateFechaTermino DateCodigoCurso Integer(8) P

CveProyCapacit Integer(5) P

GruposRH ClaveRecHumano Integer(8) P P

CveGrupo Integer(8) P P

GruposEquipReal CveGrupo Integer(8) P P

CveEqInven Integer(8) P P

TiempoUso Real(3,2)GruposInstalImprov CveGrupo Integer(8) P P

CveInstaImprov Integer(8) P P

TiempoUso Real(3,2)FechaIni Date(8)FechaFin Date(8)HoraEntrada Time(8)HoraSalida Time(8)

GruposInstalReal CveGrupo Integer(8) P P

CveInstaImprov Integer(8) P P

FechaIni Date(8)FechaFin Date(8)HoraEntrada Time(8)HoraSalida Time(8)

HistPrerrConf Clave Integer(8) P

FechaModif DateCveTipMovimiento Smallint(2) P

CveNivel Smallint(3) P

CodigoCurso Integer(8) P

HistPrerrTBConf CveHistTBConf Integer(8) P P

CodigoCurso Integer(8) P P

HistPrerrTBSind CveHistTBSind Integer(8) P P

CodigoCurso Integer(8) P P

HistInstructor Clave Serial(8) P

CveInstructor Integer(5) P

CodigoCurso Integer(8) P

Fecha Date

Apéndice C. Diccionario de datos

C-8

CveCampus Smallint(3) P

Aprobo BooleanHistParticip Clave Serial(8) P

CveRecHumano Integer(8) P

CodigoCurso Integer(8) P

Fecha DateCveCampus Smallint(3) P

Aprobo BooleanCalificacion Real(2,2)

HistProveedor Clave Serial(8) P

CveProveedor Integer(8) P

CodigoCurso Integer(8) P

Fecha DateCveCampus Smallint(3) P

AproboHistCurrConf Clave Integer(8) P

FechaModif DateCveTipoMovimiento Smallint(2) P

CveNivel Smallint(3) P

CodigoCurso Integer(8) P

HistCurrSind Clave Integer(8) P

FechaModifi DateCveTipoMovimiento Smallint(2) P

CveCategoria Smallint(3) P

CodigoCurso Integer(8) P

HistTroncBasConf Clave Integer(8) P

FechaModif DateCveTipMovimiento Smallint(2) P

CveUnidNegocio Smallint(2) P

CodigoCurso Integer(8) P

HistTroncBasSind Clave Integer(8) P

FechaModifi DateCveTipMovimiento Smallint(2) P

cvEspecialidad Smallint(3) P

CodigoCurso Integer(8) P

HistLabConf CveNivel Smallint(3) P P

CveRecHumano Integer(8) P P

Fecha DateHistLabSind CveCategoria Smallint(3) P P

CveRecHumano Integer(8) P P

Fecha DateInstalImprov Clave Integer(8) P

Descrip Char(40)CveCampus Smallint(3) P

Ubicación Char(50)CveTipInsta Integer(5) P

Capacidad Smallint(2)Costo Real(7,2)

InstitEduc Clave Integer(5) P

Nombre Integer(5)Direccion Char(40)

Instructores Clave Integer(5) P

Status BooleanCveTipProced Smallint(2) P

CveRecurso Integer(8)InstructorCurs CveInstructor Integer(5) P P

CodigoCurso Integer(8) P P

Apéndice C. Diccionario de datos

C-9

Calificacion Real(2,2)InstructorGrupos CveInstructor Integer(5) P P

CveGrupo Integer(8) P P

FechaIni DateFechaFin DateHoraEntrada TimeHoraSalida Time

InvenEq CveEquipo Integer(8) P P

NumSerie Char(20) P

Descrip Char(40)CveCampus Integer(5) P

CveTipProced Smallint(2) P

Costo Real(7,2)Estado BooleanPrivado Boolean

InvenInstalProv CveInvenInsta Integer(8) P P

CveProveedor Integer(5) P P

Localidades Clave Interger(5) P

Nombre Char(80)CveEstFederativo Smallint(2) P

MaterialPartic Clave Integer(5) P

Descrip Char(80)CostoUnit Real(9,2)

MaterialDidac Clave Smallint(2) P

Descrip Char(80)MatDidacTemas CveMaterialDidac Smallint P P

CveTema Integer P P

Descrip Char(50)RecomendDiseño Memo

ModalCapac Clave Smallint(2) P

Descrip Char(40)NecMaterialCurs CveMaterialPartic Integer(5) P P

CodigoCurso Integer(8) P P

CantPorPartic Smallint(3)Niveles Clave Smallint(3) P

Descrip Char(80)CveNivJerarq Smallint(2) P

CveUnidNegocio Smallint(3) P

NivEscolar Clave Smallint(2) P

Descripcion Char(40)NivelCurs Clave Smallint(2) P

Descrip Char(20)NivelesITM Clave Smallint(3) P

Descrip Char(50)ClaveAreaITM Smallint(3) P

NivJerarq Clave Smallint(2) P

Descrip Char(40)ObjetivosPart Clave Integer(8) P

Descrip Char(80)ObjetivosPartCurs CveObjetivosPart Integer(8) P P

CodigoCurso Integer(8) P P

OpcionesResp CvePregunta Integer(8) P P

NumRespuesta Smallint(2) P

Descrip Char(50)OrdenesServ Folio Integer(8) P

Concepto Char(80)Fecha Date

Apéndice C. Diccionario de datos

C-10

CveCoord Integer(8) P

CveProveed Integer(8) P

CveGrupo Integer(8) P

OrdenesViat Folio Integer(8) P

Fecha DateDias Integer(4)Justificacion Char(50)CveOrigen Integer(8) P

CveDestino Integer(8) P

CveCoord Integer(8) P

CveProveed Integer(8) P

CveInstructor Integer(8) P

CveGrupo Integer(8) P

Estatus Smallint(2)OrigenRequerim Clave Smallint(1) P

Descrip Char(40)PerCritUniNeg Clave Integer(8) P

FechaIni DateFechaFin DateCveUniNeg Smallint(2)

PerCitEspec Clave Integer(8) P

FechaIni DateFechaFin DateCveEspec Integer(5) P

PerIndispEquip Clave Integer(8) P

FechaIni DateFechaFin Date P

CveEq Integer(8)PerIndispInstal Clave Integer(8) P

FechaIni DateFechaFin Date P

CveInstal Integer(8)PerIndispInstr Clave Integer(8) P

FechaIni DateFechaFin Date P

CveInstruc Integer(8)PerIndispProv Clave Integer(8) P

FechaIni DateFechaFin Date P

CveProvee Integer(8)PerIndispRH Clave Integer(8) P

FechaIni DateFechaFin Date P

CveRH Integer(8)Planteles Clave Integer(5) P

Nombre Char(30)Direccion Char(50)CveEstFederativo Smallint(2) P

CveLocalidad Integer(5) P

CveCampus Integer(5) P

Preguntas Clave Integer(8) P

DescPregunta Char(80)NumRespuesta Smallint(2)CveTipPregunta Smallint(2) P

CveObjetivoPart Integer(8) P

Proveedores Clave Integer(5) P

Nombre Char(50)

Apéndice C. Diccionario de datos

C-11

Responsable Char(50)CveTipFiscal Smallint(1)Domicilio Char(80)CodigoPostal Char(5)RFC Char(15)Telefonos Char(30)Fax Char(30)Estatus BooleanCveLocalidad Integer(5) P

ProveedorCurs CodigoCurso Integer(8)CveProveedor Integer(5)Costo Real(9,2)CursosSimultaneos Smallint(2)Fecha DateVigencia DateCalificacion Real(2,2)

ProveedorGrupos CveGrupo Integer(8) P

CveProveedor Integer(5) P

Folio Integer(8)Concepto Char(80)Fecha DateCostosCveCoord Integer(8) P

CveEstOrdenTrab Smallint(1) P

ProvTipoProv CveProveedor Integer (5) P P

CveTipProveedor Smallint (2) P P

ProyCapacit Clave Interger (5) P P

Nombre Char (80)FechaInicial Date (8)FechaFinal Date (8)FechaNot Date (8)FechaRegistro Date(8)FechaImp Date (8)Ponderacion smallint (2)CveEstProy SmallInt (2)Presupuesto Money (9,2)CveRHITM Integer (8)CveProyCapacit Integer (5)CveTipProy SmallInt (3)

ProyCentrosTrab CveCentroTrab Integer(5) P P

CveProyCapacit Integer (5)ProyCenTrabNiv Clave Integer (8) P

CveNivel Smallint (3) P

CantPersonal Smallint (3)Estatus Char (2)CveCentroTrab Integer (5) P

CveProyCapacit Integer (5) P

ProyCenTrabCateg Clave Integer (8) P

CveCategoria SmallInt (3) P

CantPersonal SmallInt (3)Estatus Char (2)CveCentroTrab Integer (5) P

CveProyCapacit Integer (5) P

ProyProveedor CveProveedor Integer (8) P P

CveProyCapacit Integer (5) P P

ProLideres CveRH Integer (8) P P

CveProyCapacit Integer (5) P P

Apéndice C. Diccionario de datos

C-12

ProyResp CveRHITM Integer (8) P P

CveProyCapacit Integer (5) P P

RecHumanosITM Clave Integer (8) P P

Nombre Char (80)FechaIngreso DateDomicilio Char (80)Telefono Char (30)Fax Char (30)Estatus Char (1)CveNivelITM Smallint (3)CveEdificioITM Smallint (2)

RecHumanos Clave Integer (8) P P

Nombre Char (50)FechaNacimiento DateFechaIngreso DateStatus Char (1)RFC Char (15)CveTipPersonal Smallint (2)CveNivEscolar Smallint (2)CveNivelCategoria Smallint (3)CveCentroTrab Integer (8)CveJefeTelefonos char (30)Fax char (30)

Requerimientos Clave integer (8) P P

Descrip Char (80)FechaReg DatePonderacion Integer (2)CveEstatusReq SmallInt (2)CveOrigenReq SmallInt (1)CveProyecto Integer (5)ResultadoEsperado Memo

ReqCategorias CveRequerimiento Interger (8) P P

CveCategoria Smallint (3) P P

CantPersonal SmallInt (3)ReqCursos CveRequerimiento Integer (8) P P

CodigoCurso Integer (8) P P

ReqCursosRH CveRequerimiento Integer (8) P P

CodigoCurso Integer (8) P P

CveRH Integer (8) P P

CveEstAnalis SmallInt (1) P

SolCurricular BooleanPctjCurric SmallInt (3)CveEstPrerr SmallInt (3) P

Justificacion Char (50)CveRHITM Integer (8) P

ReqCursosRHPrerr CveRequerimiento integer(8) P P

CodigoCurso integer(8) P P

CveRH integer(8) P P

Curso¨rerrequisito Integer (8)CursoPadre Integer(8)

ReqNiveles CveRequerimiento Integer(8) P P

CveNivel SmallInt (3) P P

CantPersonal SmallInt(3)ReqEqCurs CveTipEquipo Integer(5) P P

CodigoCurso Integer(8) P P

CantPorGrupo SmallInt(3)

Apéndice C. Diccionario de datos

C-13

HoraInicial time(8)HoraFinal Time(8)

ReqInstalCurs CveTipInstalacion Integer(5) P P

CodigoCurso Integer(8) P P

HoraInicial Time(8)HoraFinal Time(8)

ResultEvalInstr Calificacion Real(2,2)CveGrupo Integer(8) P P

CveInstructor Integer(5) P P

CveTipEvalua SmallInt(2) P

ResultEValParticip Calificacion Real(2,2)CveGrupo Integer(8) P P

CveReqHumano Integer(8) P P

CveTipEvalua SmallInt(2)ResultEvalProv Calificacion Real(2,2)

CveGrupo Integer(8) P P

CveProveedor Integer(5) P P

CveTipEvalua SmallInt(2)SoliCapacit Clave Integer(8) P

CodCurso Integer(8) P

CveProyCapacit Integer(5) P

CveCampus SmallInt(3) P

SoliCapacitCateg CveSoli Integer(8) P P

CveCategoria SmallInt(3) P P

SoliCapacitniv CveSoli Integer(8) P P

CveNivel SmallInt(3) P P

SoliRH CveSoli Integer(8) P P

CveRH Integer(8) P P

CveSoliOrigen Integer(8)FechaSoli Date(8)Ponderacion Real(2,2)RazSocial SmallInt(3)AplConoci SmallInt(3)ConseqEq SmallInt(3)ConseqSeg SmallInt(3)ConseqSer SmallInt(3)FrecSoli SmallInt(3)NomEqEmpl Char(50)CveEstAnalis SmallInt(1) P

SolCurricular BoleanPctjCurric SmallInt(3)CveEstPrerr SmallInt(2) P

Justificacion Char(50)CveRHITM Integer(8) P

SoliRHPrerr CveSoli Integer(8) P P

CveRH Integer(8) P P

CodCurso Integer(8) P

Estatus Char(1)Sots Clave SmallInt(2) P

Nombre Char(50)CveDot SmallInt(2)

SubtemasDeCurso Clave Serial(8) P

Decrip Char(80)RecomendDiseño MemoCveTema Integer(8)

TecnologiasTemas CveTecnolEducat SmallInt(2) P P

CveTema Integer(8) P P

Apéndice C. Diccionario de datos

C-14

Justificacion char(80)TecnolEducat Clave SmallInt(2) P

Descrip Char(40)TemasDeCurso Clave Integer(8) P

Descrip Char(80)TiempoTema SmallInt(2)CveObjetivoPart Integer(8) P

TemasMetInstrucc CveMetInstrucc Integer(2) P P

CveTema Integer(8) P P

TemasGen Clave Integer(5)Descrip Char(80)CveAreaConoc Integer(5) P

TipCobertura Clave SmallInt(2) P

Descrip Char(20)TipCurs Clave SmallInt(2) P

Descrip Char(20)TipEquipos Clave Integer(5) P

Descrip Char(50)TipEvalua Clave SmallInt(2) P

Descrip Char(50)TipInstalaciones Clave Integer(5) P

Descrip Char(80)TipInstructores Clave SmallInt(2) P

Descrip Char(20)TipMovimiento Clave SmallInt(2) P

Descrip Char(20)TipParticip Clave SmallInt(2) P

Descrip Char(20)TipPersonal Clave SmallInt(2) P

Descrip Char(20)TipPreguntas Clave SmallInt(2) P

Descrip Char(20)TipProced Clave SmallInt(2) P

Descrip Char(20)Tabla Char(20)

TipProveedor Clave SmallInt(2) P

Descrip Char(40)TipTpoyectos Clave SmallInt(2) P

Descrip Char(40)TroncoBasConf Clave Seral(8) P

FechaVigor DateCveUnidNegocio SmallInt(2) P

CodigoCurso Integer(8)TroncoBasconfPrerr CveTroncBasConf Integer(8) P P

CodigoCurso Integer(8) P P

TroncoBasSind Clave Integer(8) P

FechaVigor DateCveEspecialidad SmallInt(3) P

CodigoCurso Integer(8) P

TroncBasSindPrerr CveTroncBasSind Integer(8) P P

CodigoCurso Integer(8) P P

UnidNegocio Clave SmallInt(2) P

Descrip Char(40)

D-1

• SIAM J. COMPUT, Vol. 5, No. 4, December 1976 “ON THE COMPLEXITY OF TIMETABLEAND MULTICOMMODITY FLOW PROBLEMS”. E.Even, A.Itati, A.Shamir

• Aho, Alfred V.; Hopcroft, John E., y Ullman, Jeffrey D., Estructura de datos y algoritmos, Sitesa,Addison-Wesley, 1988

• Wirth, Niklaus, Algoritmos y estructura de datos, Prentice-Hall, 1987

Bibliografía