CoolFace
Apppublic

yonicav/modeloptimiz

sourceHugging Faceupdated 3y agoView on Hugging Face
0likes
app.py418 linesDownload Raw Back to root
1# STREAMLIT2import streamlit as st3# DASHBOARD4import plotly.express as px5import random6from wordcloud import WordCloud7 8# PANDAS9import pandas as pd10# PYOMO11import pyomo.environ as pyo12from pyomo.environ import *13from pyomo.opt import SolverFactory14# GOOGLE AUTH15from google.oauth2 import service_account16# GSPREAD17import gspread as gs18# CURRENCY19import locale20 21### CONFIGS:22locale.setlocale(locale.LC_ALL, 'pt_BR')23st.set_page_config(24     page_title="Prescritive Analytics / Análise de Sugestão",25     page_icon="random",26     layout="wide",27     initial_sidebar_state="expanded",28)29 30### ACESSO AS PLANILHAS DO GOOGLE: 31##GRACIAS![https://medium.com/pyladiesbh/gspread-trabalhando-com-o-google-sheets-f12e53ed1346]32 33def login():34    '''35    FAZ O LOGIN NO GOOGLE DOCS USANDO CREDENCIAIS GCP36    '''37    scopes = ['https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive']38    credentials = service_account.Credentials.from_service_account_info(st.secrets["gcp_service_account"])39    scoped_credentials = credentials.with_scopes(scopes)40    gc = gs.authorize(scoped_credentials)41    return gc42 43def df_to_spreadsheet(spreadsheets,aba, df):44    '''45    Carrega um Dataframe em uma planilha do GDocs46    spreadsheets = nome da planilha47    aba = Aba do excel48    df  = Dataframe49    '''50    gc = login()51    spreadsheet = gc.open(spreadsheets)52    wks = spreadsheet.worksheet(aba)53    wks.clear()54    data_list = df.values.tolist()55    wks.insert_rows(data_list)56    #header = ["Maq","Prod","Cliente","QtdProduction","Days","VALIDAÇAO","Custo_por_Ton","Capacidade_Max_por_dia","Valor_Frete","QtdContainers","ValorDeliveryTotal","Valor Total de Produção SEM FRETE","Model OF"]57    wks.insert_row(df.columns.tolist(), 1)58 59def df_from_spreadsheet(spreadsheets,aba):60    '''61    Carrega um Dataframe de uma planilha do GDocs62    spreadsheets = nome da planilha63    aba = Aba do excel64    retorna: Dataframe previamente formatado65    '''66    gc = login()67    spreadsheet = gc.open(spreadsheets)68    wks = spreadsheet.worksheet(aba)69    data = wks.get_all_values()70    headers = data.pop(0)71    df = pd.DataFrame(data, columns=headers)72    df = df.set_index(aba)73    df.index.name = None74    df = df.apply(lambda x: x.str.replace(',','.'))75    for column in df.columns:76        df[column] = pd.to_numeric(df[column])77    return df78 79def roda_algoritmo(container, dias):80    '''81    roda o algoritmo de sugestao82    container = quantidade de itens no pacote(frete)83    dias = quantidade de dias para fabricacao da demanda84    '''85    ### CAPACIDADE86    df_capacidade = df_from_spreadsheet("pyomo","CAPACIDADE")87    df_capacidade = df_capacidade.fillna(1)88    ### CUSTO89    df_custo = df_from_spreadsheet("pyomo","CUSTO")90    df_custo = df_custo.fillna(10000000)91    ### DEMANDA92    df_demanda = df_from_spreadsheet("pyomo","DEMANDA")93    df_demanda = df_demanda.fillna(0)94    ### FRETE95    df_frete = df_from_spreadsheet("pyomo","FRETE")96    df_frete = df_frete.fillna(0)97    df_frete = df_frete.T98 99    ### ALGORITMO DE OTIMIZAÇÃO:100    model = ConcreteModel()101    model.i = df_custo.keys()    ## i=Machines102    model.j = df_demanda.index   ## j=Products103    model.h = df_demanda.keys()  ## h=Customers104 105    model.x = Var(model.i, model.j,model.h, within=NonNegativeReals)                    ### Quantity106    model.y = Var(model.i, model.j,model.h, bounds=(0,dias),  within=NonNegativeReals)  ### Days107    model.OF = Var(within=Reals)                  ### Total production Cost108    model.P = Var(model.i,within=Reals)           ### Production by Machin  109    def rule_C0(model, i):110        return sum(model.x[i,j,h] for j in model.j for h in model.h) == model.P[i]111    model.C0 = Constraint(model.i, rule=rule_C0)112    model.C1 = ConstraintList()113    for j in model.j:114        for h in model.h:115            if df_demanda.loc[j,h] > 0:116                model.C1.add(sum(model.x[i,j,h] for i in model.i) == (df_demanda.loc[j,h] ) )117    model.C2 = ConstraintList()118    for i in model.i:119        for j in model.j:120            for h in model.h:121                model.C2.add(model.x[i,j,h] == (df_capacidade.loc[j,i] * model.y[i,j,h]) )122    model.C01 = ConstraintList() # DIAS_TOTAL123    for i in model.i:124        model.C01.add(sum(model.y[i,j,h] for h in model.h for j in model.j) <= dias)125 126    def rule_OF(model):                          127        return model.OF == sum(128            (model.x[i,j,h] * df_custo.loc[j,i])129            +130            (131                (model.x[i,j,h] / container) 132                * 133                df_frete.loc[i,h]) for i in model.i for j in model.j for h in model.h)134    model.C3 = Constraint(rule=rule_OF)135    model.obj1 = Objective(expr=model.OF, sense=minimize)136    solver = SolverFactory('glpk')137    results = solver.solve(model, tee=True)138    print(results)139    print("RESULTADO:", results.solver.termination_condition)140    vOF = value(model.OF)141    #print("OF= ",vOF )142    columns1=('Maq','Prod', 'Cliente', 'QtdProduction', 'Days',"VALIDAÇAO","Custo_por_Ton", "Capacidade_Max_por_dia", "Valor_Frete", "QtdContainers", "ValorDeliveryTotal", "Valor Total de Produção SEM FRETE", 'Model OF')143    df = pd.DataFrame(columns = columns1)144    for i in model.i:145        for j in model.j:146            for h in model.h:147                v1 = value(model.x[i,j,h])148                v2 = value(model.y[i,j,h]) 149                v3 = value(df_custo.loc[j,i])150                v4 = value(df_capacidade.loc[j,i])151                v41 = value(df_frete.loc[i,h])152                v5  = ( v1 / container) 153                v6 = ( v1 / container) * df_frete.loc[i,h]154                v7 = (v1 * v3)155                v8 = (v1 * v3) + v6 156                if v1>0:157                    #model.x[i,j,h] * custo[i][j]158                    #print (i, j, h, v1, v2, v3,v4)159                    df = df.append(pd.DataFrame({"Maq":[i], "Prod":[j], "Cliente":[h], "QtdProduction":[v1], "Days":[v2], "Custo_por_Ton": v3,160            "Capacidade_Max_por_dia": v4,"Valor_Frete": v41, "QtdContainers" : v5, "ValorDeliveryTotal" : v6, "Valor Total de Produção SEM FRETE": v7, "Model OF": v8}))161    return(df,vOF)162 163 164 165#### UX:166def main():167    st.title("Prescritive Analytics / Análise de Sugestão / Pesquisa Operacional")168    menu = ["HOME", "I - Linha de Produção Simples", "II - Linha de Produção Elaborada", "III - Carteira de Investimentos", "SOBRE"]169    choice = st.sidebar.selectbox("Menu", menu)170 171 172#### HOME:173    if choice == "HOME":174        st.markdown('''175                    O objetivo é demonstrar de forma prática os conceitos em torno das soluções que utilizam ferramentas de uma área da 176                    **Inteligência Artificial** chamada de **Análise de Sugestão**, utilizada para tomada de decisão onde existen grandes quantidade de opções.177                    ''')178        with st.expander("Conceitos:"):179                   st.markdown(180                  '''181                    A **Análise de Sugestão/Recomendação/Prescritiva** é utilizada para obtenção da melhor solução de todas as soluções viáveis 182                   a fim de atingir um objetivo levando em consideração algumas restrições. Um problema de otimização consiste em *maximizar* 183                   ou *minimizar* uma função objetivo, e encontrar a melhor solução de todas as soluções viáveis.184 185                   A tecnologia de **Análise Prescritiva** recomenda ações com base nos resultados desejados, levando em consideração cenários 186                   específicos, recursos e conhecimento de eventos passados e atuais. Esses insights podem ajudar sua organização à tomar 187                   melhores decisões e ter maior controle dos resultados  os negócios. A **Análise Prescritiva** fornece às organizações  188                   recomendações sobre as ações ideais para atingir os objetivos de negócios, como satisfação do cliente, lucros e economia 189                   de custos.190 191                   As soluções de **Análise Prescritiva** usam tecnologia de otimização para resolver decisões complexas com milhões de variáveis 192                   de decisão, restrições e regulagens. Organizações em dos os setores usam análises prescritivas para uma variedade de casos193                   de uso que abrangem o planejamento estratégico, atividades operacionais e táticas. A **Análise Prescritiva** é a próxima etapa 194                   no caminho para ações baseadas em  insights. Ele cria valor por meio da  sinergia com a **Análise PREDITIVA**, que analisa os 195                   dados do passado para prever resultados futuros. A **Análise Prescritiva** leva esse insight para o próximo nível, sugerindo a 196                   maneira ideal de lidar com essa situação futura. Organizações que podem agir rapidamente em condições dinâmicas e tomar decisões 197                   superiores em ambientes incertos ganham uma forte vantagem competitiva. 198                   ''' )199        200        st.markdown("No Menu tem os seguintes exemplos:")201        st.markdown("   Linha de Produção Simples:  \n Objetivo: Exemplo simples de uma padaria para demostrar o potencial de soluções que utilizam PO para tomada de decisão")202        st.markdown("   Linha de Produção Elaborada:  \n Objetivo: Exemplo mais complexo, para Minimizar o custo de produção de vários produtos.")203        st.markdown("   Carteira de Investimentos:  \n Objetivo: Demonstrar o potencial de soluções que utilizam PO para tomada de decisão sugerindo ações para montar carteira de investimentos.")204        205        # WORDCLOUD206        # FUNCAO PARA DEFINICAO DA COR:207        def grey_color_func(word, font_size, position, orientation, random_state=None,**kwargs):208            return "hsl(0, 0%%, %d%%)" % random.randint(30, 100)209        text = '"Pesquisa Operacional","Engenharia de Produção","Simulação Estocástica","Otimização Combinatória","Optimization","Prescriptive Analytics","Operations Research","Mathematical Optimization for Business Problems"'210        # CRIA A IMAGEM COMO WORDCLOUD211        wordcloud = WordCloud(background_color='black', max_font_size = 40,collocations=False).generate(text)212        #change the color setting213        wordcloud.recolor(color_func = grey_color_func)214        # plot215        fig = px.imshow(wordcloud)216        fig.update_layout(coloraxis_showscale=False)217        fig.update_layout(width=1300, height=800)218        fig.update_xaxes(showticklabels=False)219        fig.update_yaxes(showticklabels=False)220        st.plotly_chart(fig) 221 222 223#### MIX DE PRODUÇÃO - SIMPLES:224    if choice == "I - Linha de Produção Simples":225        st.subheader("Produção de BOLOS e TORTAS em uma Padaria")226        st.write('''227        Quantos Bolos e Tortas devem ser feitos para maximizar o lucro desses dois produtos sob determinadas condições?228        ''')229        image = "https://bimbon-assets.s3.amazonaws.com/ckeditor/picture/data/52701fe1f369336f5300063f/content_Przystanek_bimbon03.jpg"230        st.image(image, width=370,)231        with st.expander("Regras de Negócio:"):232            st.markdown(233                  '''234                  Uma padaria faz bolos e tortas todos os periodos. Há: 1 forno, 2 padeiros, 1 empacotador que trabalha apenas 22 periodos. 235                  O bolo requer o uso do forno por 1 periodo e a torta requer 0,5 periodo. Cada padeiro precisa trabalhar para o bolo 0,5 pariodos e para torta 2 periodos. 236                  O empacotador precisa trabalhar para o bolo 1 periodo e a torta 0,5 periodo. O lucro em cada bolo é R$ 15,00 e o lucro em cada torta é R$ 12,00. 237                   238                Exemplo de valores:239                    - 1 FORNO240                    - 2 PADEIRO241                    - 1 EMPACOTADOR que trabala 22 periodos.242                Tempo de Preparo:                    243                    - FORNO      = BOLO 1 periodo   + TORTA 0.5 periodo  <=30 periodos244                    - PADEIRO    = BOLO 0.5 periodo + TORTA 2.0 periodo  <=60 periodos ( 2 padeiros)245                    - EMPACOTAOR = BOLO 1.O periodo + TORTA 0.5 periodo  <=22 periodos246                    - LUCRO BOLO = 15247                    - LUCRO TORTA = 12248        Objetivo: Maximizar os Lucros com os dois produtos na linha de produção249                  ''')250 251        with st.expander("Quantidade de produtos já vendidas dos produtos:"):252 253            col1, col2,col3 = st.columns(3)254            with col1:255                minBOLO = st.number_input('BOLO - Qtd min :', help='Fabricação mimima de Bolo - já demandada' , value=0)256            with col2:257                minTORTA = st.number_input('TORTA - Qtd min:',  help='Fabricação mimima de Bolo - já demandada' , value=0)          258        with st.expander("Valor de lucro  dos produtos:"):259            st.write("LUCRO:")260            col1, col2,col3 = st.columns(3)261            with col1:262                LucroBOLO = st.number_input('BOLO - Margem de Lucro:', help='Margem de Lucro do Bolo' , value=15.00, format="%.2f")263            with col2:264                LucroTORTA = st.number_input('TORTA - Margem de Lucro:',  help='Margem de Lucro do Torta' , value=12.00, format="%.2f")265        with st.expander("Restrições/Condições que precisam ser respeitadas:"):266            st.write("Capacidade - BOLO:")267            col1, col2, col3 = st.columns(3)268            with col1:269                pFORNO = st.number_input('FORNO - Capacidade:', help='Capacidade máxima de tempo do FORNO em periodos' , value=30)270            with col2:271                pPADEIRO = st.number_input('PADEIRO - Capacidade:', help='Capacidade máxima de tempo do PADEIRO em periodos:', value=60)272            with col3:273                pEMPACOTADOR = st.number_input('EMPACOTADOR - Capacidade:', help='Capacidade máxima de tempo do EMPACOTADOR em periodos:', value=22)274            275            st.write("Tempo de preparo - BOLO:")276            col1, col2, col3 = st.columns(3)277            with col1:278                tFORNOBOLO = st.number_input('BOLO/FORNO - Tempo:', help='Tempo de preparo em periodos' ,  value=1.00, format="%.2f")279            with col2:280                tPADEIROBOLO = st.number_input('BOLO/PADEIRO - Tempo:', help='Tempo de preparo em periodos:',  value=0.50, format="%.2f")281            with col3:282                tEMPACOTADORBOLO = st.number_input('BOLO/EMPACOTADOR - Tempo:', help='Tempo de preparo em periodos:',  value=1.00, format="%.2f")283            284            st.write("Tempo de preparo - TORTA:")285            col1, col2, col3 = st.columns(3)286            with col1:287                tFORNOTORTA = st.number_input('TORTA/FORNO - Tempo:', help='Tempo de preparo em periodos' ,  value=0.50, format="%.2f")288            with col2:289                tPADEIROTORTA = st.number_input('TORTA/PADEIRO - Tempo:', help='Tempo de preparo em periodos:',  value=2.00, format="%.2f")290            with col3:291                tEMPACOTADORTORTA = st.number_input('TORTA/EMPACOTADOR - Tempo:', help='Tempo de preparo em periodos:',  value=0.50, format="%.2f")292 293 294        if st.button("Enviar"):295            model = ConcreteModel()296            ##### dual297            model.dual = Suffix(direction=Suffix.IMPORT)298 299            ## VARIAVEIS DE DECISAO: ---------------------------------300            BOLO  = model.BOLO = pyo.Var(within=PositiveReals)301            TORTA = model.TORTA = pyo.Var(within=PositiveReals)302 303            ## CONSTRAINTS: ---------------------------------304            model.FORNO =       pyo.Constraint(expr= tFORNOBOLO * BOLO + tFORNOTORTA * TORTA <= pFORNO)305            model.PADEIRO =     pyo.Constraint(expr= tPADEIROBOLO * BOLO + tPADEIROTORTA * TORTA <= pPADEIRO)306            model.EMPACOTADOR = pyo.Constraint(expr= tEMPACOTADORBOLO *BOLO + tEMPACOTADORTORTA * TORTA <= pEMPACOTADOR)307            model.minBOLO =     pyo.Constraint(expr= BOLO >= minBOLO)308            model.minTORTA =    pyo.Constraint(expr= TORTA >= minTORTA)309 310            model.obj = pyo.Objective(expr= LucroBOLO*BOLO +LucroTORTA*TORTA, sense=maximize)311            model.pprint()312            313            solver = SolverFactory('glpk')314            results = solver.solve(model, tee=True)315            st.write("A solução encontrada é: ", results.solver.termination_condition)316            with st.expander(" DUAL:"):317                st.write("Capacidade semelhantes que daram o mesmo resulado:")318                for c in [model.FORNO, model.PADEIRO, model.EMPACOTADOR]:319                    st.write(c, c(), c.lslack(), c.uslack(), model.dual[c])320 321            # print(results)322            st.write("Para obter o maior lucro a sugestão de fábricação é:")323            st.write("BOLO:",pyo.value(BOLO),"TORTA é:",pyo.value(TORTA) )324            st.write("LUCRO esperado será:", pyo.value(model.obj))325            with st.expander("Explicação:"):326                st.write( '(', LucroBOLO,' X ', pyo.value(BOLO) , ") + (" , LucroTORTA,' X ',pyo.value(TORTA) ,' = ', pyo.value(model.obj),')')327 328 329#### MIX DE PRODUÇÃO - ELABORADO:330    elif choice == "II - Linha de Produção Elaborada":331        st.subheader("Linha de Produção Elaborada") 332        with st.expander("Objetivo:"):333            st.markdown("Minimizar o custo de produção incluindo o valor do frete, que é um valor fixo por capacidade maxima por pacote. \n \n \334- Quantidade de produção x Custo de produção + Valor do Frete por embalagem.  \n  \335- A demanda precisa ser igual a quantidade que deverá ser produzida  \n \336- A capacidade de produção diária precisa ser respeitada")337            st.write("Resultado: É quantidade de dias necessária, bem como a melhor alocação das máquinas, para minimizar o custo de produção da demanda" )338 339        st.write("Preencha os valores na planilha conforme abaixo:")340        col1, col2, col3 = st.columns(3)341        with col1:342            st.write("**CAPACIDADE**: Produção em cada Máquina em 1 periodo de tempo")343            st.write("**CUSTO**: Produção em cada uma Máquina em 1 periodo de tempo")344        with col2:    345            st.write("**DEMANDA**: Demanda de produtos pelos Clientes")346            st.write("**FRETE**: Valor para envio da Quantidade do Produto A pela Máquina X")347        348        col1, col2, col3 = st.columns(3)349        with col1:350            st_dias = st.number_input('Periodo:', help='Periodo para atingir a demanda. Em dias, por exemplo' , value=30)351        with col2:352             st_containers = st.number_input('Itens por pacote(frete):', help='Quantidade maxima de itens por pacote(frete):',value=2.50, format="%.2f")353        354        # embed streamlit docs in a streamlit app355        import streamlit.components.v1 as components356        components.iframe(st.secrets["private_gsheets_url"],width=1500, height=800)357        358        if st.button("Enviar"):359            with st.spinner('Processando...'):360                ## cria o dataframe com o resultado da sugestao:361                df,vOF =  roda_algoritmo(st_containers, st_dias)362                st.success('Feito!')363            364            st.write("Custo total para fabricação da Demanda - aba Resultado:", locale.currency(vOF,grouping=True))365            st.dataframe(df)366            df.fillna('', inplace=True)367            df_to_spreadsheet("pyomo","RESULTADO",df)368 369            #### GRÁFICOS:370            fig = px.bar(df.groupby(['Maq']).agg({'Days': 'sum'}))371            fig.update_layout(title = "Utilização das Maquinas",width=1500, height=800)372            st.plotly_chart(fig)373            fig = px.bar(df, x='Maq', y='QtdProduction', color='Cliente', barmode ='stack')374            fig.update_layout(title = "Qtd de Produção por Máquina",width=1500, height=800)375            st.plotly_chart(fig)376            fig = px.bar(df, x='Maq', y='Days', color='Cliente', barmode ='stack')377            fig.update_layout(title = "Tempo de Producão por Cliente",width=1500, height=800)378            st.plotly_chart(fig)379            fig = px.bar(df, x='Maq', y='Days', color='Prod', barmode   ='stack')380            fig.update_layout(title = "Tempo de Producão por Produto",width=1500, height=800)381            st.plotly_chart(fig)    382 383 384            385#### CARTEIRA DE INVESTIMENTOS:    386    elif choice == "III - Carteira de Investimentos":387        st.subheader("Carteira de Investimentos... em contrução.")    388 389 390 391 392 393 394#### SOBRE:    395    elif choice == "SOBRE":396        col1, col2, col3, col4= st.columns(4)397        with col1:398            with st.expander("Fonte"):399                st.write(400                        """401                        Livros: 402                        - Pyomo Documentation - Release 5.7.1.dev0  - Aug 17, 2020 403                        - Pesquisa Operacional para Cursos de Engenharia - Patrícia Belfiore & Luiz Paulo Fávero 404                        - ...405                        """  )406       407        st.info("Desenvolvido por Paulo Cristiano Klein, com ajuda de muitos amigos!\n"408                "Mantido por [Paulo Klein](https://www.linkedin.com/in/pauloklein/). "409                "Me visite também em https://github.com/Tianoklein")410        if st.button("OBRIGADO!!!"):411            st.balloons()412        html_temp = '''<a href="mailto:tianoklein@hotmail.com?subject=Streamlit DO/PO Parse&body=Tenho uma sugestão: ">  Duvidas, criticas e sugestões </a>'''413        import streamlit.components.v1 as components414        components.html(html_temp)415 416 417if __name__ == '__main__':418    main()